func BuildPackage(dir string) (*Package, error) { home := os.Getenv("HOME") buf := new(bytes.Buffer) tarfile := new(archivex.TarFile) tarfile.Writer = tar.NewWriter(buf) specContent, err := ioutil.ReadFile(filepath.Join(dir, "SPEC.yml")) root := Root{} err = yaml.Unmarshal(specContent, &root) if err != nil { return nil, err } spec := root.Spec tarfile.AddFileWithName(filepath.Join(dir, "SPEC.yml"), "SPEC.yml") tarfile.AddFileWithName(filepath.Join(dir, spec.Provision), spec.Provision) tarfile.AddFileWithName(filepath.Join(dir, spec.Composition), spec.Composition) for _, d := range spec.Dirs { tarfile.AddAll(filepath.Join(dir, d), true) } hashes := []string{} graph := make(DepGraph) // resolve dependencies on build // to gaurantee that the package will have // the same behaviour everytime we deploy it for name, attributes := range spec.Dependencies { attrs, err := parse(attributes) if err != nil { return nil, err } entry, err := repo.Get(name, attrs["version"]) if err != nil { return nil, err } p, err := LoadPackage(filepath.Join(home, ".dpm", "cache", entry.Filename)) if err != nil { return nil, err } err = p.ExtractIfNotExist() if err != nil { return nil, err } hashes = append(hashes, entry.Hash) deps, err := p.Deps() if err != nil { return nil, err } graph = merge(graph, deps) } // add entry of this package before save to DEPS graph["this"] = hashes depsContent, err := yaml.Marshal(graph) if err != nil { return nil, err } tarfile.Add("DEPS", depsContent) order, cyclic := toposort(graph) if len(cyclic) != 0 { return nil, fmt.Errorf("Dependency cyclic detected") } for _, h := range order { if h == "this" { continue } tarfile.AddAll(filepath.Join(home, ".dpm", "workspace", h), true) } tarfile.Close() return &Package{buf.Bytes()}, nil }