// NewRemoteRepo creates new instance of Debian remote repository with specified params func NewRemoteRepo(name string, archiveRoot string, distribution string, components []string, architectures []string, downloadSources bool, downloadUdebs bool) (*RemoteRepo, error) { result := &RemoteRepo{ UUID: uuid.New(), Name: name, ArchiveRoot: archiveRoot, Distribution: distribution, Components: components, Architectures: architectures, DownloadSources: downloadSources, DownloadUdebs: downloadUdebs, } err := result.prepare() if err != nil { return nil, err } if strings.HasSuffix(result.Distribution, "/") || strings.HasPrefix(result.Distribution, ".") { // flat repo if !strings.HasPrefix(result.Distribution, ".") { result.Distribution = "./" + result.Distribution } result.Architectures = nil if len(result.Components) > 0 { return nil, fmt.Errorf("components aren't supported for flat repos") } if result.DownloadUdebs { return nil, fmt.Errorf("debian-installer udebs aren't supported for flat repos") } result.Components = nil } return result, nil }
// NewLocalRepo creates new instance of Debian local repository func NewLocalRepo(name string, comment string) *LocalRepo { return &LocalRepo{ UUID: uuid.New(), Name: name, Comment: comment, } }
// NewSnapshotFromLocalRepo creates snapshot from current state of local repository func NewSnapshotFromLocalRepo(name string, repo *LocalRepo) (*Snapshot, error) { if repo.packageRefs == nil { return nil, errors.New("local repo doesn't have packages") } return &Snapshot{ UUID: uuid.New(), Name: name, CreatedAt: time.Now(), SourceKind: "local", SourceIDs: []string{repo.UUID}, Description: fmt.Sprintf("Snapshot from local repo %s", repo), packageRefs: repo.packageRefs, }, nil }
// NewSnapshotFromRepository creates snapshot from current state of repository func NewSnapshotFromRepository(name string, repo *RemoteRepo) (*Snapshot, error) { if repo.packageRefs == nil { return nil, errors.New("mirror not updated") } return &Snapshot{ UUID: uuid.New(), Name: name, CreatedAt: time.Now(), SourceKind: "repo", SourceIDs: []string{repo.UUID}, Description: fmt.Sprintf("Snapshot from mirror %s", repo), packageRefs: repo.packageRefs, }, nil }
// NewSnapshotFromRefList creates snapshot from PackageRefList func NewSnapshotFromRefList(name string, sources []*Snapshot, list *PackageRefList, description string) *Snapshot { sourceUUIDs := make([]string, len(sources)) for i := range sources { sourceUUIDs[i] = sources[i].UUID } return &Snapshot{ UUID: uuid.New(), Name: name, CreatedAt: time.Now(), SourceKind: "snapshot", SourceIDs: sourceUUIDs, Description: description, packageRefs: list, } }
// NewPublishedRepo creates new published repository // // storage is PublishedStorage name // prefix specifies publishing prefix // distribution and architectures are user-defined properties // components & sources are lists of component to source mapping (*Snapshot or *LocalRepo) func NewPublishedRepo(storage, prefix, distribution string, architectures []string, components []string, sources []interface{}, collectionFactory *CollectionFactory) (*PublishedRepo, error) { result := &PublishedRepo{ UUID: uuid.New(), Storage: storage, Architectures: architectures, Sources: make(map[string]string), sourceItems: make(map[string]repoSourceItem), } if len(sources) == 0 { panic("publish with empty sources") } if len(sources) != len(components) { panic("sources and components should be equal in size") } var ( discoveredDistributions = []string{} source interface{} component string snapshot *Snapshot localRepo *LocalRepo ok bool ) // get first source source = sources[0] // figure out source kind snapshot, ok = source.(*Snapshot) if ok { result.SourceKind = "snapshot" } else { localRepo, ok = source.(*LocalRepo) if ok { result.SourceKind = "local" } else { panic("unknown source kind") } } for i := range sources { component, source = components[i], sources[i] if distribution == "" || component == "" { rootDistributions, rootComponents := walkUpTree(source, collectionFactory) if distribution == "" { for i := range rootDistributions { rootDistributions[i] = strings.Replace(rootDistributions[i], "/", "-", -1) } discoveredDistributions = append(discoveredDistributions, rootDistributions...) } if component == "" { sort.Strings(rootComponents) if len(rootComponents) > 0 && rootComponents[0] == rootComponents[len(rootComponents)-1] { component = rootComponents[0] } else if len(sources) == 1 { // only if going from one source, assume default component "main" component = "main" } else { return nil, fmt.Errorf("unable to figure out component name for %s", source) } } } _, exists := result.Sources[component] if exists { return nil, fmt.Errorf("duplicate component name: %s", component) } if result.SourceKind == "snapshot" { snapshot = source.(*Snapshot) result.Sources[component] = snapshot.UUID result.sourceItems[component] = repoSourceItem{snapshot: snapshot} } else if result.SourceKind == "local" { localRepo = source.(*LocalRepo) result.Sources[component] = localRepo.UUID result.sourceItems[component] = repoSourceItem{localRepo: localRepo, packageRefs: localRepo.RefList()} } } // clean & verify prefix prefix = filepath.Clean(prefix) if strings.HasPrefix(prefix, "/") { prefix = prefix[1:] } if strings.HasSuffix(prefix, "/") { prefix = prefix[:len(prefix)-1] } prefix = filepath.Clean(prefix) for _, part := range strings.Split(prefix, "/") { if part == ".." || part == "dists" || part == "pool" { return nil, fmt.Errorf("invalid prefix %s", prefix) } } result.Prefix = prefix // guessing distribution if distribution == "" { sort.Strings(discoveredDistributions) if len(discoveredDistributions) > 0 && discoveredDistributions[0] == discoveredDistributions[len(discoveredDistributions)-1] { distribution = discoveredDistributions[0] } else { return nil, fmt.Errorf("unable to guess distribution name, please specify explicitly") } } if strings.Index(distribution, "/") != -1 { return nil, fmt.Errorf("invalid distribution %s, '/' is not allowed", distribution) } result.Distribution = distribution return result, nil }