Skip to content

Commit

Permalink
implement listFiles() function
Browse files Browse the repository at this point in the history
  • Loading branch information
adamziel committed Sep 14, 2024
1 parent e818ec8 commit e1f28a1
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 6 deletions.
18 changes: 15 additions & 3 deletions packages/playground/storage/src/lib/git-sparse-checkout.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { lsRefs, sparseCheckout } from './git-sparse-checkout';
import { listRefs, sparseCheckout, listFiles } from './git-sparse-checkout';

describe('lsRefs', () => {
describe('listRefs', () => {
it('should return the latest commit hash for a given ref', async () => {
const refs = await lsRefs(
const refs = await listRefs(
'https://github.com/WordPress/wordpress-playground',
'refs/heads/trunk'
);
Expand All @@ -25,3 +25,15 @@ describe('sparseCheckout', () => {
expect(files['README.md'].length).toBeGreaterThan(0);
});
});

describe.only('listFiles', () => {
it('should list the files in a git repo', async () => {
const files = await listFiles(
'https://github.com/WordPress/wordpress-playground.git',
'refs/heads/trunk'
);
expect(files).toHaveProperty(
'packages/playground/storage/package.json'
);
});
});
56 changes: 54 additions & 2 deletions packages/playground/storage/src/lib/git-sparse-checkout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export async function sparseCheckout(
fullyQualifiedBranchName: string,
filesPaths: string[]
) {
const refs = await lsRefs(repoUrl, fullyQualifiedBranchName);
const refs = await listRefs(repoUrl, fullyQualifiedBranchName);
const commitHash = refs[fullyQualifiedBranchName];
const treesIdx = await fetchWithoutBlobs(repoUrl, commitHash);
const objects = await resolveObjects(treesIdx, commitHash, filesPaths);
Expand All @@ -63,14 +63,42 @@ export async function sparseCheckout(
return fetchedPaths;
}

export async function listFiles(
repoUrl: string,
fullyQualifiedBranchName: string
) {
const refs = await listRefs(repoUrl, fullyQualifiedBranchName);
if (!(fullyQualifiedBranchName in refs)) {
throw new Error(`Branch ${fullyQualifiedBranchName} not found`);
}
const commitHash = refs[fullyQualifiedBranchName];
const treesIdx = await fetchWithoutBlobs(repoUrl, commitHash);
const rootTree = await resolveAllObjects(treesIdx, commitHash);
const files: Record<string, string> = {};
function recurse(tree: GitTree, prefix = '') {
if (!tree?.object) {
return;
}
for (const branch of tree.object) {
if (branch.type === 'blob') {
files[prefix + branch.path] = branch.oid;
} else if (branch.type === 'tree' && branch.object) {
recurse(branch as any as GitTree, prefix + branch.path + '/');
}
}
}
recurse(rootTree);
return files;
}

/**
* Retrieves a list of files on matching git branches.
*
* @param repoUrl The URL of the git repository. For example: https://github.com/WordPress/gutenberg.git
* @param fullyQualifiedBranchPrefix The prefix of the branch names to fetch. For example: refs/heads/my-feature-branch
* @returns A map of branch names to their corresponding commit hashes.
*/
export async function lsRefs(
export async function listRefs(
repoUrl: string,
fullyQualifiedBranchPrefix: string
) {
Expand Down Expand Up @@ -147,6 +175,30 @@ async function fetchWithoutBlobs(repoUrl: string, commitHash: string) {
return idx;
}

async function resolveAllObjects(idx: GitPackIndex, commitHash: string) {
const commit = await idx.read({
oid: commitHash,
});
readObject(commit);

const rootItem = await idx.read({ oid: commit.object.tree });
const items = [rootItem];
while (items.length > 0) {
const tree = items.pop();
const readItem = await idx.read({ oid: tree.oid });
readObject(readItem);
tree.object = readItem.object;
if (readItem.type === 'tree') {
for (const subitem of readItem.object) {
if (subitem.type === 'tree') {
items.push(subitem);
}
}
}
}
return rootItem;
}

async function resolveObjects(
idx: GitPackIndex,
commitHash: string,
Expand Down
6 changes: 5 additions & 1 deletion types/isomorphic-git.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ declare module 'isomorphic-git/src/models/GitPktLine.js' {
declare module 'isomorphic-git/src/models/GitTree.js' {
export class GitTree {
static from(buffer: Buffer): GitTree;
entries(): Array<{
type: 'tree' | 'blob';
oid: string;
format: 'content';
object: Array<{
mode: string;
path: string;
oid: string;
type?: 'blob' | 'tree';
object?: GitTree;
}>;
}
}
Expand Down

0 comments on commit e1f28a1

Please sign in to comment.