Skip to main content
Glama
feature.ts3.09 kB
import { WebApi } from 'azure-devops-node-api'; import { GitChange, GitVersionType, } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { createTwoFilesPatch } from 'diff'; import { AzureDevOpsError } from '../../../shared/errors'; import { CommitWithContent, ListCommitsOptions, ListCommitsResponse, } from '../types'; async function streamToString(stream: NodeJS.ReadableStream): Promise<string> { const chunks: Buffer[] = []; return await new Promise<string>((resolve, reject) => { stream.on('data', (c) => chunks.push(Buffer.from(c))); stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8'))); stream.on('error', (err) => reject(err)); }); } /** * List commits on a branch including their file level diffs */ export async function listCommits( connection: WebApi, options: ListCommitsOptions, ): Promise<ListCommitsResponse> { try { const gitApi = await connection.getGitApi(); const commits = await gitApi.getCommits( options.repositoryId, { itemVersion: { version: options.branchName, versionType: GitVersionType.Branch, }, $top: options.top ?? 10, $skip: options.skip, }, options.projectId, ); if (!commits || commits.length === 0) { return { commits: [] }; } const getBlobText = async (objId?: string): Promise<string> => { if (!objId) { return ''; } const stream = await gitApi.getBlobContent( options.repositoryId, objId, options.projectId, ); return stream ? await streamToString(stream) : ''; }; const commitsWithContent: CommitWithContent[] = []; for (const commit of commits) { const commitId = commit.commitId; if (!commitId) { continue; } const commitChanges = await gitApi.getChanges( commitId, options.repositoryId, options.projectId, ); const changeEntries = commitChanges?.changes ?? []; const files = await Promise.all( changeEntries.map(async (entry: GitChange) => { const path = entry.item?.path || entry.originalPath || ''; const [oldContent, newContent] = await Promise.all([ getBlobText(entry.item?.originalObjectId), getBlobText(entry.item?.objectId), ]); const patch = createTwoFilesPatch( entry.originalPath || path, path, oldContent, newContent, ); return { path, patch }; }), ); commitsWithContent.push({ commitId, comment: commit.comment, author: commit.author, committer: commit.committer, url: commit.url, parents: commit.parents, files, }); } return { commits: commitsWithContent }; } catch (error) { if (error instanceof AzureDevOpsError) { throw error; } throw new Error( `Failed to list commits: ${error instanceof Error ? error.message : String(error)}`, ); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tiberriver256/mcp-server-azure-devops'

If you have feedback or need assistance with the MCP directory API, please join our Discord server