Skip to content

Commit

Permalink
[cli] Resolve correct submodule key inside monorepos (#5)
Browse files Browse the repository at this point in the history
* [cli] Detach utils related to filesystem

* [cli] Resolve correct submodule key in monorepos

* [cli] Fix submodule paths
  • Loading branch information
junhoyeo authored Sep 14, 2022
1 parent 732b89e commit 40ba7cc
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 45 deletions.
17 changes: 3 additions & 14 deletions src/commands/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,9 @@ import GitUrlParse from 'git-url-parse';
import path from 'path';
import * as zx from 'zx';

import { insideDir } from '../utils/filesystem.js';
import { Submodule } from '../utils/submodules.js';

const insideDir = async (path: string, callback: () => Promise<void>) => {
const pwd = (await zx.$`pwd`).stdout;
zx.cd(path);
await callback();

try {
zx.cd(pwd);
} catch {
/* ignored */
}
};

const convertToAuthURL = (url: string, githubToken: string): string => {
const parsed = GitUrlParse(url);
parsed.token = githubToken;
Expand All @@ -29,10 +18,10 @@ type CloneOptions = {
submodules: Submodule[];
};
export const clone = async ({ githubToken, depth, submodules }: CloneOptions) => {
const rootDir = (await zx.$`pwd`).stdout.trim();
const topLevel = (await zx.$`git rev-parse --show-toplevel`).stdout.trim();

for (const submodule of submodules) {
const submoduleDir = path.join(rootDir, submodule.path);
const submoduleDir = path.join(topLevel, submodule.gitModulePath);
const submoduleURL = !!githubToken ? convertToAuthURL(submodule.url, githubToken) : submodule.url;

await zx.$`rm -rf ${submoduleDir}`.catch(() => {
Expand Down
21 changes: 21 additions & 0 deletions src/utils/filesystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import path from 'path';
import * as zx from 'zx';

// NOTE: Assumes that current platform is case-sensitive
export const haveSamePath = (haystack: string[], needle: string) =>
haystack.some((hay) => path.resolve(hay) === path.resolve(needle));

export const insideDir = async (
path: string,
callback: () => Promise<void>,
) => {
const pwd = (await zx.$`pwd`).stdout;
zx.cd(path);
await callback();

try {
zx.cd(pwd);
} catch {
/* ignored */
}
};
75 changes: 44 additions & 31 deletions src/utils/submodules.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,62 @@
import path from 'path';
import NodePath from 'path';
import * as zx from 'zx';

import { haveSamePath, insideDir } from './filesystem.js';

export type Submodule = {
commitHash: string;
path: string;
url: string;
gitModulePath: string;
};

// NOTE: Assumes that current platform is case-sensitive
const haveSamePath = (haystack: string[], needle: string) =>
haystack.some((hay) => path.resolve(hay) === path.resolve(needle));

type FetchSubmodulesOptions = {
paths: string[] | null;
};
export const fetchSubmodules = async (
options: FetchSubmodulesOptions,
): Promise<Submodule[]> => {
const output = await zx.$`git submodule status --recursive`;

const submodules = await Promise.all(
output.stdout
.split('\n')
.flatMap((rawLine) => {
const line = rawLine.trim();
if (line.length > 0) {
let [commitHash, path] = line.split(' ');
if (!!options.paths && !haveSamePath(options.paths, path)) {
return [];
}
if (commitHash.startsWith('-')) {
commitHash = commitHash.slice(1);
}
return { commitHash, path };
}
const topLevel = (await zx.$`git rev-parse --show-toplevel`).stdout.trim();
let output: string = '';
await insideDir(topLevel, async () => {
output = (await zx.$`git submodule status --recursive`).stdout;
});

let submodules: Submodule[] = [];

const submoduleRefs = output.split('\n').flatMap((rawLine) => {
const line = rawLine.trim();
if (line.length > 0) {
let [commitHash, path] = line.split(' ');
if (!!options.paths && !haveSamePath(options.paths, path)) {
return [];
})
.map(async ({ commitHash, path }) => {
const url =
await zx.$`git config --file .gitmodules --get submodule.${path}.url`.then(
(output) => output.stdout.trim(),
);
return { commitHash, path, url };
}),
);
}
if (commitHash.startsWith('-')) {
commitHash = commitHash.slice(1);
}
return {
commitHash,
path: NodePath.join(topLevel, path),
gitModulePath: path,
};
}
return [];
});

for (const { commitHash, path, gitModulePath } of submoduleRefs) {
await insideDir(topLevel, async () => {
let pathName = path.endsWith('/')
? path.substring(0, path.lastIndexOf('/'))
: path;
pathName = pathName.split('/').slice(-1)[0];

const url =
await zx.$`git config --file .gitmodules --get submodule.${gitModulePath}.url`.then(
(output) => output.stdout.trim(),
);
submodules.push({ commitHash, path, url, gitModulePath });
});
}

return submodules;
};

0 comments on commit 40ba7cc

Please sign in to comment.