Beispiel #1
0
func (a *Api) RepoDeletePackage(repoName, packageRef string) error {
	collection := a.Ctx().CollectionFactory().LocalRepoCollection()
	collection.Lock()
	defer collection.Unlock()
	repo, err := collection.ByName(repoName)
	if err != nil {
		return err
	}

	err = collection.LoadComplete(repo)
	if err != nil {
		return err
	}

	list, err := deb.NewPackageListFromRefList(repo.RefList(), a.Ctx().CollectionFactory().PackageCollection(), nil)
	if err != nil {
		return err
	}

	pkg, err := a.Ctx().CollectionFactory().PackageCollection().ByKey([]byte(packageRef))
	if err != nil {
		return err
	}

	list.Remove(pkg)

	repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))
	return collection.Update(repo)
}
Beispiel #2
0
func (a *Api) RepoShowPackagesDetail(repoName string) ([]*deb.Package, error) {
	collection := a.Ctx().CollectionFactory().LocalRepoCollection()
	collection.RLock()
	defer collection.RUnlock()

	repo, err := collection.ByName(repoName)
	if err != nil {
		return nil, err
	}
	err = collection.LoadComplete(repo)
	if err != nil {
		return nil, err
	}

	list, err := deb.NewPackageListFromRefList(repo.RefList(), a.Ctx().CollectionFactory().PackageCollection(), nil)
	if err != nil {
		return nil, err
	}
	result := []*deb.Package{}
	list.ForEach(func(p *deb.Package) error {
		result = append(result, p)
		return nil
	})
	return result, nil
}
Beispiel #3
0
func aptlyRepoRemove(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 2 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	name := args[0]

	repo, err := context.CollectionFactory().LocalRepoCollection().ByName(name)
	if err != nil {
		return fmt.Errorf("unable to remove: %s", err)
	}

	err = context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
	if err != nil {
		return fmt.Errorf("unable to remove: %s", err)
	}

	context.Progress().Printf("Loading packages...\n")

	list, err := deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	queries := make([]deb.PackageQuery, len(args)-1)
	for i := 0; i < len(args)-1; i++ {
		queries[i], err = query.Parse(args[i+1])
		if err != nil {
			return fmt.Errorf("unable to remove: %s", err)
		}
	}

	list.PrepareIndex()
	toRemove, err := list.Filter(queries, false, nil, 0, nil)
	if err != nil {
		return fmt.Errorf("unable to remove: %s", err)
	}

	toRemove.ForEach(func(p *deb.Package) error {
		list.Remove(p)
		context.Progress().ColoredPrintf("@r[-]@| %s removed", p)
		return nil
	})

	if context.Flags().Lookup("dry-run").Value.Get().(bool) {
		context.Progress().Printf("\nChanges not saved, as dry run has been requested.\n")
	} else {
		repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))

		err = context.CollectionFactory().LocalRepoCollection().Update(repo)
		if err != nil {
			return fmt.Errorf("unable to save: %s", err)
		}
	}

	return err
}
Beispiel #4
0
// Common piece of code to show list of packages,
// with searching & details if requested
func showPackages(c *gin.Context, reflist *deb.PackageRefList) {
	result := []*deb.Package{}

	list, err := deb.NewPackageListFromRefList(reflist, context.CollectionFactory().PackageCollection(), nil)
	if err != nil {
		c.Fail(404, err)
		return
	}

	queryS := c.Request.URL.Query().Get("q")
	if queryS != "" {
		q, err := query.Parse(c.Request.URL.Query().Get("q"))
		if err != nil {
			c.Fail(400, err)
			return
		}

		withDeps := c.Request.URL.Query().Get("withDeps") == "1"
		architecturesList := []string{}

		if withDeps {
			if len(context.ArchitecturesList()) > 0 {
				architecturesList = context.ArchitecturesList()
			} else {
				architecturesList = list.Architectures(false)
			}

			sort.Strings(architecturesList)

			if len(architecturesList) == 0 {
				c.Fail(400, fmt.Errorf("unable to determine list of architectures, please specify explicitly"))
				return
			}
		}

		list.PrepareIndex()

		list, err = list.Filter([]deb.PackageQuery{q}, withDeps,
			nil, context.DependencyOptions(), architecturesList)
		if err != nil {
			c.Fail(500, fmt.Errorf("unable to search: %s", err))
			return
		}
	}

	if c.Request.URL.Query().Get("format") == "details" {
		list.ForEach(func(p *deb.Package) error {
			result = append(result, p)
			return nil
		})

		c.JSON(200, result)
	} else {
		c.JSON(200, list.Strings())
	}
}
Beispiel #5
0
func (a *Api) RepoAddFile(repoName, fileName string, removeAfter, forceReplace bool) (*aptly.RecordingResultReporter, []string, error) {
	verifier := &utils.GpgVerifier{}
	collection := a.Ctx().CollectionFactory().LocalRepoCollection()
	collection.Lock()
	defer collection.Unlock()
	repo, err := collection.ByName(repoName)
	if err != nil {
		return nil, []string{}, err
	}

	err = collection.LoadComplete(repo)
	if err != nil {
		return nil, []string{}, err
	}

	var reporter = &aptly.RecordingResultReporter{
		Warnings:     []string{},
		AddedLines:   []string{},
		RemovedLines: []string{},
	}
	var packageFiles, failedFiles []string
	packageFiles, failedFiles = deb.CollectPackageFiles([]string{fileName}, reporter)

	list, err := deb.NewPackageListFromRefList(repo.RefList(), a.Ctx().CollectionFactory().PackageCollection(), nil)
	if err != nil {
		return nil, []string{}, err
	}
	var processedFiles, failedFiles2 []string
	processedFiles, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, a.Ctx().PackagePool(),
		a.Ctx().CollectionFactory().PackageCollection(), reporter, nil)
	failedFiles = append(failedFiles, failedFiles2...)

	if err != nil {
		return nil, []string{}, err
	}
	repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))

	err = collection.Update(repo)
	if err != nil {
		return nil, []string{}, err
	}
	processedFiles = utils.StrSliceDeduplicate(processedFiles)
	if removeAfter {
		for _, file := range processedFiles {
			os.Remove(file)
		}
	}

	if failedFiles == nil {
		failedFiles = []string{}
	}

	return reporter, failedFiles, nil
}
Beispiel #6
0
func (a *Api) RepoShowPackages(repoName string) ([]string, error) {
	collection := a.Ctx().CollectionFactory().LocalRepoCollection()
	collection.RLock()
	defer collection.RUnlock()

	repo, err := collection.ByName(repoName)
	if err != nil {
		return []string{}, err
	}
	err = collection.LoadComplete(repo)
	if err != nil {
		return []string{}, err
	}

	list, err := deb.NewPackageListFromRefList(repo.RefList(), a.Ctx().CollectionFactory().PackageCollection(), nil)
	if err != nil {
		return []string{}, err
	}
	return list.Strings(), nil
}
Beispiel #7
0
func (a *Api) SnapshotShowPackages(snapshotName string) ([]string, error) {
	collection := a.Ctx().CollectionFactory().SnapshotCollection()
	collection.RLock()
	defer collection.RUnlock()

	snapshot, err := collection.ByName(snapshotName)
	if err != nil {
		return nil, err
	}

	err = collection.LoadComplete(snapshot)
	if err != nil {
		return nil, err
	}
	list, err := deb.NewPackageListFromRefList(snapshot.RefList(), a.Ctx().CollectionFactory().PackageCollection(), nil)
	if err != nil {
		return nil, err
	}
	return list.Strings(), nil
}
Beispiel #8
0
func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error {
	var err error
	if len(args) != 2 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	name := args[0]
	command := cmd.Parent.Name()

	var reflist *deb.PackageRefList

	if command == "snapshot" {
		snapshot, err := context.CollectionFactory().SnapshotCollection().ByName(name)
		if err != nil {
			return fmt.Errorf("unable to search: %s", err)
		}

		err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
		if err != nil {
			return fmt.Errorf("unable to search: %s", err)
		}

		reflist = snapshot.RefList()
	} else if command == "mirror" {
		repo, err := context.CollectionFactory().RemoteRepoCollection().ByName(name)
		if err != nil {
			return fmt.Errorf("unable to search: %s", err)
		}

		err = context.CollectionFactory().RemoteRepoCollection().LoadComplete(repo)
		if err != nil {
			return fmt.Errorf("unable to search: %s", err)
		}

		reflist = repo.RefList()
	} else if command == "repo" {
		repo, err := context.CollectionFactory().LocalRepoCollection().ByName(name)
		if err != nil {
			return fmt.Errorf("unable to search: %s", err)
		}

		err = context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
		if err != nil {
			return fmt.Errorf("unable to search: %s", err)
		}

		reflist = repo.RefList()
	} else {
		panic("unknown command")
	}

	list, err := deb.NewPackageListFromRefList(reflist, context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to search: %s", err)
	}

	list.PrepareIndex()

	q, err := query.Parse(args[1])
	if err != nil {
		return fmt.Errorf("unable to search: %s", err)
	}

	withDeps := context.Flags().Lookup("with-deps").Value.Get().(bool)
	architecturesList := []string{}

	if withDeps {
		if len(context.ArchitecturesList()) > 0 {
			architecturesList = context.ArchitecturesList()
		} else {
			architecturesList = list.Architectures(false)
		}

		sort.Strings(architecturesList)

		if len(architecturesList) == 0 {
			return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
		}
	}

	result, err := list.Filter([]deb.PackageQuery{q}, withDeps,
		nil, context.DependencyOptions(), architecturesList)
	if err != nil {
		return fmt.Errorf("unable to search: %s", err)
	}

	if result.Len() == 0 {
		return fmt.Errorf("no results")
	}

	result.ForEach(func(p *deb.Package) error {
		context.Progress().Printf("%s\n", p)
		return nil
	})

	return err
}
Beispiel #9
0
func aptlyRepoInclude(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 1 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	verifier, err := getVerifier(context.Flags())
	if err != nil {
		return fmt.Errorf("unable to initialize GPG verifier: %s", err)
	}

	if verifier == nil {
		verifier = &utils.GpgVerifier{}
	}

	forceReplace := context.Flags().Lookup("force-replace").Value.Get().(bool)
	acceptUnsigned := context.Flags().Lookup("accept-unsigned").Value.Get().(bool)
	ignoreSignatures := context.Flags().Lookup("ignore-signatures").Value.Get().(bool)
	noRemoveFiles := context.Flags().Lookup("no-remove-files").Value.Get().(bool)

	repoTemplate, err := template.New("repo").Parse(context.Flags().Lookup("repo").Value.Get().(string))
	if err != nil {
		return fmt.Errorf("error parsing -repo template: %s", err)
	}

	uploaders := (*deb.Uploaders)(nil)
	uploadersFile := context.Flags().Lookup("uploaders-file").Value.Get().(string)
	if uploadersFile != "" {
		uploaders, err = deb.NewUploadersFromFile(uploadersFile)
		if err != nil {
			return err
		}

		for i := range uploaders.Rules {
			uploaders.Rules[i].CompiledCondition, err = query.Parse(uploaders.Rules[i].Condition)
			if err != nil {
				return fmt.Errorf("error parsing query %s: %s", uploaders.Rules[i].Condition, err)
			}
		}
	}

	reporter := &aptly.ConsoleResultReporter{Progress: context.Progress()}

	var changesFiles, failedFiles, processedFiles []string

	changesFiles, failedFiles = deb.CollectChangesFiles(args, reporter)

	for _, path := range changesFiles {
		var changes *deb.Changes

		changes, err = deb.NewChanges(path)
		if err != nil {
			failedFiles = append(failedFiles, path)
			reporter.Warning("unable to process file %s: %s", path, err)
			continue
		}

		err = changes.VerifyAndParse(acceptUnsigned, ignoreSignatures, verifier)
		if err != nil {
			failedFiles = append(failedFiles, path)
			reporter.Warning("unable to process file %s: %s", changes.ChangesName, err)
			changes.Cleanup()
			continue
		}

		err = changes.Prepare()
		if err != nil {
			failedFiles = append(failedFiles, path)
			reporter.Warning("unable to process file %s: %s", changes.ChangesName, err)
			changes.Cleanup()
			continue
		}

		repoName := &bytes.Buffer{}
		err = repoTemplate.Execute(repoName, changes.Stanza)
		if err != nil {
			return fmt.Errorf("error applying template to repo: %s", err)
		}

		context.Progress().Printf("Loading repository %s for changes file %s...\n", repoName.String(), changes.ChangesName)

		repo, err := context.CollectionFactory().LocalRepoCollection().ByName(repoName.String())
		if err != nil {
			failedFiles = append(failedFiles, path)
			reporter.Warning("unable to process file %s: %s", changes.ChangesName, err)
			changes.Cleanup()
			continue
		}

		currentUploaders := uploaders
		if repo.Uploaders != nil {
			currentUploaders = repo.Uploaders
			for i := range currentUploaders.Rules {
				currentUploaders.Rules[i].CompiledCondition, err = query.Parse(currentUploaders.Rules[i].Condition)
				if err != nil {
					return fmt.Errorf("error parsing query %s: %s", currentUploaders.Rules[i].Condition, err)
				}
			}
		}

		if currentUploaders != nil {
			if err = currentUploaders.IsAllowed(changes); err != nil {
				failedFiles = append(failedFiles, path)
				reporter.Warning("changes file skipped due to uploaders config: %s, keys %#v: %s",
					changes.ChangesName, changes.SignatureKeys, err)
				changes.Cleanup()
				continue
			}
		}

		err = context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
		if err != nil {
			return fmt.Errorf("unable to load repo: %s", err)
		}

		list, err := deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
		if err != nil {
			return fmt.Errorf("unable to load packages: %s", err)
		}

		packageFiles, _ := deb.CollectPackageFiles([]string{changes.TempDir}, reporter)

		var restriction deb.PackageQuery

		restriction, err = changes.PackageQuery()
		if err != nil {
			failedFiles = append(failedFiles, path)
			reporter.Warning("unable to process file %s: %s", changes.ChangesName, err)
			changes.Cleanup()
			continue
		}

		var processedFiles2, failedFiles2 []string

		processedFiles2, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
			context.CollectionFactory().PackageCollection(), reporter, restriction)

		if err != nil {
			return fmt.Errorf("unable to import package files: %s", err)
		}

		repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))

		err = context.CollectionFactory().LocalRepoCollection().Update(repo)
		if err != nil {
			return fmt.Errorf("unable to save: %s", err)
		}

		err = changes.Cleanup()
		if err != nil {
			return err
		}

		for _, file := range failedFiles2 {
			failedFiles = append(failedFiles, filepath.Join(changes.BasePath, filepath.Base(file)))
		}

		for _, file := range processedFiles2 {
			processedFiles = append(processedFiles, filepath.Join(changes.BasePath, filepath.Base(file)))
		}

		processedFiles = append(processedFiles, path)
	}

	if !noRemoveFiles {
		processedFiles = utils.StrSliceDeduplicate(processedFiles)

		for _, file := range processedFiles {
			err := os.Remove(file)
			if err != nil {
				return fmt.Errorf("unable to remove file: %s", err)
			}
		}
	}

	if len(failedFiles) > 0 {
		context.Progress().ColoredPrintf("@y[!]@| @!Some files were skipped due to errors:@|")
		for _, file := range failedFiles {
			context.Progress().ColoredPrintf("  %s", file)
		}

		return fmt.Errorf("some files failed to be added")
	}

	return err
}
Beispiel #10
0
func aptlySnapshotPull(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 4 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	noDeps := context.Flags().Lookup("no-deps").Value.Get().(bool)
	noRemove := context.Flags().Lookup("no-remove").Value.Get().(bool)
	allMatches := context.Flags().Lookup("all-matches").Value.Get().(bool)

	// Load <name> snapshot
	snapshot, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	// Load <source> snapshot
	source, err := context.CollectionFactory().SnapshotCollection().ByName(args[1])
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	err = context.CollectionFactory().SnapshotCollection().LoadComplete(source)
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	context.Progress().Printf("Dependencies would be pulled into snapshot:\n    %s\nfrom snapshot:\n    %s\nand result would be saved as new snapshot %s.\n",
		snapshot, source, args[2])

	// Convert snapshot to package list
	context.Progress().Printf("Loading packages (%d)...\n", snapshot.RefList().Len()+source.RefList().Len())
	packageList, err := deb.NewPackageListFromRefList(snapshot.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	sourcePackageList, err := deb.NewPackageListFromRefList(source.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	context.Progress().Printf("Building indexes...\n")
	packageList.PrepareIndex()
	sourcePackageList.PrepareIndex()

	// Calculate architectures
	var architecturesList []string

	if len(context.ArchitecturesList()) > 0 {
		architecturesList = context.ArchitecturesList()
	} else {
		architecturesList = packageList.Architectures(false)
	}

	sort.Strings(architecturesList)

	if len(architecturesList) == 0 {
		return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
	}

	// Build architecture query: (arch == "i386" | arch == "amd64" | ...)
	var archQuery deb.PackageQuery = &deb.FieldQuery{Field: "$Architecture", Relation: deb.VersionEqual, Value: ""}
	for _, arch := range architecturesList {
		archQuery = &deb.OrQuery{L: &deb.FieldQuery{Field: "$Architecture", Relation: deb.VersionEqual, Value: arch}, R: archQuery}
	}

	// Initial queries out of arguments
	queries := make([]deb.PackageQuery, len(args)-3)
	for i, arg := range args[3:] {
		queries[i], err = query.Parse(arg)
		if err != nil {
			return fmt.Errorf("unable to parse query: %s", err)
		}
		// Add architecture filter
		queries[i] = &deb.AndQuery{L: queries[i], R: archQuery}
	}

	// Filter with dependencies as requested
	result, err := sourcePackageList.Filter(queries, !noDeps, packageList, context.DependencyOptions(), architecturesList)
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}
	result.PrepareIndex()

	alreadySeen := map[string]bool{}

	result.ForEachIndexed(func(pkg *deb.Package) error {
		key := pkg.Architecture + "_" + pkg.Name
		_, seen := alreadySeen[key]

		// If we haven't seen such name-architecture pair and were instructed to remove, remove it
		if !noRemove && !seen {
			// Remove all packages with the same name and architecture
			pS := packageList.Search(deb.Dependency{Architecture: pkg.Architecture, Pkg: pkg.Name}, true)
			for _, p := range pS {
				packageList.Remove(p)
				context.Progress().ColoredPrintf("@r[-]@| %s removed", p)
			}
		}

		// If !allMatches, add only first matching name-arch package
		if !seen || allMatches {
			packageList.Add(pkg)
			context.Progress().ColoredPrintf("@g[+]@| %s added", pkg)
		}

		alreadySeen[key] = true

		return nil
	})
	alreadySeen = nil

	if context.Flags().Lookup("dry-run").Value.Get().(bool) {
		context.Progress().Printf("\nNot creating snapshot, as dry run was requested.\n")
	} else {
		// Create <destination> snapshot
		destination := deb.NewSnapshotFromPackageList(args[2], []*deb.Snapshot{snapshot, source}, packageList,
			fmt.Sprintf("Pulled into '%s' with '%s' as source, pull request was: '%s'", snapshot.Name, source.Name, strings.Join(args[3:], " ")))

		err = context.CollectionFactory().SnapshotCollection().Add(destination)
		if err != nil {
			return fmt.Errorf("unable to create snapshot: %s", err)
		}

		context.Progress().Printf("\nSnapshot %s successfully created.\nYou can run 'aptly publish snapshot %s' to publish snapshot as Debian repository.\n", destination.Name, destination.Name)
	}
	return err
}
Beispiel #11
0
func aptlySnapshotVerify(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 1 {
		cmd.Usage()
		return err
	}

	snapshots := make([]*deb.Snapshot, len(args))
	for i := range snapshots {
		snapshots[i], err = context.CollectionFactory().SnapshotCollection().ByName(args[i])
		if err != nil {
			return fmt.Errorf("unable to verify: %s", err)
		}

		err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshots[i])
		if err != nil {
			return fmt.Errorf("unable to verify: %s", err)
		}
	}

	context.Progress().Printf("Loading packages...\n")

	packageList, err := deb.NewPackageListFromRefList(snapshots[0].RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		fmt.Errorf("unable to load packages: %s", err)
	}

	sourcePackageList := deb.NewPackageList()
	err = sourcePackageList.Append(packageList)
	if err != nil {
		fmt.Errorf("unable to merge sources: %s", err)
	}

	var pL *deb.PackageList
	for i := 1; i < len(snapshots); i++ {
		pL, err = deb.NewPackageListFromRefList(snapshots[i].RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
		if err != nil {
			fmt.Errorf("unable to load packages: %s", err)
		}

		err = sourcePackageList.Append(pL)
		if err != nil {
			fmt.Errorf("unable to merge sources: %s", err)
		}
	}

	sourcePackageList.PrepareIndex()

	var architecturesList []string

	if len(context.ArchitecturesList()) > 0 {
		architecturesList = context.ArchitecturesList()
	} else {
		architecturesList = packageList.Architectures(true)
	}

	if len(architecturesList) == 0 {
		return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
	}

	context.Progress().Printf("Verifying...\n")

	missing, err := packageList.VerifyDependencies(context.DependencyOptions(), architecturesList, sourcePackageList, context.Progress())
	if err != nil {
		return fmt.Errorf("unable to verify dependencies: %s", err)
	}

	if len(missing) == 0 {
		context.Progress().Printf("All dependencies are satisfied.\n")
	} else {
		context.Progress().Printf("Missing dependencies (%d):\n", len(missing))
		deps := make([]string, len(missing))
		i := 0
		for _, dep := range missing {
			deps[i] = dep.String()
			i++
		}

		sort.Strings(deps)

		for _, dep := range deps {
			context.Progress().Printf("  %s\n", dep)
		}
	}

	return err
}
Beispiel #12
0
func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 3 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	command := cmd.Name()

	dstRepo, err := context.CollectionFactory().LocalRepoCollection().ByName(args[1])
	if err != nil {
		return fmt.Errorf("unable to %s: %s", command, err)
	}

	err = context.CollectionFactory().LocalRepoCollection().LoadComplete(dstRepo)
	if err != nil {
		return fmt.Errorf("unable to %s: %s", command, err)
	}

	var (
		srcRefList *deb.PackageRefList
		srcRepo    *deb.LocalRepo
	)

	if command == "copy" || command == "move" {
		srcRepo, err = context.CollectionFactory().LocalRepoCollection().ByName(args[0])
		if err != nil {
			return fmt.Errorf("unable to %s: %s", command, err)
		}

		if srcRepo.UUID == dstRepo.UUID {
			return fmt.Errorf("unable to %s: source and destination are the same", command)
		}

		err = context.CollectionFactory().LocalRepoCollection().LoadComplete(srcRepo)
		if err != nil {
			return fmt.Errorf("unable to %s: %s", command, err)
		}

		srcRefList = srcRepo.RefList()
	} else if command == "import" {
		var srcRemoteRepo *deb.RemoteRepo

		srcRemoteRepo, err = context.CollectionFactory().RemoteRepoCollection().ByName(args[0])
		if err != nil {
			return fmt.Errorf("unable to %s: %s", command, err)
		}

		err = context.CollectionFactory().RemoteRepoCollection().LoadComplete(srcRemoteRepo)
		if err != nil {
			return fmt.Errorf("unable to %s: %s", command, err)
		}

		if srcRemoteRepo.RefList() == nil {
			return fmt.Errorf("unable to %s: mirror not updated", command)
		}

		srcRefList = srcRemoteRepo.RefList()
	} else {
		panic("unexpected command")
	}

	context.Progress().Printf("Loading packages...\n")

	dstList, err := deb.NewPackageListFromRefList(dstRepo.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	srcList, err := deb.NewPackageListFromRefList(srcRefList, context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	srcList.PrepareIndex()

	var architecturesList []string

	withDeps := context.flags.Lookup("with-deps").Value.Get().(bool)

	if withDeps {
		dstList.PrepareIndex()

		// Calculate architectures
		if len(context.ArchitecturesList()) > 0 {
			architecturesList = context.ArchitecturesList()
		} else {
			architecturesList = dstList.Architectures(false)
		}

		sort.Strings(architecturesList)

		if len(architecturesList) == 0 {
			return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
		}
	}

	toProcess, err := srcList.Filter(args[2:], withDeps, dstList, context.DependencyOptions(), architecturesList)
	if err != nil {
		return fmt.Errorf("unable to %s: %s", command, err)
	}

	var verb string

	if command == "move" {
		verb = "moved"
	} else if command == "copy" {
		verb = "copied"
	} else if command == "import" {
		verb = "imported"
	}

	err = toProcess.ForEach(func(p *deb.Package) error {
		err = dstList.Add(p)
		if err != nil {
			return err
		}

		if command == "move" {
			srcList.Remove(p)
		}
		context.Progress().ColoredPrintf("@g[o]@| %s %s", p, verb)
		return nil
	})
	if err != nil {
		return fmt.Errorf("unable to %s: %s", command, err)
	}

	if context.flags.Lookup("dry-run").Value.Get().(bool) {
		context.Progress().Printf("\nChanges not saved, as dry run has been requested.\n")
	} else {
		dstRepo.UpdateRefList(deb.NewPackageRefListFromPackageList(dstList))

		err = context.CollectionFactory().LocalRepoCollection().Update(dstRepo)
		if err != nil {
			return fmt.Errorf("unable to save: %s", err)
		}

		if command == "move" {
			srcRepo.UpdateRefList(deb.NewPackageRefListFromPackageList(srcList))

			err = context.CollectionFactory().LocalRepoCollection().Update(srcRepo)
			if err != nil {
				return fmt.Errorf("unable to save: %s", err)
			}
		}
	}

	return err
}
Beispiel #13
0
func aptlyRepoAdd(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 2 {
		cmd.Usage()
		return err
	}

	name := args[0]

	verifier := &utils.GpgVerifier{}

	repo, err := context.CollectionFactory().LocalRepoCollection().ByName(name)
	if err != nil {
		return fmt.Errorf("unable to add: %s", err)
	}

	err = context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
	if err != nil {
		return fmt.Errorf("unable to add: %s", err)
	}

	context.Progress().Printf("Loading packages...\n")

	list, err := deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	packageFiles := []string{}

	for _, location := range args[1:] {
		info, err2 := os.Stat(location)
		if err2 != nil {
			context.Progress().ColoredPrintf("@y[!]@| @!Unable to process %s: %s@|", location, err2)
			continue
		}
		if info.IsDir() {
			err2 = filepath.Walk(location, func(path string, info os.FileInfo, err3 error) error {
				if err3 != nil {
					return err3
				}
				if info.IsDir() {
					return nil
				}

				if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".dsc") {
					packageFiles = append(packageFiles, path)
				}

				return nil
			})
		} else {
			if strings.HasSuffix(info.Name(), ".deb") || strings.HasSuffix(info.Name(), ".dsc") {
				packageFiles = append(packageFiles, location)
			} else {
				context.Progress().ColoredPrintf("@y[!]@| @!Unknwon file extenstion: %s@|", location)
				continue
			}
		}
	}

	processedFiles := []string{}
	sort.Strings(packageFiles)

	for _, file := range packageFiles {
		var (
			stanza deb.Stanza
			p      *deb.Package
		)

		candidateProcessedFiles := []string{}
		isSourcePackage := strings.HasSuffix(file, ".dsc")

		if isSourcePackage {
			stanza, err = deb.GetControlFileFromDsc(file, verifier)

			if err == nil {
				stanza["Package"] = stanza["Source"]
				delete(stanza, "Source")

				p, err = deb.NewSourcePackageFromControlFile(stanza)
			}
		} else {
			stanza, err = deb.GetControlFileFromDeb(file)
			p = deb.NewPackageFromControlFile(stanza)
		}
		if err != nil {
			context.Progress().ColoredPrintf("@y[!]@| @!Unable to read file %s: %s@|", file, err)
			continue
		}

		var checksums utils.ChecksumInfo
		checksums, err = utils.ChecksumsForFile(file)
		if err != nil {
			return err
		}

		if isSourcePackage {
			p.UpdateFiles(append(p.Files(), deb.PackageFile{Filename: filepath.Base(file), Checksums: checksums}))
		} else {
			p.UpdateFiles([]deb.PackageFile{deb.PackageFile{Filename: filepath.Base(file), Checksums: checksums}})
		}

		err = context.PackagePool().Import(file, checksums.MD5)
		if err != nil {
			context.Progress().ColoredPrintf("@y[!]@| @!Unable to import file %s into pool: %s@|", file, err)
			continue
		}

		candidateProcessedFiles = append(candidateProcessedFiles, file)

		// go over all files, except for the last one (.dsc/.deb itself)
		for _, f := range p.Files() {
			if filepath.Base(f.Filename) == filepath.Base(file) {
				continue
			}
			sourceFile := filepath.Join(filepath.Dir(file), filepath.Base(f.Filename))
			err = context.PackagePool().Import(sourceFile, f.Checksums.MD5)
			if err != nil {
				context.Progress().ColoredPrintf("@y[!]@| @!Unable to import file %s into pool: %s@|", sourceFile, err)
				break
			}

			candidateProcessedFiles = append(candidateProcessedFiles, sourceFile)
		}
		if err != nil {
			// some files haven't been imported
			continue
		}

		err = context.CollectionFactory().PackageCollection().Update(p)
		if err != nil {
			context.Progress().ColoredPrintf("@y[!]@| @!Unable to save package %s: %s@|", p, err)
			continue
		}

		err = list.Add(p)
		if err != nil {
			context.Progress().ColoredPrintf("@y[!]@| @!Unable to add package to repo %s: %s@|", p, err)
			continue
		}

		context.Progress().ColoredPrintf("@g[+]@| %s added@|", p)
		processedFiles = append(processedFiles, candidateProcessedFiles...)
	}

	repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))

	err = context.CollectionFactory().LocalRepoCollection().Update(repo)
	if err != nil {
		return fmt.Errorf("unable to save: %s", err)
	}

	if context.flags.Lookup("remove-files").Value.Get().(bool) {
		processedFiles = utils.StrSliceDeduplicate(processedFiles)

		for _, file := range processedFiles {
			err := os.Remove(file)
			if err != nil {
				return fmt.Errorf("unable to remove file: %s", err)
			}
		}
	}

	return err
}
Beispiel #14
0
func aptlyRepoAdd(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 2 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	name := args[0]

	verifier := &utils.GpgVerifier{}

	repo, err := context.CollectionFactory().LocalRepoCollection().ByName(name)
	if err != nil {
		return fmt.Errorf("unable to add: %s", err)
	}

	err = context.CollectionFactory().LocalRepoCollection().LoadComplete(repo)
	if err != nil {
		return fmt.Errorf("unable to add: %s", err)
	}

	context.Progress().Printf("Loading packages...\n")

	list, err := deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	forceReplace := context.Flags().Lookup("force-replace").Value.Get().(bool)

	var packageFiles, failedFiles []string

	packageFiles, failedFiles = deb.CollectPackageFiles(args[1:], &aptly.ConsoleResultReporter{Progress: context.Progress()})

	var processedFiles, failedFiles2 []string

	processedFiles, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
		context.CollectionFactory().PackageCollection(), &aptly.ConsoleResultReporter{Progress: context.Progress()}, nil)
	failedFiles = append(failedFiles, failedFiles2...)
	if err != nil {
		return fmt.Errorf("unable to import package files: %s", err)
	}

	repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))

	err = context.CollectionFactory().LocalRepoCollection().Update(repo)
	if err != nil {
		return fmt.Errorf("unable to save: %s", err)
	}

	if context.Flags().Lookup("remove-files").Value.Get().(bool) {
		processedFiles = utils.StrSliceDeduplicate(processedFiles)

		for _, file := range processedFiles {
			err := os.Remove(file)
			if err != nil {
				return fmt.Errorf("unable to remove file: %s", err)
			}
		}
	}

	if len(failedFiles) > 0 {
		context.Progress().ColoredPrintf("@y[!]@| @!Some files were skipped due to errors:@|")
		for _, file := range failedFiles {
			context.Progress().ColoredPrintf("  %s", file)
		}

		return fmt.Errorf("some files failed to be added")
	}

	return err
}
Beispiel #15
0
func aptlySnapshotFilter(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 3 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	withDeps := context.Flags().Lookup("with-deps").Value.Get().(bool)

	// Load <source> snapshot
	source, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
	if err != nil {
		return fmt.Errorf("unable to filter: %s", err)
	}

	err = context.CollectionFactory().SnapshotCollection().LoadComplete(source)
	if err != nil {
		return fmt.Errorf("unable to filter: %s", err)
	}

	// Convert snapshot to package list
	context.Progress().Printf("Loading packages (%d)...\n", source.RefList().Len())
	packageList, err := deb.NewPackageListFromRefList(source.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	context.Progress().Printf("Building indexes...\n")
	packageList.PrepareIndex()

	// Calculate architectures
	var architecturesList []string

	if len(context.ArchitecturesList()) > 0 {
		architecturesList = context.ArchitecturesList()
	} else {
		architecturesList = packageList.Architectures(false)
	}

	sort.Strings(architecturesList)

	if len(architecturesList) == 0 && withDeps {
		return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
	}

	// Initial queries out of arguments
	queries := make([]deb.PackageQuery, len(args)-2)
	for i, arg := range args[2:] {
		queries[i], err = query.Parse(arg)
		if err != nil {
			return fmt.Errorf("unable to parse query: %s", err)
		}
	}

	// Filter with dependencies as requested
	result, err := packageList.Filter(queries, withDeps, nil, context.DependencyOptions(), architecturesList)
	if err != nil {
		return fmt.Errorf("unable to filter: %s", err)
	}

	// Create <destination> snapshot
	destination := deb.NewSnapshotFromPackageList(args[1], []*deb.Snapshot{source}, result,
		fmt.Sprintf("Filtered '%s', query was: '%s'", source.Name, strings.Join(args[2:], " ")))

	err = context.CollectionFactory().SnapshotCollection().Add(destination)
	if err != nil {
		return fmt.Errorf("unable to create snapshot: %s", err)
	}

	context.Progress().Printf("\nSnapshot %s successfully filtered.\nYou can run 'aptly publish snapshot %s' to publish snapshot as Debian repository.\n", destination.Name, destination.Name)

	return err
}
Beispiel #16
0
// Handler for both add and delete
func apiReposPackagesAddDelete(c *gin.Context, cb func(list *deb.PackageList, p *deb.Package) error) {
	var b struct {
		PackageRefs []string
	}

	if !c.Bind(&b) {
		return
	}

	collection := context.CollectionFactory().LocalRepoCollection()
	collection.Lock()
	defer collection.Unlock()

	repo, err := collection.ByName(c.Params.ByName("name"))
	if err != nil {
		c.Fail(404, err)
		return
	}

	err = collection.LoadComplete(repo)
	if err != nil {
		c.Fail(500, err)
		return
	}

	list, err := deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), nil)
	if err != nil {
		c.Fail(500, err)
		return
	}

	// verify package refs and build package list
	for _, ref := range b.PackageRefs {
		var p *deb.Package

		p, err = context.CollectionFactory().PackageCollection().ByKey([]byte(ref))
		if err != nil {
			if err == database.ErrNotFound {
				c.Fail(404, fmt.Errorf("package %s: %s", ref, err))
			} else {
				c.Fail(500, err)
			}
			return
		}
		err = cb(list, p)
		if err != nil {
			c.Fail(400, err)
			return
		}
	}

	repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))

	err = context.CollectionFactory().LocalRepoCollection().Update(repo)
	if err != nil {
		c.Fail(500, fmt.Errorf("unable to save: %s", err))
		return
	}

	c.JSON(200, repo)

}
Beispiel #17
0
// POST /repos/:name/file/:dir
func apiReposPackageFromDir(c *gin.Context) {
	forceReplace := c.Request.URL.Query().Get("forceReplace") == "1"
	noRemove := c.Request.URL.Query().Get("noRemove") == "1"

	if !verifyDir(c) {
		return
	}

	fileParam := c.Params.ByName("file")
	if fileParam != "" && !verifyPath(fileParam) {
		c.Fail(400, fmt.Errorf("wrong file"))
		return
	}

	collection := context.CollectionFactory().LocalRepoCollection()
	collection.Lock()
	defer collection.Unlock()

	repo, err := collection.ByName(c.Params.ByName("name"))
	if err != nil {
		c.Fail(404, err)
		return
	}

	err = collection.LoadComplete(repo)
	if err != nil {
		c.Fail(500, err)
		return
	}

	verifier := &utils.GpgVerifier{}

	var (
		sources                      []string
		packageFiles, failedFiles    []string
		processedFiles, failedFiles2 []string
		reporter                     = &aptly.RecordingResultReporter{
			Warnings:     []string{},
			AddedLines:   []string{},
			RemovedLines: []string{},
		}
		list *deb.PackageList
	)

	if fileParam == "" {
		sources = []string{filepath.Join(context.UploadPath(), c.Params.ByName("dir"))}
	} else {
		sources = []string{filepath.Join(context.UploadPath(), c.Params.ByName("dir"), c.Params.ByName("file"))}
	}

	packageFiles, failedFiles = deb.CollectPackageFiles(sources, reporter)

	list, err = deb.NewPackageListFromRefList(repo.RefList(), context.CollectionFactory().PackageCollection(), nil)
	if err != nil {
		c.Fail(500, fmt.Errorf("unable to load packages: %s", err))
		return
	}

	processedFiles, failedFiles2, err = deb.ImportPackageFiles(list, packageFiles, forceReplace, verifier, context.PackagePool(),
		context.CollectionFactory().PackageCollection(), reporter, nil)
	failedFiles = append(failedFiles, failedFiles2...)

	if err != nil {
		c.Fail(500, fmt.Errorf("unable to import package files: %s", err))
		return
	}

	repo.UpdateRefList(deb.NewPackageRefListFromPackageList(list))

	err = context.CollectionFactory().LocalRepoCollection().Update(repo)
	if err != nil {
		c.Fail(500, fmt.Errorf("unable to save: %s", err))
		return
	}

	if !noRemove {
		processedFiles = utils.StrSliceDeduplicate(processedFiles)

		for _, file := range processedFiles {
			err := os.Remove(file)
			if err != nil {
				reporter.Warning("unable to remove file %s: %s", file, err)
			}
		}

		// atempt to remove dir, if it fails, that's fine: probably it's not empty
		os.Remove(filepath.Join(context.UploadPath(), c.Params.ByName("dir")))
	}

	if failedFiles == nil {
		failedFiles = []string{}
	}

	c.JSON(200, gin.H{
		"Report":      reporter,
		"FailedFiles": failedFiles,
	})
}
Beispiel #18
0
func aptlySnapshotPull(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 4 {
		cmd.Usage()
		return commander.ErrCommandError
	}

	noDeps := context.flags.Lookup("no-deps").Value.Get().(bool)
	noRemove := context.flags.Lookup("no-remove").Value.Get().(bool)

	// Load <name> snapshot
	snapshot, err := context.CollectionFactory().SnapshotCollection().ByName(args[0])
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	err = context.CollectionFactory().SnapshotCollection().LoadComplete(snapshot)
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	// Load <source> snapshot
	source, err := context.CollectionFactory().SnapshotCollection().ByName(args[1])
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	err = context.CollectionFactory().SnapshotCollection().LoadComplete(source)
	if err != nil {
		return fmt.Errorf("unable to pull: %s", err)
	}

	context.Progress().Printf("Dependencies would be pulled into snapshot:\n    %s\nfrom snapshot:\n    %s\nand result would be saved as new snapshot %s.\n",
		snapshot, source, args[2])

	// Convert snapshot to package list
	context.Progress().Printf("Loading packages (%d)...\n", snapshot.RefList().Len()+source.RefList().Len())
	packageList, err := deb.NewPackageListFromRefList(snapshot.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	sourcePackageList, err := deb.NewPackageListFromRefList(source.RefList(), context.CollectionFactory().PackageCollection(), context.Progress())
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	context.Progress().Printf("Building indexes...\n")
	packageList.PrepareIndex()
	sourcePackageList.PrepareIndex()

	// Calculate architectures
	var architecturesList []string

	if len(context.ArchitecturesList()) > 0 {
		architecturesList = context.ArchitecturesList()
	} else {
		architecturesList = packageList.Architectures(false)
	}

	sort.Strings(architecturesList)

	if len(architecturesList) == 0 {
		return fmt.Errorf("unable to determine list of architectures, please specify explicitly")
	}

	// Initial dependencies out of arguments
	initialDependencies := make([]deb.Dependency, len(args)-3)
	for i, arg := range args[3:] {
		initialDependencies[i], err = deb.ParseDependency(arg)
		if err != nil {
			return fmt.Errorf("unable to parse argument: %s", err)
		}
	}

	// Perform pull
	for _, arch := range architecturesList {
		dependencies := make([]deb.Dependency, len(initialDependencies), 2*len(initialDependencies))
		for i := range dependencies {
			dependencies[i] = initialDependencies[i]
			dependencies[i].Architecture = arch
		}

		// Go over list of initial dependencies + list of dependencies found
		for i := 0; i < len(dependencies); i++ {
			dep := dependencies[i]

			// Search for package that can satisfy dependencies
			pkg := sourcePackageList.Search(dep)
			if pkg == nil {
				context.Progress().ColoredPrintf("@y[!]@| @!Dependency %s can't be satisfied with source %s@|", &dep, source)
				continue
			}

			if !noRemove {
				// Remove all packages with the same name and architecture
				for p := packageList.Search(deb.Dependency{Architecture: pkg.Architecture, Pkg: pkg.Name}); p != nil; {
					packageList.Remove(p)
					context.Progress().ColoredPrintf("@r[-]@| %s removed", p)
					p = packageList.Search(deb.Dependency{Architecture: pkg.Architecture, Pkg: pkg.Name})
				}
			}

			// Add new discovered package
			packageList.Add(pkg)
			context.Progress().ColoredPrintf("@g[+]@| %s added", pkg)

			if noDeps {
				continue
			}

			// Find missing dependencies for single added package
			pL := deb.NewPackageList()
			pL.Add(pkg)

			var missing []deb.Dependency
			missing, err = pL.VerifyDependencies(context.DependencyOptions(), []string{arch}, packageList, nil)
			if err != nil {
				context.Progress().ColoredPrintf("@y[!]@| @!Error while verifying dependencies for pkg %s: %s@|", pkg, err)
			}

			// Append missing dependencies to the list of dependencies to satisfy
			for _, misDep := range missing {
				found := false
				for _, d := range dependencies {
					if d == misDep {
						found = true
						break
					}
				}

				if !found {
					dependencies = append(dependencies, misDep)
				}
			}
		}
	}

	if context.flags.Lookup("dry-run").Value.Get().(bool) {
		context.Progress().Printf("\nNot creating snapshot, as dry run was requested.\n")
	} else {
		// Create <destination> snapshot
		destination := deb.NewSnapshotFromPackageList(args[2], []*deb.Snapshot{snapshot, source}, packageList,
			fmt.Sprintf("Pulled into '%s' with '%s' as source, pull request was: '%s'", snapshot.Name, source.Name, strings.Join(args[3:], " ")))

		err = context.CollectionFactory().SnapshotCollection().Add(destination)
		if err != nil {
			return fmt.Errorf("unable to create snapshot: %s", err)
		}

		context.Progress().Printf("\nSnapshot %s successfully created.\nYou can run 'aptly publish snapshot %s' to publish snapshot as Debian repository.\n", destination.Name, destination.Name)
	}
	return err
}