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  }