github.com/haagen/force@v0.19.6-0.20140911230915-22addd930b34/fetch.go (about) 1 package main 2 3 import ( 4 "archive/zip" 5 "encoding/json" 6 "encoding/xml" 7 "fmt" 8 "io" 9 "io/ioutil" 10 "log" 11 "os" 12 "path/filepath" 13 "strings" 14 ) 15 16 var cmdFetch = &Command{ 17 Run: runFetch, 18 Usage: "fetch <type> [<artifact name>] [options]", 19 Short: "Export specified artifact(s) to a local directory", 20 Long: ` 21 Export specified artifact(s) to a local directory. Use "package" type to retrieve an unmanaged package. 22 23 Examples 24 25 force fetch CustomObject Book__c Author__c 26 27 force fetch CustomObject 28 29 force fetch Aura [<entity name>] 30 31 force fetch package MyPackagedApp 32 33 options 34 -u, --unpack 35 will expand static resources if type is StaticResource 36 37 example: force fetch StaticResource MyResource --unpack 38 39 `, 40 } 41 42 func runFetchAura(cmd *Command, entityname string) { 43 force, _ := ActiveForce() 44 45 var bundles AuraDefinitionBundleResult 46 var definitions AuraDefinitionBundleResult 47 var err error 48 49 if entityname == "" { 50 bundles, definitions, err = force.GetAuraBundles() 51 if err != nil { 52 ErrorAndExit(err.Error()) 53 } 54 } else { 55 bundles, definitions, err = force.GetAuraBundle(entityname) 56 if err != nil { 57 ErrorAndExit(err.Error()) 58 } 59 } 60 61 var bundleMap = make(map[string]string) 62 var bundleRecords = bundles.Records 63 for _, bundle := range bundleRecords { 64 id := fmt.Sprintf("%s", bundle["Id"]) 65 bundleMap[id] = fmt.Sprintf("%s", bundle["DeveloperName"]) 66 } 67 68 var defRecords = definitions.Records 69 wd, _ := os.Getwd() 70 root := filepath.Join(wd, "metadata", "aurabundles") 71 72 if err := os.MkdirAll(root, 0755); err != nil { 73 ErrorAndExit(err.Error()) 74 } 75 76 for key, value := range bundleMap { 77 if err := os.MkdirAll(filepath.Join(root, value), 0755); err != nil { 78 ErrorAndExit(err.Error()) 79 } 80 81 var bundleManifest = BundleManifest{} 82 bundleManifest.Name = value 83 bundleManifest.Files = []ComponentFile{} 84 bundleManifest.Id = key 85 86 for _, def := range defRecords { 87 var did = fmt.Sprintf("%s", def["AuraDefinitionBundleId"]) 88 if did == key { 89 var entity = fmt.Sprintf("%s%s", value, strings.Title(strings.ToLower(fmt.Sprintf("%s", def["DefType"])))) 90 switch fmt.Sprintf("%s", def["DefType"]) { 91 case "COMPONENT": 92 entity += ".cmp" 93 case "APPLICATION": 94 entity += ".app" 95 case "EVENT": 96 entity += ".evt" 97 case "STYLE": 98 entity += ".css" 99 default: 100 entity += ".js" 101 } 102 var componentFile = ComponentFile{filepath.Join(root, value, entity), fmt.Sprintf("%s", def["Id"])} 103 bundleManifest.Files = append(bundleManifest.Files, componentFile) 104 ioutil.WriteFile(filepath.Join(root, value, entity), []byte(fmt.Sprintf("%s", def["Source"])), 0644) 105 } 106 } 107 bmBody, _ := json.Marshal(bundleManifest) 108 ioutil.WriteFile(filepath.Join(root, value, ".manifest"), bmBody, 0644) 109 } 110 return 111 } 112 113 func runFetch(cmd *Command, args []string) { 114 wd, _ := os.Getwd() 115 root := filepath.Join(wd, "metadata") 116 if len(args) < 1 { 117 ErrorAndExit("must specify object type and/or object name") 118 } 119 120 force, _ := ActiveForce() 121 var files ForceMetadataFiles 122 var err error 123 var expandResources bool = false 124 125 artifactType := args[0] 126 if strings.ToLower(artifactType) == "aura" { 127 if len(args) == 2 { 128 runFetchAura(cmd, args[1]) 129 } else { 130 runFetchAura(cmd, "") 131 } 132 } else if artifactType == "package" { 133 files, err = force.Metadata.RetrievePackage(args[1]) 134 if err != nil { 135 ErrorAndExit(err.Error()) 136 } 137 for artifactNames := range args[1:] { 138 if args[1:][artifactNames] == "--unpack" || args[1:][artifactNames] == "-u" { 139 expandResources = true 140 } 141 } 142 } else { 143 query := ForceMetadataQuery{} 144 if len(args) >= 2 { 145 newargs := args[1:] 146 for artifactNames := range newargs { 147 if newargs[artifactNames] == "--unpack" || newargs[artifactNames] == "-u" { 148 expandResources = true 149 } else { 150 mq := ForceMetadataQueryElement{artifactType, newargs[artifactNames]} 151 query = append(query, mq) 152 } 153 } 154 } else { 155 mq := ForceMetadataQueryElement{artifactType, "*"} 156 query = append(query, mq) 157 } 158 files, err = force.Metadata.Retrieve(query) 159 if err != nil { 160 ErrorAndExit(err.Error()) 161 } 162 } 163 164 var resourcesMap map[string]string 165 resourcesMap = make(map[string]string) 166 167 for name, data := range files { 168 file := filepath.Join(root, name) 169 dir := filepath.Dir(file) 170 171 if err := os.MkdirAll(dir, 0755); err != nil { 172 ErrorAndExit(err.Error()) 173 } 174 if err := ioutil.WriteFile(filepath.Join(root, name), data, 0644); err != nil { 175 ErrorAndExit(err.Error()) 176 } 177 var isResource = false 178 if artifactType == "StaticResource" { 179 isResource = true 180 } else if strings.HasSuffix(file, ".resource-meta.xml") { 181 isResource = true 182 } 183 //Handle expanding static resources into a "bundle" folder 184 if isResource && expandResources && name != "package.xml" { 185 pathParts := strings.Split(name, string(os.PathSeparator)) 186 resourceName := pathParts[cap(pathParts)-1] 187 188 resourceExt := strings.Split(resourceName, ".")[1] 189 resourceName = strings.Split(resourceName, ".")[0] 190 if resourceExt == "resource-meta" { 191 //Check the xml to determine the mime type of the resource 192 // We are looking for application/zip 193 var meta struct { 194 CacheControl string `xml:"cacheControl"` 195 ContentType string `xml:"contentType"` 196 } 197 if err = xml.Unmarshal([]byte(data), &meta); err != nil { 198 //return 199 } 200 if meta.ContentType == "application/zip" { 201 // this is the meat for a zip file, so add the map 202 resourcesMap[resourceName] = filepath.Join(filepath.Dir(file), resourceName+".resource") 203 } 204 } 205 } 206 } 207 208 // Now we need to see if we have any zips to expand 209 if expandResources && len(resourcesMap) > 0 { 210 for key, value := range resourcesMap { 211 //resourcefile := filepath.Join(root, "staticresources", value) 212 resourcefile := value 213 dest := filepath.Join(filepath.Dir(value), key) 214 if err := os.MkdirAll(dest, 0755); err != nil { 215 ErrorAndExit(err.Error()) 216 } 217 //f, err := os.Open(resourcefile); 218 r, err := zip.OpenReader(resourcefile) 219 if err != nil { 220 log.Fatal(err) 221 } 222 defer r.Close() 223 224 for _, f := range r.File { 225 rc, err := f.Open() 226 if err != nil { 227 fmt.Println(err) 228 } 229 defer rc.Close() 230 231 path := filepath.Join(dest, f.Name) 232 if !strings.HasPrefix(f.Name, "__") { 233 if f.FileInfo().IsDir() { 234 os.MkdirAll(path, f.Mode()) 235 } else { 236 zf, err := os.OpenFile( 237 path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) 238 if err != nil { 239 fmt.Println(err) 240 } 241 242 _, err = io.Copy(zf, rc) 243 if err != nil { 244 fmt.Println(err) 245 zf.Close() 246 } 247 zf.Close() 248 } 249 } 250 } 251 } 252 } 253 254 fmt.Printf("Exported to %s\n", root) 255 }