Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cli/qmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ function multiGet(pattern: string, maxLines?: number, maxBytes: number = DEFAULT
const db = getDb();

// Check if it's a comma-separated list or a glob pattern
const isCommaSeparated = pattern.includes(',') && !pattern.includes('*') && !pattern.includes('?');
const isCommaSeparated = pattern.includes(',') && !pattern.includes('*') && !pattern.includes('?') && !pattern.includes('{');

let files: { filepath: string; displayPath: string; bodyLength: number; collection?: string; path?: string }[];

Expand Down
4 changes: 2 additions & 2 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2245,7 +2245,7 @@ export function matchFilesByGlob(db: Database, pattern: string): { filepath: str

const isMatch = picomatch(pattern);
return allFiles
.filter(f => isMatch(f.virtual_path) || isMatch(f.path))
.filter(f => isMatch(f.virtual_path) || isMatch(f.path) || isMatch(f.collection + '/' + f.path))
.map(f => ({
filepath: f.virtual_path, // Virtual path for precise lookup
displayPath: f.path, // Relative path for display
Expand Down Expand Up @@ -3354,7 +3354,7 @@ export function findDocuments(
pattern: string,
options: { includeBody?: boolean; maxBytes?: number } = {}
): { docs: MultiGetResult[]; errors: string[] } {
const isCommaSeparated = pattern.includes(',') && !pattern.includes('*') && !pattern.includes('?');
const isCommaSeparated = pattern.includes(',') && !pattern.includes('*') && !pattern.includes('?') && !pattern.includes('{');
const errors: string[] = [];
const maxBytes = options.maxBytes ?? DEFAULT_MULTI_GET_MAX_BYTES;

Expand Down
91 changes: 91 additions & 0 deletions test/store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1757,6 +1757,55 @@ describe("Document Retrieval", () => {

await cleanupTestDb(store);
});

test("findDocuments supports brace expansion patterns", async () => {
const store = await createTestStore();
const collectionName = await createTestCollection();

await insertTestDocument(store.db, collectionName, {
name: "doc1",
filepath: "/path/doc1.md",
displayPath: "doc1.md",
});
await insertTestDocument(store.db, collectionName, {
name: "doc2",
filepath: "/path/doc2.md",
displayPath: "doc2.md",
});
await insertTestDocument(store.db, collectionName, {
name: "doc3",
filepath: "/path/doc3.md",
displayPath: "doc3.md",
});

const { docs, errors } = store.findDocuments("{doc1,doc2}.md");
expect(errors).toHaveLength(0);
expect(docs).toHaveLength(2);

await cleanupTestDb(store);
});

test("findDocuments supports brace expansion with collection prefix", async () => {
const store = await createTestStore();
const collectionName = await createTestCollection();

await insertTestDocument(store.db, collectionName, {
name: "readme",
filepath: "/path/readme.md",
displayPath: "readme.md",
});
await insertTestDocument(store.db, collectionName, {
name: "changelog",
filepath: "/path/changelog.md",
displayPath: "changelog.md",
});

const { docs, errors } = store.findDocuments(`${collectionName}/{readme,changelog}.md`);
expect(errors).toHaveLength(0);
expect(docs).toHaveLength(2);

await cleanupTestDb(store);
});
});

});
Expand Down Expand Up @@ -2115,6 +2164,48 @@ describe("Fuzzy Matching", () => {

await cleanupTestDb(store);
});

test("matchFilesByGlob matches collection/path patterns", async () => {
const store = await createTestStore();
const collectionName = await createTestCollection();

await insertTestDocument(store.db, collectionName, {
filepath: "/p/readme.md",
displayPath: "readme.md",
});
await insertTestDocument(store.db, collectionName, {
filepath: "/p/changelog.md",
displayPath: "changelog.md",
});

const matches = store.matchFilesByGlob(`${collectionName}/*.md`);
expect(matches).toHaveLength(2);

await cleanupTestDb(store);
});

test("matchFilesByGlob matches brace expansion", async () => {
const store = await createTestStore();
const collectionName = await createTestCollection();

await insertTestDocument(store.db, collectionName, {
filepath: "/p/readme.md",
displayPath: "readme.md",
});
await insertTestDocument(store.db, collectionName, {
filepath: "/p/changelog.md",
displayPath: "changelog.md",
});
await insertTestDocument(store.db, collectionName, {
filepath: "/p/license.md",
displayPath: "license.md",
});

const matches = store.matchFilesByGlob(`${collectionName}/{readme,changelog}.md`);
expect(matches).toHaveLength(2);

await cleanupTestDb(store);
});
});

// =============================================================================
Expand Down