Skip to content

Commit

Permalink
feat: allow switching branches (#73)
Browse files Browse the repository at this point in the history
* implemented checkout and added test cases

* updated readme
  • Loading branch information
shubhbapna authored May 24, 2023
1 parent a961e78 commit 25c0e74
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 1 deletion.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ await github.setup();

#### Utility functions

There multiple utility functions available to extract information about the state of the repositories.
There multiple utility functions available to extract information about the state of the repositories and perform some action on them.

```typescript
const github = new MockGithub("path to config");
Expand Down Expand Up @@ -422,6 +422,11 @@ const branches = github.repo.getBranchState("repoA");
* { path: string, branch: string }[]
*/
const repoFs = await github.repo.getFileSystemState("repoA");

/**
* Checkout the given branch in the given repo. Will throw an error if the repo or the branch does not exist
*/
await github.repo.checkout("repoA", "branchA");
```

### Env
Expand Down
23 changes: 23 additions & 0 deletions src/github/repository/state/repository-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
RepositoryStateMethods,
State,
} from "@mg/github/repository/state/repository-state.types";
import simpleGit from "simple-git";

export class RepositoryState implements RepositoryStateMethods {
private repositories: Repositories;
Expand Down Expand Up @@ -83,6 +84,28 @@ export class RepositoryState implements RepositoryStateMethods {
}
}

async checkout(repositoryName: string, branch: string): Promise<void> {
const repoPath = this.getPath(repositoryName);
const currBranches = this.getBranchState(repositoryName);
if (!repoPath) {
throw new Error("Repository does not exist");
}

if (
!currBranches?.localBranches.includes(branch) &&
!currBranches?.pushedBranches.includes(branch)
) {
throw new Error("Branch does not exist");
}

await simpleGit(repoPath).checkout(branch);

this.repositories[repositoryName] = {
...this.repositories[repositoryName],
currentBranch: branch
};
}

async getFileSystemState(
repositoryName: string
): Promise<FileState[] | undefined> {
Expand Down
1 change: 1 addition & 0 deletions src/github/repository/state/repository-state.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ export interface RepositoryStateMethods {
getOwner(repositoryName: string): string | undefined;
getBranchState(repositoryName: string): BranchState | undefined;
getFileSystemState(repositoryName: string): Promise<FileState[] | undefined>;
checkout(repositoryName: string, branch: string): Promise<void>;
}
48 changes: 48 additions & 0 deletions test/github/repository/state/repository-state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import {
} from "@mg/github/repository/history/repository-history.types";
import { DEFAULT_BRANCH } from "@mg/github/repository/repository.constants";
import { RepositoryState } from "@mg/github/repository/state/repository-state";
import simpleGit from "simple-git";

const setupPath = __dirname;

jest.mock("simple-git");

describe("getFileSystemState", () => {
test("undefined repository", async () => {
const repoState = new RepositoryState({}, setupPath);
Expand Down Expand Up @@ -320,3 +323,48 @@ describe("getState", () => {
});
});
});

describe("checkout", () => {
test.each([
["repository does not exist", {}],
[
"repository exists but branch doesn't",
{
repoA: {
owner: "owner",
localBranches: ["local1", "local2"],
pushedBranches: ["pushed1", "pushed2"],
currentBranch: "local1",
forkedFrom: "project-forked",
},
},
],
])("%p", async (_title, config) => {
const repoState = new RepositoryState(config, setupPath);
await expect(repoState.checkout("repoA", "branchA")).rejects.toThrowError();
});

test("repository and branch does exist", async () => {
const simpleGitMock = simpleGit as jest.Mock;
const checkoutMock = jest.fn(async _branch => undefined);

simpleGitMock.mockReturnValue({
checkout: checkoutMock
});

const repoState = new RepositoryState({
repoA: {
owner: "owner",
localBranches: ["local1", "local2"],
pushedBranches: ["pushed1", "pushed2"],
currentBranch: "local1",
forkedFrom: "project-forked",
},
}, setupPath);

await expect(repoState.checkout("repoA", "pushed1")).resolves.not.toThrowError();
expect(repoState.getBranchState("repoA")).toMatchObject({currentBranch: "pushed1"});
expect(simpleGitMock).toHaveBeenCalledWith(repoState.getPath("repoA"));
expect(checkoutMock).toHaveBeenCalledWith("pushed1");
});
});

0 comments on commit 25c0e74

Please sign in to comment.