Skip to content

Commit

Permalink
Export deepenCloneBy and isRepoShallow (#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist committed Dec 31, 2021
1 parent de15ae0 commit 77c1cef
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 72 deletions.
8 changes: 8 additions & 0 deletions .changeset/fifty-crabs-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@changesets/git": minor
---

author: @RoystonS
author: @Andarist

New public utilities have been added: `deepenCloneBy` and `isRepoShallow`.
130 changes: 60 additions & 70 deletions packages/git/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { deprecate } from "util";

const isInDir = (dir: string) => (subdir: string) => isSubdir(dir, subdir);

async function add(pathToFile: string, cwd: string) {
export async function add(pathToFile: string, cwd: string) {
const gitCmd = await spawn("git", ["add", pathToFile], { cwd });

if (gitCmd.code !== 0) {
Expand All @@ -17,7 +17,7 @@ async function add(pathToFile: string, cwd: string) {
return gitCmd.code === 0;
}

async function commit(message: string, cwd: string) {
export async function commit(message: string, cwd: string) {
const gitCmd = await spawn(
"git",
["commit", "-m", message, "--allow-empty"],
Expand All @@ -26,7 +26,7 @@ async function commit(message: string, cwd: string) {
return gitCmd.code === 0;
}

async function getAllTags(cwd: string): Promise<Set<string>> {
export async function getAllTags(cwd: string): Promise<Set<string>> {
const gitCmd = await spawn("git", ["tag"], { cwd });

if (gitCmd.code !== 0) {
Expand All @@ -42,8 +42,8 @@ async function getAllTags(cwd: string): Promise<Set<string>> {
}

// used to create a single tag at a time for the current head only
async function tag(tagStr: string, cwd: string) {
// NOTE: it's important we use the -m flag otherwise 'git push --follow-tags' won't actually push
export async function tag(tagStr: string, cwd: string) {
// NOTE: it's important we use the -m flag to create annotated tag otherwise 'git push --follow-tags' won't actually push
// the tags
const gitCmd = await spawn("git", ["tag", tagStr, "-m", tagStr], { cwd });
return gitCmd.code === 0;
Expand All @@ -60,7 +60,7 @@ export async function getDivergedCommit(cwd: string, ref: string) {
return cmd.stdout.toString().trim();
}

const getCommitThatAddsFile = deprecate(
export const getCommitThatAddsFile = deprecate(
async (gitPath: string, cwd: string) => {
return (await getCommitsThatAddFiles([gitPath], cwd))[0];
},
Expand All @@ -73,7 +73,7 @@ const getCommitThatAddsFile = deprecate(
* @param gitPaths - Paths to fetch
* @param cwd - Location of the repository
*/
async function getCommitsThatAddFiles(
export async function getCommitsThatAddFiles(
gitPaths: string[],
cwd: string
): Promise<(string | undefined)[]> {
Expand All @@ -85,7 +85,26 @@ async function getCommitsThatAddFiles(

do {
// Fetch commit information for all paths we don't have yet
const commitInfos = await Promise.all(remaining.map(findCommitAndParent));
const commitInfos = await Promise.all(
remaining.map(async (gitPath: string) => {
const [commitSha, parentSha] = (
await spawn(
"git",
[
"log",
"--diff-filter=A",
"--max-count=1",
"--pretty=format:%h:%p",
gitPath
],
{ cwd }
)
).stdout
.toString()
.split(":");
return { path: gitPath, commitSha, parentSha };
})
);

// To collect commits without parents (usually because they're absent from
// a shallow clone).
Expand Down Expand Up @@ -113,9 +132,9 @@ async function getCommitsThatAddFiles(
// a shallow clone.

// Can we deepen the clone?
if (await isRepoShallow()) {
if (await isRepoShallow({ cwd })) {
// Yes.
await deepenCloneBy(50);
await deepenCloneBy({ by: 50, cwd });
remaining = commitsWithMissingParents.map(p => p.path);
} else {
// It's not a shallow clone, so all the commit SHAs we have are legitimate.
Expand All @@ -127,61 +146,44 @@ async function getCommitsThatAddFiles(
} while (true);

return gitPaths.map(p => map.get(p));
}

/** Find the commit that added a file, and the parent of that commit */
async function findCommitAndParent(gitPath: string) {
const logResult = await spawn(
"git",
[
"log",
"--diff-filter=A",
"--max-count=1",
"--pretty=format:%h:%p",
gitPath
],
{ cwd }
);
const [commitSha, parentSha] = logResult.stdout.toString().split(":");
return { path: gitPath, commitSha, parentSha };
}

async function isRepoShallow() {
const gitCmd = await spawn(
"git",
["rev-parse", "--is-shallow-repository"],
{ cwd }
);

const isShallowRepoOutput = gitCmd.stdout.toString().trim();
export async function isRepoShallow({ cwd }: { cwd: string }) {
const isShallowRepoOutput = (
await spawn("git", ["rev-parse", "--is-shallow-repository"], {
cwd
})
).stdout
.toString()
.trim();

if (isShallowRepoOutput === "--is-shallow-repository") {
// We have an old version of Git (<2.15) which doesn't support `rev-parse --is-shallow-repository`
// In that case, we'll test for the existence of .git/shallow.
if (isShallowRepoOutput === "--is-shallow-repository") {
// We have an old version of Git (<2.15) which doesn't support `rev-parse --is-shallow-repository`
// In that case, we'll test for the existence of .git/shallow.

// Firstly, find the .git folder for the repo; note that this will be relative to the repo dir
const gitDir = (
await spawn("git", ["rev-parse", "--git-dir"], { cwd })
).stdout
.toString()
.trim();
// Firstly, find the .git folder for the repo; note that this will be relative to the repo dir
const gitDir = (
await spawn("git", ["rev-parse", "--git-dir"], { cwd })
).stdout
.toString()
.trim();

const fullGitDir = path.resolve(cwd, gitDir);
const fullGitDir = path.resolve(cwd, gitDir);

// Check for the existence of <gitDir>/shallow
return fs.existsSync(path.join(fullGitDir, "shallow"));
} else {
// We have a newer Git which supports `rev-parse --is-shallow-repository`. We'll use
// the output of that instead of messing with .git/shallow in case that changes in the future.
return isShallowRepoOutput === "true";
}
// Check for the existence of <gitDir>/shallow
return fs.existsSync(path.join(fullGitDir, "shallow"));
} else {
// We have a newer Git which supports `rev-parse --is-shallow-repository`. We'll use
// the output of that instead of messing with .git/shallow in case that changes in the future.
return isShallowRepoOutput === "true";
}
}

async function deepenCloneBy(by: number) {
await spawn("git", ["fetch", `--deepen=${by}`], { cwd });
}
export async function deepenCloneBy({ by, cwd }: { by: number; cwd: string }) {
await spawn("git", ["fetch", `--deepen=${by}`], { cwd });
}

async function getChangedFilesSince({
export async function getChangedFilesSince({
cwd,
ref,
fullPath = false
Expand Down Expand Up @@ -209,7 +211,7 @@ async function getChangedFilesSince({
}

// below are less generic functions that we use in combination with other things we are doing
async function getChangedChangesetFilesSinceRef({
export async function getChangedChangesetFilesSinceRef({
cwd,
ref
}: {
Expand Down Expand Up @@ -241,7 +243,7 @@ async function getChangedChangesetFilesSinceRef({
}
}

async function getChangedPackagesSinceRef({
export async function getChangedPackagesSinceRef({
cwd,
ref
}: {
Expand All @@ -266,15 +268,3 @@ async function getChangedPackagesSinceRef({
.filter((pkg, idx, packages) => packages.indexOf(pkg) === idx)
);
}

export {
getCommitThatAddsFile,
getCommitsThatAddFiles,
getChangedFilesSince,
add,
commit,
tag,
getChangedPackagesSinceRef,
getChangedChangesetFilesSinceRef,
getAllTags
};
4 changes: 2 additions & 2 deletions packages/read/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ async function filterChangesetsSinceRef(
cwd: changesetBase,
ref: sinceRef
});
const newHahses = newChangesets.map(c => c.split("/")[1]);
const newHashes = newChangesets.map(c => c.split("/")[1]);

return changesets.filter(dir => newHahses.includes(dir));
return changesets.filter(dir => newHashes.includes(dir));
}

export default async function getChangesets(
Expand Down

0 comments on commit 77c1cef

Please sign in to comment.