Skip to content

Commit

Permalink
Added branch service
Browse files Browse the repository at this point in the history
  • Loading branch information
Caleb-T-Owens committed Jan 9, 2025
1 parent 908d52b commit 3a735c6
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
3 changes: 3 additions & 0 deletions apps/desktop/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import { User, UserService } from '$lib/stores/user';
import * as events from '$lib/utils/events';
import { unsubscribe } from '$lib/utils/unsubscribe';
import { BranchService as CloudBranchService } from '@gitbutler/shared/branches/branchService';
import { FeedService } from '@gitbutler/shared/feeds/service';
import { HttpClient } from '@gitbutler/shared/network/httpClient';
import { OrganizationService } from '@gitbutler/shared/organizations/organizationService';
Expand Down Expand Up @@ -70,6 +71,7 @@
const organizationService = new OrganizationService(data.cloud, appState.appDispatch);
const cloudUserService = new CloudUserService(data.cloud, appState.appDispatch);
const cloudProjectService = new CloudProjectService(data.cloud, appState.appDispatch);
const cloudBranchService = new CloudBranchService(data.cloud, appState.appDispatch);
setContext(AppState, appState);
setContext(AppDispatch, appState.appDispatch);
Expand All @@ -79,6 +81,7 @@
setContext(OrganizationService, organizationService);
setContext(CloudUserService, cloudUserService);
setContext(CloudProjectService, cloudProjectService);
setContext(CloudBranchService, cloudBranchService);
// Setters do not need to be reactive since `data` never updates
setSecretsService(data.secretsService);
Expand Down
4 changes: 4 additions & 0 deletions apps/web/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import { goto } from '$app/navigation';
import { page } from '$app/stores';
import { env } from '$env/dynamic/public';
import { BranchService } from '@gitbutler/shared/branches/branchService';

Check failure on line 18 in apps/web/src/routes/+layout.svelte

View workflow job for this annotation

GitHub Actions / lint-node

`@gitbutler/shared/branches/branchService` import should occur before import of `@gitbutler/shared/feeds/service`
interface Props {
children: Snippet;
Expand Down Expand Up @@ -46,6 +47,9 @@
const newUserService = new NewUserService(httpClient, appState.appDispatch);
setContext(NewUserService, newUserService);
const branchService = new BranchService(httpClient, appState.appDispatch);
setContext(BranchService, branchService);
$effect(() => {
const token = get(authService.token) || $page.url.searchParams.get('gb_access_token');
if (token) {
Expand Down
112 changes: 112 additions & 0 deletions packages/shared/src/lib/branches/branchService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { upsertBranch, upsertBranches } from '$lib/branches/branchesSlice';
import { upsertPatches } from '$lib/branches/patchesSlice';
import {
apiToBranch,
apiToPatch,
BranchStatus,
type ApiBranch,
type Branch,
type LoadableBranch,
type LoadablePatch
} from '$lib/branches/types';
import { InterestStore, type Interest } from '$lib/interest/intrestStore';
import { POLLING_GLACIALLY, POLLING_REGULAR } from '$lib/polling';
import type { HttpClient } from '$lib/network/httpClient';
import type { AppDispatch } from '$lib/redux/store.svelte';

type BranchUpdateParams = {
status: BranchStatus.Active | BranchStatus.Closed;
title: string;
description: string;
};

export class BranchService {
private readonly branchesInterests = new InterestStore<{
repositoryId: string;
branchStatus: BranchStatus;
}>(POLLING_GLACIALLY);
private readonly branchInterests = new InterestStore<{ branchId: string }>(POLLING_REGULAR);

constructor(
private readonly httpClient: HttpClient,
private readonly appDispatch: AppDispatch
) {}

getBranches(repositoryId: string, branchStatus: BranchStatus = BranchStatus.All): Interest {
return this.branchesInterests
.findOrCreateSubscribable({ repositoryId, branchStatus }, async () => {
try {
const apiBranches = await this.httpClient.get<ApiBranch[]>(
`patch_stack/${repositoryId}?status=${branchStatus}`
);
const branches = apiBranches.map(
(api): LoadableBranch => ({
status: 'found',
id: api.branch_id,
value: apiToBranch(api)
})
);

const patches = apiBranches
.flatMap((branch) => branch.patches)
.map(
(api): LoadablePatch => ({
status: 'found',
id: api.change_id,
value: apiToPatch(api)
})
);

this.appDispatch.dispatch(upsertBranches(branches));
this.appDispatch.dispatch(upsertPatches(patches));
} catch (_error: unknown) {
/* empty */
}
})
.createInterest();
}

async createBranch(repositoryId: string, branchId: string, oplogSha: string): Promise<Branch> {
const apiBranch = await this.httpClient.post<ApiBranch>(`patch_stack`, {
body: { branch_id: branchId, oplog_sha: oplogSha, project_id: repositoryId }
});
const branch = apiToBranch(apiBranch);

const patches = apiBranch.patches.map(
(api): LoadablePatch => ({ status: 'found', id: api.change_id, value: apiToPatch(api) })
);

this.appDispatch.dispatch(
upsertBranch({
status: 'found',
id: branch.branchId,
value: branch
})
);
this.appDispatch.dispatch(upsertPatches(patches));

return branch;
}

async updateBranch(branchId: string, params: BranchUpdateParams): Promise<Branch> {
const apiBranch = await this.httpClient.put<ApiBranch>(`patch_stack/${branchId}`, {
body: params
});
const branch = apiToBranch(apiBranch);

const patches = apiBranch.patches.map(
(api): LoadablePatch => ({ status: 'found', id: api.change_id, value: apiToPatch(api) })
);

this.appDispatch.dispatch(
upsertBranch({
status: 'found',
id: branch.branchId,
value: branch
})
);
this.appDispatch.dispatch(upsertPatches(patches));

return branch;
}
}

0 comments on commit 3a735c6

Please sign in to comment.