mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-31 04:30:44 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 68814ff1f0 | |||
| d44ae522ac | |||
| 8f2b335409 | |||
| 9ecbc844e7 | |||
| 9e91ee4c4a | |||
| b7969c7a2d | |||
| 2a5992c74e | |||
| 2827620cfe | |||
| 8dc61cf362 | |||
| 4a9ddbdc34 | |||
| c316ea9b73 | |||
| d027a251ba | |||
| 16b6348710 | |||
| 1c1abe6b10 | |||
| c4bfbe52ca | |||
| c723fea807 | |||
| 0d31298f37 | |||
| bba6bd7db5 | |||
| faeaad0378 |
@@ -155,7 +155,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
name: ["Debian 13/trixie", "Debian 12/bookworm", "Debian 11/bullseye", "Ubuntu 24.04", "Ubuntu 22.04", "Ubuntu 20.04"]
|
||||
name: ["Debian 13/trixie", "Debian 12/bookworm", "Debian 11/bullseye", "Ubuntu 26.04", "Ubuntu 24.04", "Ubuntu 22.04", "Ubuntu 20.04"]
|
||||
arch: ["amd64", "i386" , "arm64" , "armhf"]
|
||||
include:
|
||||
- name: "Debian 13/trixie"
|
||||
@@ -167,6 +167,9 @@ jobs:
|
||||
- name: "Debian 11/bullseye"
|
||||
suite: bullseye
|
||||
image: debian:bullseye-slim
|
||||
- name: "Ubuntu 26.04"
|
||||
suite: resolute
|
||||
image: ubuntu:26.04
|
||||
- name: "Ubuntu 24.04"
|
||||
suite: noble
|
||||
image: ubuntu:24.04
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ Please report unacceptable behavior on [https://github.com/aptly-dev/aptly/discu
|
||||
### List of Repositories
|
||||
|
||||
* [aptly-dev/aptly](https://github.com/aptly-dev/aptly) - aptly source code, functional tests, man page
|
||||
* [apty-dev/aptly-dev.github.io](https://github.com/aptly-dev/aptly-dev.github.io) - aptly website (https://www.aptly.info/)
|
||||
* [aptly-dev/aptly-dev.github.io](https://github.com/aptly-dev/aptly-dev.github.io) - aptly website (https://www.aptly.info/)
|
||||
* [aptly-dev/aptly-fixture-db](https://github.com/aptly-dev/aptly-fixture-db) & [aptly-dev/aptly-fixture-pool](https://github.com/aptly-dev/aptly-fixture-pool) provide
|
||||
fixtures for aptly functional tests
|
||||
|
||||
@@ -137,7 +137,7 @@ make docker-unit-tests
|
||||
|
||||
In order to run aptly system tests, enter the following:
|
||||
```
|
||||
make docker-system-tests
|
||||
make docker-system-test
|
||||
```
|
||||
|
||||
#### Running golangci-lint
|
||||
|
||||
@@ -241,4 +241,4 @@ clean: ## remove local build and module cache
|
||||
rm -f unit.out aptly.test VERSION docs/docs.go docs/swagger.json docs/swagger.yaml docs/swagger.conf
|
||||
find system/ -type d -name __pycache__ -exec rm -rf {} \; 2>/dev/null || true
|
||||
|
||||
.PHONY: help man prepare swagger version binaries build docker-release docker-system-tests docker-unit-test docker-lint docker-build docker-image docker-man docker-shell docker-serve clean releasetype dpkg serve flake8
|
||||
.PHONY: help man prepare swagger version binaries build docker-release docker-system-test docker-unit-test docker-lint docker-build docker-image docker-man docker-shell docker-serve clean releasetype dpkg serve flake8
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ type gpgDeleteKeyParams struct {
|
||||
// @Summary Add GPG Keys
|
||||
// @Description **Adds GPG keys to aptly keyring**
|
||||
// @Description
|
||||
// @Description Add GPG public keys for veryfing remote repositories for mirroring.
|
||||
// @Description Add GPG public keys for verifying remote repositories for mirroring.
|
||||
// @Description
|
||||
// @Description Keys can be added in two ways:
|
||||
// @Description * By providing the ASCII armord key in `GpgKeyArmor` (leave Keyserver and GpgKeyID empty)
|
||||
|
||||
+1
-1
@@ -497,7 +497,7 @@ func apiMirrorsEdit(c *gin.Context) {
|
||||
type mirrorUpdateParams struct {
|
||||
// Change mirror name to `Name`
|
||||
Name string ` json:"Name" example:"mirror1"`
|
||||
// Gpg keyring(s) for verifing Release file
|
||||
// Gpg keyring(s) for verifying Release file
|
||||
Keyrings []string ` json:"Keyrings" example:"trustedkeys.gpg"`
|
||||
// Set "true" to ignore checksum errors
|
||||
IgnoreChecksums bool ` json:"IgnoreChecksums"`
|
||||
|
||||
+304
-201
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -124,7 +125,7 @@ func apiPublishList(c *gin.Context) {
|
||||
// @Description See also: `aptly publish show`
|
||||
// @Tags Publish
|
||||
// @Produce json
|
||||
// @Param prefix path string true "publishing prefix, use `:.` instead of `.` because it is ambigious in URLs"
|
||||
// @Param prefix path string true "publishing prefix, use `:.` instead of `.` because it is ambiguous in URLs"
|
||||
// @Param distribution path string true "distribution name"
|
||||
// @Success 200 {object} deb.PublishedRepo
|
||||
// @Failure 404 {object} Error "Published repository not found"
|
||||
@@ -298,11 +299,25 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
||||
multiDist = *b.MultiDist
|
||||
}
|
||||
|
||||
collection := collectionFactory.PublishedRepoCollection()
|
||||
// Pre-register the published repo key in resources so that concurrent
|
||||
// POST requests for the same prefix/distribution are serialized by the
|
||||
// task queue rather than racing on CheckDuplicate + Add.
|
||||
if b.Distribution != "" {
|
||||
storagePrefix := prefix
|
||||
if storage != "" {
|
||||
storagePrefix = storage + ":" + prefix
|
||||
}
|
||||
resources = append(resources, "U"+storagePrefix+">>"+b.Distribution)
|
||||
} else {
|
||||
log.Printf("distribution not specified for publish to prefix '%s' - unable to lock ", prefix)
|
||||
}
|
||||
|
||||
taskName := fmt.Sprintf("Publish %s repository %s/%s with components \"%s\" and sources \"%s\"",
|
||||
b.SourceKind, param, b.Distribution, strings.Join(components, `", "`), strings.Join(names, `", "`))
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(out aptly.Progress, detail *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
taskDetail := task.PublishDetail{
|
||||
Detail: detail,
|
||||
}
|
||||
@@ -314,10 +329,10 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
||||
for _, source := range sources {
|
||||
switch s := source.(type) {
|
||||
case *deb.Snapshot:
|
||||
snapshotCollection := collectionFactory.SnapshotCollection()
|
||||
snapshotCollection := taskCollectionFactory.SnapshotCollection()
|
||||
err = snapshotCollection.LoadComplete(s)
|
||||
case *deb.LocalRepo:
|
||||
localCollection := collectionFactory.LocalRepoCollection()
|
||||
localCollection := taskCollectionFactory.LocalRepoCollection()
|
||||
err = localCollection.LoadComplete(s)
|
||||
default:
|
||||
err = fmt.Errorf("unexpected type for source: %T", source)
|
||||
@@ -327,13 +342,11 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
published, err := deb.NewPublishedRepo(storage, prefix, b.Distribution, b.Architectures, components, sources, collectionFactory, multiDist)
|
||||
published, err := deb.NewPublishedRepo(storage, prefix, b.Distribution, b.Architectures, components, sources, taskCollectionFactory, multiDist)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to publish: %s", err)
|
||||
}
|
||||
|
||||
resources = append(resources, string(published.Key()))
|
||||
|
||||
if b.Origin != "" {
|
||||
published.Origin = b.Origin
|
||||
}
|
||||
@@ -367,18 +380,18 @@ func apiPublishRepoOrSnapshot(c *gin.Context) {
|
||||
published.Version = b.Version
|
||||
}
|
||||
|
||||
duplicate := collection.CheckDuplicate(published)
|
||||
duplicate := taskCollection.CheckDuplicate(published)
|
||||
if duplicate != nil {
|
||||
_ = collectionFactory.PublishedRepoCollection().LoadComplete(duplicate, collectionFactory)
|
||||
_ = taskCollectionFactory.PublishedRepoCollection().LoadComplete(duplicate, taskCollectionFactory)
|
||||
return &task.ProcessReturnValue{Code: http.StatusBadRequest, Value: nil}, fmt.Errorf("prefix/distribution already used by another published repo: %s", duplicate)
|
||||
}
|
||||
|
||||
err = published.Publish(context.PackagePool(), context, collectionFactory, signer, publishOutput, b.ForceOverwrite, context.SkelPath())
|
||||
err = published.Publish(context.PackagePool(), context, taskCollectionFactory, signer, publishOutput, b.ForceOverwrite, context.SkelPath())
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to publish: %s", err)
|
||||
}
|
||||
|
||||
err = collection.Add(published)
|
||||
err = taskCollection.Add(published)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to save to DB: %s", err)
|
||||
}
|
||||
@@ -458,6 +471,7 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
||||
collectionFactory := context.NewCollectionFactory()
|
||||
collection := collectionFactory.PublishedRepoCollection()
|
||||
snapshotCollection := collectionFactory.SnapshotCollection()
|
||||
localRepoCollection := collectionFactory.LocalRepoCollection()
|
||||
|
||||
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
@@ -465,64 +479,78 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
resources := []string{string(published.Key())}
|
||||
|
||||
if published.SourceKind == deb.SourceLocalRepo {
|
||||
if len(b.Snapshots) > 0 {
|
||||
AbortWithJSONError(c, http.StatusBadRequest, fmt.Errorf("snapshots shouldn't be given when updating local repo"))
|
||||
return
|
||||
}
|
||||
} else if published.SourceKind == deb.SourceSnapshot {
|
||||
for _, snapshotInfo := range b.Snapshots {
|
||||
_, err2 := snapshotCollection.ByName(snapshotInfo.Name)
|
||||
for _, uuid := range published.Sources {
|
||||
repo, err2 := localRepoCollection.ByUUID(uuid)
|
||||
if err2 != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, err2)
|
||||
return
|
||||
}
|
||||
resources = append(resources, string(repo.Key()))
|
||||
}
|
||||
} else if published.SourceKind == deb.SourceSnapshot {
|
||||
for _, snapshotInfo := range b.Snapshots {
|
||||
snapshot, err2 := snapshotCollection.ByName(snapshotInfo.Name)
|
||||
if err2 != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, err2)
|
||||
return
|
||||
}
|
||||
resources = append(resources, string(snapshot.ResourceKey()))
|
||||
}
|
||||
} else {
|
||||
AbortWithJSONError(c, http.StatusInternalServerError, fmt.Errorf("unknown published repository type"))
|
||||
return
|
||||
}
|
||||
|
||||
if b.SkipContents != nil {
|
||||
published.SkipContents = *b.SkipContents
|
||||
}
|
||||
|
||||
if b.SkipBz2 != nil {
|
||||
published.SkipBz2 = *b.SkipBz2
|
||||
}
|
||||
|
||||
if b.AcquireByHash != nil {
|
||||
published.AcquireByHash = *b.AcquireByHash
|
||||
}
|
||||
|
||||
if b.SignedBy != nil {
|
||||
published.SignedBy = *b.SignedBy
|
||||
}
|
||||
|
||||
if b.MultiDist != nil {
|
||||
published.MultiDist = *b.MultiDist
|
||||
}
|
||||
|
||||
if b.Label != nil {
|
||||
published.Label = *b.Label
|
||||
}
|
||||
|
||||
if b.Origin != nil {
|
||||
published.Origin = *b.Origin
|
||||
}
|
||||
|
||||
if b.Version != nil {
|
||||
published.Version = *b.Version
|
||||
}
|
||||
|
||||
resources := []string{string(published.Key())}
|
||||
// Field mutations and fresh DB load are deferred to inside the task so
|
||||
// they always operate on a consistent state after the lock is held.
|
||||
taskName := fmt.Sprintf("Update published %s repository %s/%s", published.SourceKind, published.StoragePrefix(), published.Distribution)
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(out aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
err = collection.LoadComplete(published, collectionFactory)
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
published, err := taskCollection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = taskCollection.LoadComplete(published, taskCollectionFactory)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
// Apply field mutations on the freshly loaded object.
|
||||
if b.SkipContents != nil {
|
||||
published.SkipContents = *b.SkipContents
|
||||
}
|
||||
if b.SkipBz2 != nil {
|
||||
published.SkipBz2 = *b.SkipBz2
|
||||
}
|
||||
if b.AcquireByHash != nil {
|
||||
published.AcquireByHash = *b.AcquireByHash
|
||||
}
|
||||
if b.SignedBy != nil {
|
||||
published.SignedBy = *b.SignedBy
|
||||
}
|
||||
if b.MultiDist != nil {
|
||||
published.MultiDist = *b.MultiDist
|
||||
}
|
||||
if b.Label != nil {
|
||||
published.Label = *b.Label
|
||||
}
|
||||
if b.Origin != nil {
|
||||
published.Origin = *b.Origin
|
||||
}
|
||||
if b.Version != nil {
|
||||
published.Version = *b.Version
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := revision.Sources
|
||||
|
||||
@@ -534,17 +562,17 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
result, err := published.Update(collectionFactory, out)
|
||||
result, err := published.Update(taskCollectionFactory, out)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = published.Publish(context.PackagePool(), context, collectionFactory, signer, out, b.ForceOverwrite, context.SkelPath())
|
||||
err = published.Publish(context.PackagePool(), context, taskCollectionFactory, signer, out, b.ForceOverwrite, context.SkelPath())
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = collection.Update(published)
|
||||
err = taskCollection.Update(published)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to save to DB: %s", err)
|
||||
}
|
||||
@@ -552,7 +580,7 @@ func apiPublishUpdateSwitch(c *gin.Context) {
|
||||
if b.SkipCleanup == nil || !*b.SkipCleanup {
|
||||
cleanComponents := make([]string, 0, len(result.UpdatedSources)+len(result.RemovedSources))
|
||||
cleanComponents = append(append(cleanComponents, result.UpdatedComponents()...), result.RemovedComponents()...)
|
||||
err = collection.CleanupPrefixComponentFiles(context, published, cleanComponents, collectionFactory, out)
|
||||
err = taskCollection.CleanupPrefixComponentFiles(context, published, cleanComponents, taskCollectionFactory, out)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
@@ -602,8 +630,11 @@ func apiPublishDrop(c *gin.Context) {
|
||||
resources := []string{string(published.Key())}
|
||||
taskName := fmt.Sprintf("Delete published %s repository %s/%s", published.SourceKind, published.StoragePrefix(), published.Distribution)
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(out aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
err := collection.Remove(context, storage, prefix, distribution,
|
||||
collectionFactory, out, force, skipCleanup)
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
err := taskCollection.Remove(context, storage, prefix, distribution,
|
||||
taskCollectionFactory, out, force, skipCleanup)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to drop: %s", err)
|
||||
}
|
||||
@@ -639,43 +670,52 @@ func apiPublishAddSource(c *gin.Context) {
|
||||
storage, prefix := deb.ParsePrefix(param)
|
||||
distribution := slashEscape(c.Params.ByName("distribution"))
|
||||
|
||||
if c.Bind(&b) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
collectionFactory := context.NewCollectionFactory()
|
||||
collection := collectionFactory.PublishedRepoCollection()
|
||||
|
||||
// Load shallowly (no LoadComplete) to verify existence and obtain the
|
||||
// resource key and task name. The actual mutation is performed inside
|
||||
// the task on a freshly loaded copy to prevent lost-update races.
|
||||
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, fmt.Errorf("unable to create: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = collection.LoadComplete(published, collectionFactory)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusInternalServerError, fmt.Errorf("unable to create: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
if c.Bind(&b) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := revision.Sources
|
||||
|
||||
component := b.Component
|
||||
name := b.Name
|
||||
|
||||
_, exists := sources[component]
|
||||
if exists {
|
||||
AbortWithJSONError(c, http.StatusBadRequest, fmt.Errorf("unable to create: Component '%s' already exists", component))
|
||||
return
|
||||
}
|
||||
|
||||
sources[component] = name
|
||||
|
||||
resources := []string{string(published.Key())}
|
||||
taskName := fmt.Sprintf("Update published %s repository %s/%s", published.SourceKind, published.StoragePrefix(), published.Distribution)
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(_ aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
err = collection.Update(published)
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
published, err := taskCollection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("unable to create: %s", err)
|
||||
}
|
||||
|
||||
err = taskCollection.LoadComplete(published, taskCollectionFactory)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to create: %s", err)
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := revision.Sources
|
||||
|
||||
component := b.Component
|
||||
name := b.Name
|
||||
|
||||
_, exists := sources[component]
|
||||
if exists {
|
||||
return &task.ProcessReturnValue{Code: http.StatusBadRequest, Value: nil}, fmt.Errorf("unable to create: Component '%s' already exists", component)
|
||||
}
|
||||
|
||||
sources[component] = name
|
||||
|
||||
err = taskCollection.Update(published)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to save to DB: %s", err)
|
||||
}
|
||||
@@ -757,39 +797,48 @@ func apiPublishSetSources(c *gin.Context) {
|
||||
storage, prefix := deb.ParsePrefix(param)
|
||||
distribution := slashEscape(c.Params.ByName("distribution"))
|
||||
|
||||
if c.Bind(&b) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
collectionFactory := context.NewCollectionFactory()
|
||||
collection := collectionFactory.PublishedRepoCollection()
|
||||
|
||||
// Load shallowly for 404 check, resource key, and task name.
|
||||
// Full load and mutation happen inside the task.
|
||||
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, fmt.Errorf("unable to update: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = collection.LoadComplete(published, collectionFactory)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusInternalServerError, fmt.Errorf("unable to update: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
if c.Bind(&b) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := make(map[string]string, len(b))
|
||||
revision.Sources = sources
|
||||
|
||||
for _, source := range b {
|
||||
component := source.Component
|
||||
name := source.Name
|
||||
sources[component] = name
|
||||
}
|
||||
|
||||
resources := []string{string(published.Key())}
|
||||
taskName := fmt.Sprintf("Update published %s repository %s/%s", published.SourceKind, published.StoragePrefix(), published.Distribution)
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(_ aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
err = collection.Update(published)
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
published, err := taskCollection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = taskCollection.LoadComplete(published, taskCollectionFactory)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := make(map[string]string, len(b))
|
||||
revision.Sources = sources
|
||||
|
||||
for _, source := range b {
|
||||
component := source.Component
|
||||
name := source.Name
|
||||
sources[component] = name
|
||||
}
|
||||
|
||||
err = taskCollection.Update(published)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to save to DB: %s", err)
|
||||
}
|
||||
@@ -822,24 +871,33 @@ func apiPublishDropChanges(c *gin.Context) {
|
||||
collectionFactory := context.NewCollectionFactory()
|
||||
collection := collectionFactory.PublishedRepoCollection()
|
||||
|
||||
// Load shallowly for 404 check, resource key, and task name.
|
||||
// Full load and DropRevision happen inside the task.
|
||||
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, fmt.Errorf("unable to delete: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = collection.LoadComplete(published, collectionFactory)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusInternalServerError, fmt.Errorf("unable to delete: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
published.DropRevision()
|
||||
|
||||
resources := []string{string(published.Key())}
|
||||
taskName := fmt.Sprintf("Update published %s repository %s/%s", published.SourceKind, published.StoragePrefix(), published.Distribution)
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(_ aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
err = collection.Update(published)
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
published, err := taskCollection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("unable to delete: %s", err)
|
||||
}
|
||||
|
||||
err = taskCollection.LoadComplete(published, taskCollectionFactory)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to delete: %s", err)
|
||||
}
|
||||
|
||||
published.DropRevision()
|
||||
|
||||
err = taskCollection.Update(published)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to save to DB: %s", err)
|
||||
}
|
||||
@@ -875,51 +933,58 @@ func apiPublishUpdateSource(c *gin.Context) {
|
||||
param := slashEscape(c.Params.ByName("prefix"))
|
||||
storage, prefix := deb.ParsePrefix(param)
|
||||
distribution := slashEscape(c.Params.ByName("distribution"))
|
||||
component := slashEscape(c.Params.ByName("component"))
|
||||
urlComponent := slashEscape(c.Params.ByName("component"))
|
||||
|
||||
// Default component to the URL path segment; the body may rename it.
|
||||
b.Component = urlComponent
|
||||
if c.Bind(&b) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
collectionFactory := context.NewCollectionFactory()
|
||||
collection := collectionFactory.PublishedRepoCollection()
|
||||
|
||||
// Load shallowly for 404 check, resource key, and task name.
|
||||
// Full load and mutation happen inside the task.
|
||||
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, fmt.Errorf("unable to update: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = collection.LoadComplete(published, collectionFactory)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusInternalServerError, fmt.Errorf("unable to update: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := revision.Sources
|
||||
|
||||
_, exists := sources[component]
|
||||
if !exists {
|
||||
AbortWithJSONError(c, http.StatusNotFound, fmt.Errorf("unable to update: Component '%s' does not exist", component))
|
||||
return
|
||||
}
|
||||
|
||||
b.Component = component
|
||||
b.Name = revision.Sources[component]
|
||||
|
||||
if c.Bind(&b) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if b.Component != component {
|
||||
delete(sources, component)
|
||||
}
|
||||
|
||||
component = b.Component
|
||||
name := b.Name
|
||||
sources[component] = name
|
||||
|
||||
resources := []string{string(published.Key())}
|
||||
taskName := fmt.Sprintf("Update published %s repository %s/%s", published.SourceKind, published.StoragePrefix(), published.Distribution)
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(_ aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
err = collection.Update(published)
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
published, err := taskCollection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = taskCollection.LoadComplete(published, taskCollectionFactory)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := revision.Sources
|
||||
|
||||
_, exists := sources[urlComponent]
|
||||
if !exists {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("unable to update: Component '%s' does not exist", urlComponent)
|
||||
}
|
||||
|
||||
if b.Component != urlComponent {
|
||||
delete(sources, urlComponent)
|
||||
}
|
||||
|
||||
newComponent := b.Component
|
||||
name := b.Name
|
||||
sources[newComponent] = name
|
||||
|
||||
err = taskCollection.Update(published)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to save to DB: %s", err)
|
||||
}
|
||||
@@ -956,33 +1021,41 @@ func apiPublishRemoveSource(c *gin.Context) {
|
||||
collectionFactory := context.NewCollectionFactory()
|
||||
collection := collectionFactory.PublishedRepoCollection()
|
||||
|
||||
// Load shallowly for 404 check, resource key, and task name.
|
||||
// Full load and mutation happen inside the task.
|
||||
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, fmt.Errorf("unable to delete: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = collection.LoadComplete(published, collectionFactory)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusInternalServerError, fmt.Errorf("unable to delete: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := revision.Sources
|
||||
|
||||
_, exists := sources[component]
|
||||
if !exists {
|
||||
AbortWithJSONError(c, http.StatusNotFound, fmt.Errorf("unable to delete: Component '%s' does not exist", component))
|
||||
return
|
||||
}
|
||||
|
||||
delete(sources, component)
|
||||
|
||||
resources := []string{string(published.Key())}
|
||||
taskName := fmt.Sprintf("Update published %s repository %s/%s", published.SourceKind, published.StoragePrefix(), published.Distribution)
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(_ aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
err = collection.Update(published)
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
published, err := taskCollection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("unable to delete: %s", err)
|
||||
}
|
||||
|
||||
err = taskCollection.LoadComplete(published, taskCollectionFactory)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to delete: %s", err)
|
||||
}
|
||||
|
||||
revision := published.ObtainRevision()
|
||||
sources := revision.Sources
|
||||
|
||||
_, exists := sources[component]
|
||||
if !exists {
|
||||
return &task.ProcessReturnValue{Code: http.StatusNotFound, Value: nil}, fmt.Errorf("unable to delete: Component '%s' does not exist", component)
|
||||
}
|
||||
|
||||
delete(sources, component)
|
||||
|
||||
err = taskCollection.Update(published)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to save to DB: %s", err)
|
||||
}
|
||||
@@ -1054,64 +1127,94 @@ func apiPublishUpdate(c *gin.Context) {
|
||||
collectionFactory := context.NewCollectionFactory()
|
||||
collection := collectionFactory.PublishedRepoCollection()
|
||||
|
||||
// Load shallowly for 404 check, resource key, and task name.
|
||||
// Full load and field mutations happen inside the task.
|
||||
published, err := collection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, fmt.Errorf("unable to update: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
err = collection.LoadComplete(published, collectionFactory)
|
||||
if err != nil {
|
||||
AbortWithJSONError(c, http.StatusInternalServerError, fmt.Errorf("unable to update: %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
if b.SkipContents != nil {
|
||||
published.SkipContents = *b.SkipContents
|
||||
}
|
||||
|
||||
if b.SkipBz2 != nil {
|
||||
published.SkipBz2 = *b.SkipBz2
|
||||
}
|
||||
|
||||
if b.AcquireByHash != nil {
|
||||
published.AcquireByHash = *b.AcquireByHash
|
||||
}
|
||||
|
||||
if b.SignedBy != nil {
|
||||
published.SignedBy = *b.SignedBy
|
||||
}
|
||||
|
||||
if b.MultiDist != nil {
|
||||
published.MultiDist = *b.MultiDist
|
||||
}
|
||||
|
||||
if b.Label != nil {
|
||||
published.Label = *b.Label
|
||||
}
|
||||
|
||||
if b.Origin != nil {
|
||||
published.Origin = *b.Origin
|
||||
}
|
||||
|
||||
if b.Version != nil {
|
||||
published.Version = *b.Version
|
||||
}
|
||||
|
||||
resources := []string{string(published.Key())}
|
||||
|
||||
// Lock source repos / snapshots the same way apiPublishUpdateSwitch does,
|
||||
// because published.Update() reads from them and concurrent modification
|
||||
// would produce an inconsistent view.
|
||||
snapshotCollection := collectionFactory.SnapshotCollection()
|
||||
localRepoCollection := collectionFactory.LocalRepoCollection()
|
||||
|
||||
if published.SourceKind == deb.SourceLocalRepo {
|
||||
for _, uuid := range published.Sources {
|
||||
repo, err2 := localRepoCollection.ByUUID(uuid)
|
||||
if err2 != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, err2)
|
||||
return
|
||||
}
|
||||
resources = append(resources, string(repo.Key()))
|
||||
}
|
||||
} else if published.SourceKind == deb.SourceSnapshot {
|
||||
for _, uuid := range published.Sources {
|
||||
snapshot, err2 := snapshotCollection.ByUUID(uuid)
|
||||
if err2 != nil {
|
||||
AbortWithJSONError(c, http.StatusNotFound, err2)
|
||||
return
|
||||
}
|
||||
resources = append(resources, string(snapshot.ResourceKey()))
|
||||
}
|
||||
}
|
||||
|
||||
taskName := fmt.Sprintf("Update published %s repository %s/%s", published.SourceKind, published.StoragePrefix(), published.Distribution)
|
||||
maybeRunTaskInBackground(c, taskName, resources, func(out aptly.Progress, _ *task.Detail) (*task.ProcessReturnValue, error) {
|
||||
result, err := published.Update(collectionFactory, out)
|
||||
taskCollectionFactory := context.NewCollectionFactory()
|
||||
taskCollection := taskCollectionFactory.PublishedRepoCollection()
|
||||
|
||||
published, err := taskCollection.ByStoragePrefixDistribution(storage, prefix, distribution)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = published.Publish(context.PackagePool(), context, collectionFactory, signer, out, b.ForceOverwrite, context.SkelPath())
|
||||
err = taskCollection.LoadComplete(published, taskCollectionFactory)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = collection.Update(published)
|
||||
// Apply field mutations on the freshly loaded object.
|
||||
if b.SkipContents != nil {
|
||||
published.SkipContents = *b.SkipContents
|
||||
}
|
||||
if b.SkipBz2 != nil {
|
||||
published.SkipBz2 = *b.SkipBz2
|
||||
}
|
||||
if b.AcquireByHash != nil {
|
||||
published.AcquireByHash = *b.AcquireByHash
|
||||
}
|
||||
if b.SignedBy != nil {
|
||||
published.SignedBy = *b.SignedBy
|
||||
}
|
||||
if b.MultiDist != nil {
|
||||
published.MultiDist = *b.MultiDist
|
||||
}
|
||||
if b.Label != nil {
|
||||
published.Label = *b.Label
|
||||
}
|
||||
if b.Origin != nil {
|
||||
published.Origin = *b.Origin
|
||||
}
|
||||
if b.Version != nil {
|
||||
published.Version = *b.Version
|
||||
}
|
||||
|
||||
result, err := published.Update(taskCollectionFactory, out)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = published.Publish(context.PackagePool(), context, taskCollectionFactory, signer, out, b.ForceOverwrite, context.SkelPath())
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
err = taskCollection.Update(published)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to save to DB: %s", err)
|
||||
}
|
||||
@@ -1119,7 +1222,7 @@ func apiPublishUpdate(c *gin.Context) {
|
||||
if b.SkipCleanup == nil || !*b.SkipCleanup {
|
||||
cleanComponents := make([]string, 0, len(result.UpdatedSources)+len(result.RemovedSources))
|
||||
cleanComponents = append(append(cleanComponents, result.UpdatedComponents()...), result.RemovedComponents()...)
|
||||
err = collection.CleanupPrefixComponentFiles(context, published, cleanComponents, collectionFactory, out)
|
||||
err = taskCollection.CleanupPrefixComponentFiles(context, published, cleanComponents, taskCollectionFactory, out)
|
||||
if err != nil {
|
||||
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err)
|
||||
}
|
||||
|
||||
+2
-2
@@ -102,7 +102,7 @@ type repoCreateParams struct {
|
||||
DefaultDistribution string ` json:"DefaultDistribution" example:"stable"`
|
||||
// Default component when publishing from this local repo
|
||||
DefaultComponent string ` json:"DefaultComponent" example:"main"`
|
||||
// Snapshot name to create repoitory from (optional)
|
||||
// Snapshot name to create repository from (optional)
|
||||
FromSnapshot string ` json:"FromSnapshot" example:""`
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ type reposEditParams struct {
|
||||
Comment *string ` json:"Comment" example:"example repo"`
|
||||
// Change Default Distribution for publishing
|
||||
DefaultDistribution *string ` json:"DefaultDistribution" example:""`
|
||||
// Change Devault Component for publishing
|
||||
// Change Default Component for publishing
|
||||
DefaultComponent *string ` json:"DefaultComponent" example:""`
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -168,6 +168,8 @@ func (collection *LocalRepoCollection) Update(repo *LocalRepo) error {
|
||||
|
||||
// LoadComplete loads additional information for local repo
|
||||
func (collection *LocalRepoCollection) LoadComplete(repo *LocalRepo) error {
|
||||
repo.packageRefs = &PackageRefList{}
|
||||
|
||||
encoded, err := collection.db.Get(repo.RefKey())
|
||||
if err == database.ErrNotFound {
|
||||
return nil
|
||||
@@ -176,7 +178,6 @@ func (collection *LocalRepoCollection) LoadComplete(repo *LocalRepo) error {
|
||||
return err
|
||||
}
|
||||
|
||||
repo.packageRefs = &PackageRefList{}
|
||||
return repo.packageRefs.Decode(encoded)
|
||||
}
|
||||
|
||||
|
||||
@@ -133,6 +133,18 @@ func (s *LocalRepoCollectionSuite) TestByUUID(c *C) {
|
||||
c.Assert(r.String(), Equals, repo.String())
|
||||
}
|
||||
|
||||
func (s *LocalRepoCollectionSuite) TestLoadCompleteNoRefKey(c *C) {
|
||||
repo := NewLocalRepo("local1", "Comment 1")
|
||||
c.Assert(s.collection.Update(repo), IsNil)
|
||||
|
||||
r, err := s.collection.ByName("local1")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
c.Assert(s.collection.LoadComplete(r), IsNil)
|
||||
c.Assert(r.packageRefs, NotNil)
|
||||
c.Assert(r.NumPackages(), Equals, 0)
|
||||
}
|
||||
|
||||
func (s *LocalRepoCollectionSuite) TestUpdateLoadComplete(c *C) {
|
||||
repo := NewLocalRepo("local1", "Comment 1")
|
||||
c.Assert(s.collection.Update(repo), IsNil)
|
||||
|
||||
+6
-1
@@ -28,6 +28,11 @@ func ParsePPA(ppaURL string, config *utils.ConfigStructure) (url string, distrib
|
||||
}
|
||||
}
|
||||
|
||||
baseurl := config.PpaBaseURL
|
||||
if baseurl == "" {
|
||||
baseurl = "http://ppa.launchpad.net"
|
||||
}
|
||||
|
||||
codename := config.PpaCodename
|
||||
if codename == "" {
|
||||
codename, err = getCodename()
|
||||
@@ -39,7 +44,7 @@ func ParsePPA(ppaURL string, config *utils.ConfigStructure) (url string, distrib
|
||||
|
||||
distribution = codename
|
||||
components = []string{"main"}
|
||||
url = fmt.Sprintf("http://ppa.launchpad.net/%s/%s/%s", matches[1], matches[2], distributorID)
|
||||
url = fmt.Sprintf("%s/%s/%s/%s", baseurl, matches[1], matches[2], distributorID)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -79,6 +79,9 @@ func (l *PackageRefList) Decode(input []byte) error {
|
||||
|
||||
// ForEach calls handler for each package ref in list
|
||||
func (l *PackageRefList) ForEach(handler func([]byte) error) error {
|
||||
if l == nil {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
for _, p := range l.Refs {
|
||||
err = handler(p)
|
||||
|
||||
@@ -130,6 +130,17 @@ func (s *PackageRefListSuite) TestPackageRefListForeach(c *C) {
|
||||
c.Check(err, Equals, e)
|
||||
}
|
||||
|
||||
func (s *PackageRefListSuite) TestForEachNilList(c *C) {
|
||||
var l *PackageRefList
|
||||
called := false
|
||||
err := l.ForEach(func([]byte) error {
|
||||
called = true
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(called, Equals, false)
|
||||
}
|
||||
|
||||
func (s *PackageRefListSuite) TestHas(c *C) {
|
||||
_ = s.list.Add(s.p1)
|
||||
_ = s.list.Add(s.p3)
|
||||
|
||||
Vendored
+3
@@ -70,6 +70,9 @@ ppa_distributor_id: ubuntu
|
||||
# Codename for short PPA url expansion
|
||||
ppa_codename: ""
|
||||
|
||||
# PPA Base URL (default: launchpad)
|
||||
# # ppa_baseurl: http://ppa.launchpad.net
|
||||
|
||||
|
||||
# Aptly Server
|
||||
###############
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
|
||||
In order to add debian package files to a local repository, files are first uploaded to a temporary directory.
|
||||
Then the directory (or a specific file within) is added to a repository. After adding to a repositorty, the directory resp. files are removed bt default.
|
||||
Then the directory (or a specific file within) is added to a repository. After adding to a repository, the directory resp. files are removed bt default.
|
||||
|
||||
All uploaded files are stored under `<rootDir>/upload/<tempdir>` directory.
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# Search Package Collection
|
||||
<div>
|
||||
Perform operations on the whole collection of packages in apty database.
|
||||
Perform operations on the whole collection of packages in aptly database.
|
||||
</div>
|
||||
|
||||
|
||||
+1
-1
@@ -35,6 +35,6 @@ aptly publish repo my-repo --gpg-key=KEY_ID_a --gpg-key=KEY_ID_b
|
||||
#### Parameters
|
||||
|
||||
Publish APIs use following convention to identify published repositories: `/api/publish/:prefix/:distribution`. `:distribution` is distribution name, while `:prefix` is `[<storage>:]<prefix>` (storage is optional, it defaults to empty string), if publishing prefix contains slashes `/`, they should be replaced with underscores (`_`) and underscores
|
||||
should be replaced with double underscore (`__`). To specify root `:prefix`, use `:.`, as `.` is ambigious in URLs.
|
||||
should be replaced with double underscore (`__`). To specify root `:prefix`, use `:.`, as `.` is ambiguous in URLs.
|
||||
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Manage Local Repositories
|
||||
<div>
|
||||
A local repository is a collection of versionned packages (usually custom packages created internally).
|
||||
A local repository is a collection of versioned packages (usually custom packages created internally).
|
||||
|
||||
Packages can be added, removed, moved or copied between repos.
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencyVerboseResolve": false,
|
||||
"ppaDistributorID": "ubuntu",
|
||||
"ppaCodename": "",
|
||||
"ppaBaseURL": "http://ppa.launchpad.net",
|
||||
"serveInAPIMode": true,
|
||||
"enableMetricsEndpoint": true,
|
||||
"enableSwaggerEndpoint": false,
|
||||
|
||||
@@ -11,6 +11,7 @@ dep_follow_source: false
|
||||
dep_verboseresolve: false
|
||||
ppa_distributor_id: ubuntu
|
||||
ppa_codename: ""
|
||||
ppa_baseurl: http://ppa.launchpad.net
|
||||
serve_in_api_mode: true
|
||||
enable_metrics_endpoint: true
|
||||
enable_swagger_endpoint: false
|
||||
|
||||
@@ -70,6 +70,9 @@ ppa_distributor_id: ubuntu
|
||||
# Codename for short PPA url expansion
|
||||
ppa_codename: ""
|
||||
|
||||
# PPA Base URL (default: launchpad)
|
||||
# # ppa_baseurl: http://ppa.launchpad.net
|
||||
|
||||
|
||||
# Aptly Server
|
||||
###############
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Downloading: http://ppa.launchpad.net/gladky-anton/gnuplot/ubuntu/dists/maverick/InRelease
|
||||
Downloading: http://repo.aptly.info/system-tests/ppa/gladky-anton/gnuplot/ubuntu/dists/maverick/InRelease
|
||||
gpgv: Signature made Sun Jul 28 07:57:01 2024 UTC
|
||||
gpgv: using RSA key 5BFCD481D86D5824470E469F9000B1C3A01F726C
|
||||
gpgv: Good signature from "Launchpad PPA for Anton Gladky"
|
||||
@@ -6,5 +6,5 @@ gpgv: Signature made Sun Jul 28 07:57:01 2024 UTC
|
||||
gpgv: using RSA key 02219381E9161C78A46CB2BFA5279A973B1F56C0
|
||||
gpgv: Good signature from "Launchpad sim"
|
||||
|
||||
Mirror [mirror18]: http://ppa.launchpad.net/gladky-anton/gnuplot/ubuntu/ maverick successfully added.
|
||||
Mirror [mirror18]: http://repo.aptly.info/system-tests/ppa/gladky-anton/gnuplot/ubuntu/ maverick successfully added.
|
||||
You can run 'aptly mirror update mirror18' to download repository contents.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name: mirror18
|
||||
Archive Root URL: http://ppa.launchpad.net/gladky-anton/gnuplot/ubuntu/
|
||||
Archive Root URL: http://repo.aptly.info/system-tests/ppa/gladky-anton/gnuplot/ubuntu/
|
||||
Distribution: maverick
|
||||
Components: main
|
||||
Architectures: amd64, armel, i386, powerpc
|
||||
|
||||
@@ -221,6 +221,7 @@ class CreateMirror18Test(BaseTest):
|
||||
"max-tries": 1,
|
||||
"ppaDistributorID": "ubuntu",
|
||||
"ppaCodename": "maverick",
|
||||
"ppaBaseURL": "http://repo.aptly.info/system-tests/ppa",
|
||||
}
|
||||
|
||||
fixtureCmds = [
|
||||
|
||||
@@ -31,6 +31,7 @@ type ConfigStructure struct { // nolint: maligned
|
||||
// PPA
|
||||
PpaDistributorID string `json:"ppaDistributorID" yaml:"ppa_distributor_id"`
|
||||
PpaCodename string `json:"ppaCodename" yaml:"ppa_codename"`
|
||||
PpaBaseURL string `json:"ppaBaseURL" yaml:"ppa_baseurl"`
|
||||
|
||||
// Server
|
||||
ServeInAPIMode bool `json:"serveInAPIMode" yaml:"serve_in_api_mode"`
|
||||
@@ -235,6 +236,7 @@ var Config = ConfigStructure{
|
||||
SkipLegacyPool: false,
|
||||
PpaDistributorID: "ubuntu",
|
||||
PpaCodename: "",
|
||||
PpaBaseURL: "http://ppa.launchpad.net",
|
||||
FileSystemPublishRoots: map[string]FileSystemPublishRoot{},
|
||||
S3PublishRoots: map[string]S3PublishRoot{},
|
||||
SwiftPublishRoots: map[string]SwiftPublishRoot{},
|
||||
|
||||
@@ -85,6 +85,7 @@ func (s *ConfigSuite) TestSaveConfig(c *C) {
|
||||
" \"dependencyVerboseResolve\": false,\n" +
|
||||
" \"ppaDistributorID\": \"\",\n" +
|
||||
" \"ppaCodename\": \"\",\n" +
|
||||
" \"ppaBaseURL\": \"\",\n" +
|
||||
" \"serveInAPIMode\": false,\n" +
|
||||
" \"enableMetricsEndpoint\": false,\n" +
|
||||
" \"enableSwaggerEndpoint\": false,\n" +
|
||||
@@ -252,6 +253,7 @@ func (s *ConfigSuite) TestSaveYAML2Config(c *C) {
|
||||
"dep_verboseresolve: false\n" +
|
||||
"ppa_distributor_id: \"\"\n" +
|
||||
"ppa_codename: \"\"\n" +
|
||||
"ppa_baseurl: \"\"\n" +
|
||||
"serve_in_api_mode: false\n" +
|
||||
"enable_metrics_endpoint: false\n" +
|
||||
"enable_swagger_endpoint: false\n" +
|
||||
@@ -308,6 +310,7 @@ dep_follow_source: true
|
||||
dep_verboseresolve: true
|
||||
ppa_distributor_id: Ubuntu
|
||||
ppa_codename: code
|
||||
ppa_baseurl: http://ppa.launchpad.net
|
||||
serve_in_api_mode: true
|
||||
enable_metrics_endpoint: true
|
||||
enable_swagger_endpoint: true
|
||||
|
||||
Reference in New Issue
Block a user