microsoft / microsoft/FluidFramework

Duplicate Code: Gitrest routes repeat fsManager + soft-delete setup

Open
#27,002 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
4.9k
Forks
586
Avg merge
1d 15h
Merged PRs (30d)
146

Description

🔍 Duplicate Code Detected: Gitrest route FS-manager setup

Analysis of commit 705e92735ec8ed44b6819739520bdd22d3c27f6d

Assignee: @copilot

Summary

Multiple Gitrest HTTP route handlers contain a near-identical block that:

  1. derives repoManagerParams from the request,
  2. opens/gets a repo manager,
  3. creates a filesystem manager (getFilesystemManagerFactory(...).create(...)), and
  4. runs checkSoftDeleted(...).

This duplication increases the risk of inconsistent behavior when the soft-delete rules, FS manager creation, or ephemeral-container handling changes.

Note: this workflow environment has a shallow git history (no parent commit available), so “recently changed files” couldn’t be derived via git diff. A repo-wide scan of eligible .ts/.mjs/.cjs (excluding tests/workflows) was used, and the finding was validated by inspecting the matched blocks.

Duplication Details

Pattern: “open repo → create fsManager → checkSoftDeleted”
  • Severity: Medium
  • Occurrences: 8 (exact duplicate block; additional near-duplicates exist in the same files)
  • Locations:
    • server/gitrest/packages/gitrest-base/src/routes/git/blobs.ts (lines 63–80)
    • server/gitrest/packages/gitrest-base/src/routes/git/refs.ts (lines 44–61)
    • server/gitrest/packages/gitrest-base/src/routes/git/refs.ts (lines 70–87)
    • server/gitrest/packages/gitrest-base/src/routes/git/refs.ts (lines 163–180)
    • server/gitrest/packages/gitrest-base/src/routes/git/tags.ts (lines 62–79)
    • server/gitrest/packages/gitrest-base/src/routes/git/trees.ts (lines 60–77)
    • server/gitrest/packages/gitrest-base/src/routes/repository/commits.ts (lines 37–54)
    • server/gitrest/packages/gitrest-base/src/routes/repository/contents.ts (lines 29–46)

Code sample (from blobs.ts):

const repoManagerParams = getRepoManagerParamsFromRequest(request);
const resultP = repoManagerFactory
	.open(repoManagerParams)
	.then(async (repoManager) => {
		const fileSystemManagerFactory = getFilesystemManagerFactory(
			fileSystemManagerFactories,
			repoManagerParams.isEphemeralContainer ?? false,
		);
		const fsManager = fileSystemManagerFactory.create({
			...repoManagerParams.fileSystemManagerParams,
			rootDir: repoManager.path,
		});
		await checkSoftDeleted(
			fsManager,
			repoManager.path,
			repoManagerParams,
			repoPerDocEnabled,
		);
		// handler-specific repoManager call...
	});

Impact Analysis

  • Maintainability: Future changes to soft-delete semantics, repo-per-doc behavior, or FS manager options require editing many route handlers.
  • Bug Risk: High likelihood of drift (one route updated, another missed), especially since some handlers use repoManagerFactory.open(...) while others use getRepoManagerFromWriteAPI(...).
  • Code Bloat: ~18 duplicated lines per occurrence (+ near-duplicates), spread across multiple route modules.

Refactoring Recommendations

  1. Extract a shared helper in server/gitrest/packages/gitrest-base/src/utils

    • Proposed shape (example):
      • async function openRepoAndGetFsManager(request, { repoManagerFactory, fileSystemManagerFactories, repoPerDocEnabled, write: boolean }): Promise<{ repoManagerParams, repoManager, fsManager }>
    • Centralize:
      • getRepoManagerParamsFromRequest(request)
      • getFilesystemManagerFactory(...).create(...)
      • checkSoftDeleted(...)
    • Keep open vs getRepoManagerFromWriteAPI selection as a parameter.
  2. Optional: wrap the error-handling/promise plumbing

    • Consider a helper that returns the resultP already wired with .catch((error) => logAndThrowApiError(...)) so route handlers become small and consistent.

Implementation Checklist

  • Create helper in server/gitrest/packages/gitrest-base/src/utils
  • Update affected route modules to call helper
  • Ensure behavior parity for ephemeral containers and repo-per-doc
  • Run existing Gitrest/unit/integration tests (as appropriate)

Analysis Metadata

  • Analyzed Files: 2,835 eligible .ts/.mjs/.cjs files (excluding tests/workflows)
  • Detection Method: Exact clone scan + Serena-assisted inspection
  • Commit: 705e92735ec8ed44b6819739520bdd22d3c27f6d
  • Analysis Date: 2026-04-11

Generated by Duplicate Code Detector ·

To install this agentic workflow, run

gh aw add github/gh-aw/.github/workflows/duplicate-code-detector.md@94662b1dee8ce96c876ba9f33b3ab8be32de82a4

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the duplicated blocks in blobs.ts, refs.ts, tags.ts, trees.ts, repository/commits.ts, and repository/contents.ts, then inspect the shared utils directory and existing Gitrest tests. Define the helper boundaries while preserving open versus write-manager behavior, ephemeral-container handling, and repo-per-doc checks. Done means the affected routes use the shared helper and the existing Gitrest, unit, and integration tests pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.