Filter remote object listings by prefix
This commit is contained in:
@@ -51,7 +51,7 @@ func (h *ObjectsHandler) list(w http.ResponseWriter, r *http.Request) {
|
|||||||
remoteName := chi.URLParam(r, "name")
|
remoteName := chi.URLParam(r, "name")
|
||||||
limit, offset := pageBounds(r)
|
limit, offset := pageBounds(r)
|
||||||
|
|
||||||
artifacts, err := h.db.ListArtifacts(r.Context(), remoteName, limit, offset)
|
artifacts, err := h.db.ListArtifacts(r.Context(), remoteName, r.URL.Query().Get("prefix"), limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ func (db *DB) TouchArtifactAccess(ctx context.Context, remoteName, path string)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) ListArtifacts(ctx context.Context, remoteName string, limit, offset int) ([]models.Artifact, error) {
|
// ListArtifacts pages a remote's artifacts whose path starts with prefix ("" lists all).
|
||||||
|
func (db *DB) ListArtifacts(ctx context.Context, remoteName, prefix string, limit, offset int) ([]models.Artifact, error) {
|
||||||
rows, err := db.Pool.Query(ctx, `
|
rows, err := db.Pool.Query(ctx, `
|
||||||
SELECT a.id, a.remote_name, a.path, a.content_hash, a.upstream_etag,
|
SELECT a.id, a.remote_name, a.path, a.content_hash, a.upstream_etag,
|
||||||
a.upstream_last_modified, a.first_seen_at, a.last_fetched_at,
|
a.upstream_last_modified, a.first_seen_at, a.last_fetched_at,
|
||||||
@@ -73,10 +74,10 @@ func (db *DB) ListArtifacts(ctx context.Context, remoteName string, limit, offse
|
|||||||
b.size_bytes, b.content_type
|
b.size_bytes, b.content_type
|
||||||
FROM artifacts a
|
FROM artifacts a
|
||||||
JOIN blobs b ON a.content_hash = b.content_hash
|
JOIN blobs b ON a.content_hash = b.content_hash
|
||||||
WHERE a.remote_name = $1
|
WHERE a.remote_name = $1 AND left(a.path, length($2)) = $2
|
||||||
ORDER BY a.path
|
ORDER BY a.path
|
||||||
LIMIT $2 OFFSET $3
|
LIMIT $3 OFFSET $4
|
||||||
`, remoteName, limit, offset)
|
`, remoteName, prefix, limit, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,10 +168,17 @@ func TestArtifactsAndBlobs(t *testing.T) {
|
|||||||
if err := testDB.TouchArtifactAccess(ctx(), "r-art", "path/a.txt"); err != nil {
|
if err := testDB.TouchArtifactAccess(ctx(), "r-art", "path/a.txt"); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
arts, err := testDB.ListArtifacts(ctx(), "r-art", 10, 0)
|
if err := testDB.UpsertArtifact(ctx(), "r-art", "other/b.txt", hash, ""); err != nil {
|
||||||
if err != nil || len(arts) != 1 {
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
arts, err := testDB.ListArtifacts(ctx(), "r-art", "", 10, 0)
|
||||||
|
if err != nil || len(arts) != 2 {
|
||||||
t.Fatalf("list artifacts: %v %v", len(arts), err)
|
t.Fatalf("list artifacts: %v %v", len(arts), err)
|
||||||
}
|
}
|
||||||
|
arts, err = testDB.ListArtifacts(ctx(), "r-art", "path/", 10, 0)
|
||||||
|
if err != nil || len(arts) != 1 || arts[0].Path != "path/a.txt" {
|
||||||
|
t.Fatalf("list artifacts with prefix: %+v %v", arts, err)
|
||||||
|
}
|
||||||
if err := testDB.InsertAccessLog(ctx(), "r-art", "path/a.txt", true, 10, 5, "1.2.3.4"); err != nil {
|
if err := testDB.InsertAccessLog(ctx(), "r-art", "path/a.txt", true, 10, 5, "1.2.3.4"); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -320,7 +327,7 @@ func TestDatabaseErrorPaths(t *testing.T) {
|
|||||||
if _, err := bad.ListVirtuals(ctx); err == nil {
|
if _, err := bad.ListVirtuals(ctx); err == nil {
|
||||||
t.Error("ListVirtuals should error")
|
t.Error("ListVirtuals should error")
|
||||||
}
|
}
|
||||||
if _, err := bad.ListArtifacts(ctx, "r", 10, 0); err == nil {
|
if _, err := bad.ListArtifacts(ctx, "r", "", 10, 0); err == nil {
|
||||||
t.Error("ListArtifacts should error")
|
t.Error("ListArtifacts should error")
|
||||||
}
|
}
|
||||||
if _, err := bad.ListLocalFiles(ctx, "r", 10, 0); err == nil {
|
if _, err := bad.ListLocalFiles(ctx, "r", 10, 0); err == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user