MCPcopy Index your code
hub / github.com/sourcebot-dev/sourcebot / getFileBlame

Function getFileBlame

packages/web/src/features/git/getFileBlameApi.ts:159–214  ·  view source on GitHub ↗
({ path: filePath, repo: repoName, ref }: FileBlameRequest, { source }: { source?: string } = {})

Source from the content-addressed store, hash-verified

157};
158
159export const getFileBlame = async ({ path: filePath, repo: repoName, ref }: FileBlameRequest, { source }: { source?: string } = {}): Promise<FileBlameResponse | ServiceError> =>
160 sew(() =>
161 withOptionalAuth(async ({ org, prisma, user }) => {
162 if (user) {
163 const resolvedSource = source ?? (await headers()).get('X-Sourcebot-Client-Source') ?? undefined;
164 await createAudit({
165 action: 'user.fetched_file_blame',
166 actor: { id: user.id, type: 'user' },
167 target: { id: org.id.toString(), type: 'org' },
168 orgId: org.id,
169 metadata: { source: resolvedSource },
170 });
171 }
172
173 const repo = await prisma.repo.findFirst({
174 where: { name: repoName, orgId: org.id },
175 });
176 if (!repo) {
177 return notFound(`Repository "${repoName}" not found.`);
178 }
179
180 if (!isPathValid(filePath)) {
181 return fileNotFound(filePath, repoName);
182 }
183
184 if (ref !== undefined && !isGitRefValid(ref)) {
185 return invalidGitRef(ref);
186 }
187
188 const { path: repoPath } = getRepoPath(repo);
189 const git = simpleGit().cwd(repoPath);
190
191 const gitRef = ref ?? repo.defaultBranch ?? 'HEAD';
192
193 let porcelain: string;
194 try {
195 porcelain = await git.raw(['blame', '--porcelain', gitRef, '--', filePath]);
196 } catch (error: unknown) {
197 const errorMessage = error instanceof Error ? error.message : String(error);
198 if (errorMessage.includes('no such path') || errorMessage.includes('does not exist') || errorMessage.includes('fatal: path') || errorMessage.includes('no such file')) {
199 return fileNotFound(filePath, repoName);
200 }
201 if (errorMessage.includes('unknown revision') || errorMessage.includes('bad revision') || errorMessage.includes('invalid object name')) {
202 return unresolvedGitRef(gitRef);
203 }
204 return unexpectedError(errorMessage);
205 }
206
207 try {
208 return parsePorcelainBlame(porcelain) satisfies FileBlameResponse;
209 } catch (error: unknown) {
210 const errorMessage = error instanceof Error ? error.message : String(error);
211 return unexpectedError(`Failed to parse git blame output: ${errorMessage}`);
212 }
213 })
214 );

Callers 2

CodePreviewPanelFunction · 0.90
route.tsFile · 0.90

Calls 12

sewFunction · 0.90
withOptionalAuthFunction · 0.90
createAuditFunction · 0.90
notFoundFunction · 0.90
isPathValidFunction · 0.90
fileNotFoundFunction · 0.90
isGitRefValidFunction · 0.90
invalidGitRefFunction · 0.90
getRepoPathFunction · 0.90
unresolvedGitRefFunction · 0.90
unexpectedErrorFunction · 0.90
parsePorcelainBlameFunction · 0.85

Tested by

no test coverage detected