Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions GVFS/GVFS.Common/Git/GitRepo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,35 @@ public virtual bool CommitAndRootTreeExists(string commitSha, out string rootTre
return output;
}

/// <summary>
/// Check whether a given object SHA exists as a loose object file
/// in the shared cache or local object store.
/// </summary>
public virtual bool LooseObjectExists(string sha)
{
if (GVFSPlatform.Instance.Constants.CaseSensitiveFileSystem)
{
sha = sha.ToLower();
}

string looseObjectPath = Path.Combine(
Comment thread
tyrielv marked this conversation as resolved.
this.enlistment.GitObjectsRoot,
sha.Substring(0, 2),
sha.Substring(2));

if (this.fileSystem.FileExists(looseObjectPath))
{
return true;
}

looseObjectPath = Path.Combine(
this.enlistment.LocalObjectsRoot,
sha.Substring(0, 2),
sha.Substring(2));

return this.fileSystem.FileExists(looseObjectPath);
}

public virtual bool ObjectExists(string blobSha)
{
bool output = false;
Expand Down
26 changes: 22 additions & 4 deletions GVFS/GVFS/CommandLine/GVFSVerb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -487,15 +487,33 @@ protected bool TryDownloadCommit(
out string error,
bool checkLocalObjectCache = true)
{
if (!checkLocalObjectCache || !repo.CommitAndRootTreeExists(commitId, out _))
if (checkLocalObjectCache && repo.CommitAndRootTreeExists(commitId, out _))
{
if (!gitObjects.TryDownloadCommit(commitId))
if (repo.LooseObjectExists(commitId))
{
error = "Could not download commit " + commitId + " from: " + Uri.EscapeDataString(objectRequestor.CacheServer.ObjectsEndpointUrl);
return false;
// The commit exists as a loose object (e.g., from a prior 'git show'
// or 'git log' in a mounted enlistment). Loose commits do not include
// their reachable trees — those would need to be fetched individually.
// Download the commit pack which includes all reachable trees so that
// operations like 'git checkout -f' can succeed without the read-object
// hook.
}
else
{
// The commit exists in a pack file (prefetch pack or a previous commit
// pack download). Packs from the GVFS protocol include all reachable
// trees, so we can safely skip re-downloading.
error = null;
Comment thread
tyrielv marked this conversation as resolved.
return true;
}
}

if (!gitObjects.TryDownloadCommit(commitId))
{
error = "Could not download commit " + commitId + " from: " + Uri.EscapeDataString(objectRequestor.CacheServer.ObjectsEndpointUrl);
return false;
}

error = null;
return true;
}
Expand Down
Loading