// Package api provides implementation of aptly REST API package api import ( "fmt" "sort" "github.com/aptly-dev/aptly/aptly" "github.com/aptly-dev/aptly/deb" "github.com/aptly-dev/aptly/query" "github.com/gin-gonic/gin" ) // Lock order acquisition (canonical): // 1. RemoteRepoCollection // 2. LocalRepoCollection // 3. SnapshotCollection // 4. PublishedRepoCollection // GET /api/version func apiVersion(c *gin.Context) { c.JSON(200, gin.H{"Version": aptly.Version}) } type dbRequestKind int const ( acquiredb dbRequestKind = iota releasedb ) type dbRequest struct { kind dbRequestKind err chan<- error } // Acquire database lock and release it when not needed anymore. // // Should be run in a goroutine! func acquireDatabase(requests <-chan dbRequest) { clients := 0 for request := range requests { var err error switch request.kind { case acquiredb: if clients == 0 { err = context.ReOpenDatabase() } request.err <- err if err == nil { clients++ } case releasedb: clients-- if clients == 0 { err = context.CloseDatabase() } else { err = nil } request.err <- err } } } // Common piece of code to show list of packages, // with searching & details if requested func showPackages(c *gin.Context, reflist *deb.PackageRefList, collectionFactory *deb.CollectionFactory) { result := []*deb.Package{} list, err := deb.NewPackageListFromRefList(reflist, collectionFactory.PackageCollection(), nil) if err != nil { c.AbortWithError(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.AbortWithError(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.AbortWithError(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.AbortWithError(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()) } }