Esempio n. 1
0
func aptlyRepoRemove(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 2 {
		cmd.Usage()
		return err
	}

	name := args[0]

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

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

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

	packageCollection := debian.NewPackageCollection(context.database)
	list, err := debian.NewPackageListFromRefList(repo.RefList(), packageCollection)
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

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

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

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

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

	return err
}
Esempio n. 2
0
func aptlyMirrorUpdate(cmd *commander.Command, args []string) error {
	var err error
	if len(args) != 1 {
		cmd.Usage()
		return err
	}

	name := args[0]

	repoCollection := debian.NewRemoteRepoCollection(context.database)
	repo, err := repoCollection.ByName(name)
	if err != nil {
		return fmt.Errorf("unable to update: %s", err)
	}

	err = repoCollection.LoadComplete(repo)
	if err != nil {
		return fmt.Errorf("unable to update: %s", err)
	}

	ignoreMismatch := cmd.Flag.Lookup("ignore-checksums").Value.Get().(bool)

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

	err = repo.Fetch(context.downloader, verifier)
	if err != nil {
		return fmt.Errorf("unable to update: %s", err)
	}

	packageCollection := debian.NewPackageCollection(context.database)

	err = repo.Download(context.downloader, packageCollection, context.packageRepository, ignoreMismatch)
	if err != nil {
		return fmt.Errorf("unable to update: %s", err)
	}

	err = repoCollection.Update(repo)
	if err != nil {
		return fmt.Errorf("unable to update: %s", err)
	}

	fmt.Printf("\nMirror `%s` has been successfully updated.\n", repo.Name)
	return err
}
Esempio n. 3
0
//ListPackagesRefList shows list of packages in PackageRefList
func ListPackagesRefList(reflist *debian.PackageRefList) (err error) {
	fmt.Printf("Packages:\n")

	packageCollection := debian.NewPackageCollection(context.database)

	err = reflist.ForEach(func(key []byte) error {
		p, err := packageCollection.ByKey(key)
		if err != nil {
			return err
		}
		fmt.Printf("  %s\n", p)
		return nil
	})
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	return
}
Esempio n. 4
0
func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 3 {
		cmd.Usage()
		return err
	}

	command := cmd.Name()

	localRepoCollection := debian.NewLocalRepoCollection(context.database)

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

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

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

	if command == "copy" || command == "move" {
		srcRepo, err = 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 = localRepoCollection.LoadComplete(srcRepo)
		if err != nil {
			return fmt.Errorf("unable to %s: %s", command, err)
		}

		srcRefList = srcRepo.RefList()
	} else if command == "import" {
		repoCollection := debian.NewRemoteRepoCollection(context.database)

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

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

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

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

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

	packageCollection := debian.NewPackageCollection(context.database)
	dstList, err := debian.NewPackageListFromRefList(dstRepo.RefList(), packageCollection)
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	srcList, err := debian.NewPackageListFromRefList(srcRefList, packageCollection)
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	srcList.PrepareIndex()

	var architecturesList []string

	withDeps := cmd.Flag.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 *debian.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 cmd.Flag.Lookup("dry-run").Value.Get().(bool) {
		context.progress.Printf("\nChanges not saved, as dry run has been requested.\n")
	} else {
		dstRepo.UpdateRefList(debian.NewPackageRefListFromPackageList(dstList))

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

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

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

	return err
}
Esempio n. 5
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{}

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

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

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

	packageCollection := debian.NewPackageCollection(context.database)
	list, err := debian.NewPackageListFromRefList(repo.RefList(), packageCollection)
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	packageFiles := []string{}

	for _, location := range args[1:] {
		info, err := os.Stat(location)
		if err != nil {
			context.progress.ColoredPrintf("@y[!]@| @!Unable to process %s: %s@|", location, err)
			continue
		}
		if info.IsDir() {
			err = filepath.Walk(location, func(path string, info os.FileInfo, err error) error {
				if err != nil {
					return err
				}
				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 debian.Stanza
			err    error
			p      *debian.Package
		)

		isSourcePackage := strings.HasSuffix(file, ".dsc")

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

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

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

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

		if isSourcePackage {
			p.Files = append(p.Files, debian.PackageFile{Filename: filepath.Base(file), Checksums: checksums})
		} else {
			p.Files = []debian.PackageFile{debian.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
		}

		processedFiles = append(processedFiles, file)

		// go over all files, except for the last one (.dsc/.deb itself)
		for i := 0; i < len(p.Files)-1; i++ {
			sourceFile := filepath.Join(filepath.Dir(file), filepath.Base(p.Files[i].Filename))
			err = context.packagePool.Import(sourceFile, p.Files[i].Checksums.MD5)
			if err != nil {
				context.progress.ColoredPrintf("@y[!]@| @!Unable to import file %s into pool: %s@|", sourceFile, err)
				break
			}

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

		err = 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)
	}

	repo.UpdateRefList(debian.NewPackageRefListFromPackageList(list))

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

	if cmd.Flag.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
}
Esempio n. 6
0
func aptlySnapshotDiff(cmd *commander.Command, args []string) error {
	var err error
	if len(args) != 2 {
		cmd.Usage()
		return err
	}

	onlyMatching := cmd.Flag.Lookup("only-matching").Value.Get().(bool)

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	packageCollection := debian.NewPackageCollection(context.database)

	// Load <name-a> snapshot
	snapshotA, err := snapshotCollection.ByName(args[0])
	if err != nil {
		return fmt.Errorf("unable to load snapshot A: %s", err)
	}

	err = snapshotCollection.LoadComplete(snapshotA)
	if err != nil {
		return fmt.Errorf("unable to load snapshot A: %s", err)
	}

	// Load <name-b> snapshot
	snapshotB, err := snapshotCollection.ByName(args[1])
	if err != nil {
		return fmt.Errorf("unable to load snapshot B: %s", err)
	}

	err = snapshotCollection.LoadComplete(snapshotB)
	if err != nil {
		return fmt.Errorf("unable to load snapshot B: %s", err)
	}

	// Calculate diff
	diff, err := snapshotA.RefList().Diff(snapshotB.RefList(), packageCollection)
	if err != nil {
		return fmt.Errorf("unable to calculate diff: %s", err)
	}

	if len(diff) == 0 {
		fmt.Printf("Snapshots are identical.\n")
	} else {
		fmt.Printf("  Arch   | Package                                  | Version in A                             | Version in B\n")
		for _, pdiff := range diff {
			if onlyMatching && (pdiff.Left == nil || pdiff.Right == nil) {
				continue
			}

			var verA, verB, pkg, arch, code string

			if pdiff.Left == nil {
				verA = "-"
				verB = pdiff.Right.Version
				pkg = pdiff.Right.Name
				arch = pdiff.Right.Architecture
			} else {
				pkg = pdiff.Left.Name
				arch = pdiff.Left.Architecture
				verA = pdiff.Left.Version
				if pdiff.Right == nil {
					verB = "-"
				} else {
					verB = pdiff.Right.Version
				}
			}

			if pdiff.Left == nil {
				code = "@g+@|"
			} else {
				if pdiff.Right == nil {
					code = "@r-@|"
				} else {
					code = "@y!@|"
				}
			}

			color.Printf(code+" %-6s | %-40s | %-40s | %-40s\n", arch, pkg, verA, verB)
		}
	}

	return err
}
Esempio n. 7
0
func aptlySnapshotPull(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 4 {
		cmd.Usage()
		return err
	}

	noDeps := cmd.Flag.Lookup("no-deps").Value.Get().(bool)

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	packageCollection := debian.NewPackageCollection(context.database)

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

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

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

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

	fmt.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
	fmt.Printf("Loading packages (%d)...\n", snapshot.RefList().Len()+source.RefList().Len())
	packageList, err := debian.NewPackageListFromRefList(snapshot.RefList(), packageCollection)
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	sourcePackageList, err := debian.NewPackageListFromRefList(source.RefList(), packageCollection)
	if err != nil {
		return fmt.Errorf("unable to load packages: %s", err)
	}

	fmt.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)
	}

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

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

	// Perform pull
	for _, arch := range architecturesList {
		dependencies := make([]debian.Dependency, len(initialDependencies), 128)
		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 {
				color.Printf("@y[!]@| @!Dependency %s can't be satisfied with source %s@|", &dep, source)
				fmt.Printf("\n")
				continue
			}

			// Remove all packages with the same name and architecture
			for p := packageList.Search(debian.Dependency{Architecture: arch, Pkg: pkg.Name}); p != nil; {
				packageList.Remove(p)
				color.Printf("@r[-]@| %s removed", p)
				fmt.Printf("\n")
				p = packageList.Search(debian.Dependency{Architecture: arch, Pkg: pkg.Name})
			}

			// Add new discovered package
			packageList.Add(pkg)
			color.Printf("@g[+]@| %s added", pkg)
			fmt.Printf("\n")

			if noDeps {
				continue
			}

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

			missing, err := pL.VerifyDependencies(context.dependencyOptions, []string{arch}, packageList)
			if err != nil {
				color.Printf("@y[!]@| @!Error while verifying dependencies for pkg %s: %s@|", pkg, err)
				fmt.Printf("\n")
			}

			// 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 cmd.Flag.Lookup("dry-run").Value.Get().(bool) {
		fmt.Printf("\nNot creating snapshot, as dry run was requested.\n")
	} else {
		// Create <destination> snapshot
		destination := debian.NewSnapshotFromPackageList(args[2], []*debian.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 = snapshotCollection.Add(destination)
		if err != nil {
			return fmt.Errorf("unable to create snapshot: %s", err)
		}

		fmt.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
}
Esempio n. 8
0
func aptlySnapshotVerify(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 1 {
		cmd.Usage()
		return err
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	packageCollection := debian.NewPackageCollection(context.database)

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

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

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

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

	for i := 1; i < len(snapshots); i++ {
		pL, err := debian.NewPackageListFromRefList(snapshots[i].RefList(), packageCollection)
		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")
	}

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

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

		sort.Strings(deps)

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

	return err
}
Esempio n. 9
0
func aptlyPublishSnapshot(cmd *commander.Command, args []string) error {
	var err error
	if len(args) < 1 || len(args) > 2 {
		cmd.Usage()
		return err
	}

	name := args[0]

	var prefix string
	if len(args) == 2 {
		prefix = args[1]
	} else {
		prefix = ""
	}

	publishedCollecton := debian.NewPublishedRepoCollection(context.database)

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	snapshot, err := snapshotCollection.ByName(name)
	if err != nil {
		return fmt.Errorf("unable to publish: %s", err)
	}

	err = snapshotCollection.LoadComplete(snapshot)
	if err != nil {
		return fmt.Errorf("unable to publish: %s", err)
	}

	var sourceRepo *debian.RemoteRepo

	if snapshot.SourceKind == "repo" && len(snapshot.SourceIDs) == 1 {
		repoCollection := debian.NewRemoteRepoCollection(context.database)

		sourceRepo, _ = repoCollection.ByUUID(snapshot.SourceIDs[0])
	}

	component := cmd.Flag.Lookup("component").Value.String()
	if component == "" {
		if sourceRepo != nil && len(sourceRepo.Components) == 1 {
			component = sourceRepo.Components[0]
		} else {
			component = "main"
		}
	}

	distribution := cmd.Flag.Lookup("distribution").Value.String()
	if distribution == "" {
		if sourceRepo != nil {
			distribution = sourceRepo.Distribution
		}

		if distribution == "" {
			return fmt.Errorf("unable to guess distribution name, please specify explicitly")
		}
	}

	published, err := debian.NewPublishedRepo(prefix, distribution, component, context.architecturesList, snapshot)
	if err != nil {
		return fmt.Errorf("unable to publish: %s", err)
	}

	duplicate := publishedCollecton.CheckDuplicate(published)
	if duplicate != nil {
		publishedCollecton.LoadComplete(duplicate, snapshotCollection)
		return fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate)
	}

	signer, err := getSigner(cmd)
	if err != nil {
		return fmt.Errorf("unable to initialize GPG signer: %s", err)
	}

	packageCollection := debian.NewPackageCollection(context.database)
	err = published.Publish(context.packageRepository, packageCollection, signer)
	if err != nil {
		return fmt.Errorf("unable to publish: %s", err)
	}

	err = publishedCollecton.Add(published)
	if err != nil {
		return fmt.Errorf("unable to save to DB: %s", err)
	}

	if prefix != "" && !strings.HasSuffix(prefix, "/") {
		prefix += "/"
	}

	fmt.Printf("\nSnapshot %s has been successfully published.\nPlease setup your webserver to serve directory '%s' with autoindexing.\n",
		snapshot.Name, context.packageRepository.PublicPath())
	fmt.Printf("Now you can add following line to apt sources:\n")
	fmt.Printf("  deb http://your-server/%s %s %s\n", prefix, distribution, component)
	fmt.Printf("Don't forget to add your GPG key to apt with apt-key.\n")
	fmt.Printf("\nYou can also use `aptly serve` to publish your repositories over HTTP quickly.\n")

	return err
}
Esempio n. 10
0
// aptly db cleanup
func aptlyDbCleanup(cmd *commander.Command, args []string) error {
	var err error

	if len(args) != 0 {
		cmd.Usage()
		return err
	}

	// collect information about references packages...
	existingPackageRefs := debian.NewPackageRefList()

	context.downloader.GetProgress().Printf("Loading mirrors and snapshots...\n")
	repoCollection := debian.NewRemoteRepoCollection(context.database)
	err = repoCollection.ForEach(func(repo *debian.RemoteRepo) error {
		err := repoCollection.LoadComplete(repo)
		if err != nil {
			return err
		}
		existingPackageRefs = existingPackageRefs.Merge(repo.RefList(), false)
		return nil
	})
	if err != nil {
		return err
	}

	snapshotCollection := debian.NewSnapshotCollection(context.database)
	err = snapshotCollection.ForEach(func(snapshot *debian.Snapshot) error {
		err := snapshotCollection.LoadComplete(snapshot)
		if err != nil {
			return err
		}
		existingPackageRefs = existingPackageRefs.Merge(snapshot.RefList(), false)
		return nil
	})
	if err != nil {
		return err
	}

	// ... and compare it to the list of all packages
	context.downloader.GetProgress().Printf("Loading list of all packages...\n")
	packageCollection := debian.NewPackageCollection(context.database)
	allPackageRefs := packageCollection.AllPackageRefs()

	toDelete := allPackageRefs.Substract(existingPackageRefs)

	// delete packages that are no longer referenced
	context.downloader.GetProgress().Printf("Deleting unreferenced packages (%d)...\n", toDelete.Len())

	context.database.StartBatch()
	err = toDelete.ForEach(func(ref []byte) error {
		return packageCollection.DeleteByKey(ref)
	})
	if err != nil {
		return err
	}

	err = context.database.FinishBatch()
	if err != nil {
		return fmt.Errorf("unable to write to DB: %s", err)
	}

	// now, build a list of files that should be present in Repository (package pool)
	context.downloader.GetProgress().Printf("Building list of files referenced by packages...\n")
	referencedFiles := make([]string, 0, existingPackageRefs.Len())
	context.downloader.GetProgress().InitBar(int64(existingPackageRefs.Len()), false)

	err = existingPackageRefs.ForEach(func(key []byte) error {
		pkg, err := packageCollection.ByKey(key)
		if err != nil {
			return err
		}
		paths, err := pkg.FilepathList(context.packageRepository)
		if err != nil {
			return err
		}
		referencedFiles = append(referencedFiles, paths...)
		context.downloader.GetProgress().AddBar(1)

		return nil
	})
	if err != nil {
		return err
	}

	sort.Strings(referencedFiles)
	context.downloader.GetProgress().ShutdownBar()

	// build a list of files in the package pool
	context.downloader.GetProgress().Printf("Building list of files in package pool...\n")
	existingFiles, err := context.packageRepository.PoolFilepathList(context.downloader.GetProgress())
	if err != nil {
		return fmt.Errorf("unable to collect file paths: %s", err)
	}

	// find files which are in the pool but not referenced by packages
	filesToDelete := utils.StrSlicesSubstract(existingFiles, referencedFiles)

	// delete files that are no longer referenced
	context.downloader.GetProgress().Printf("Deleting unreferenced files (%d)...\n", len(filesToDelete))

	if len(filesToDelete) > 0 {
		context.downloader.GetProgress().InitBar(int64(len(filesToDelete)), false)
		totalSize := int64(0)
		for _, file := range filesToDelete {
			size, err := context.packageRepository.PoolRemove(file)
			if err != nil {
				return err
			}

			context.downloader.GetProgress().AddBar(1)
			totalSize += size
		}
		context.downloader.GetProgress().ShutdownBar()

		context.downloader.GetProgress().Printf("Disk space freed: %.2f GiB...\n", float64(totalSize)/1024.0/1024.0/1024.0)
	}
	return err
}