From ccbd974e185a15d14853e8319a6590781dc47975 Mon Sep 17 00:00:00 2001 From: Kyle Rader Date: Mon, 13 Aug 2018 14:32:32 -0700 Subject: [PATCH 1/4] Add --force flag to fast fetch (apply patch from VSTS work) --- GVFS/FastFetch/CheckoutPrefetcher.cs | 4 +- GVFS/FastFetch/FastFetchVerb.cs | 9 ++- GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs | 15 +++-- GVFS/GVFS.Common/Prefetch/Jobs/CheckoutJob.cs | 16 +++++- .../Tests/FastFetchTests.cs | 56 +++++++++++++++++++ 5 files changed, 89 insertions(+), 11 deletions(-) diff --git a/GVFS/FastFetch/CheckoutPrefetcher.cs b/GVFS/FastFetch/CheckoutPrefetcher.cs index 16a8a09bd..b344a5847 100644 --- a/GVFS/FastFetch/CheckoutPrefetcher.cs +++ b/GVFS/FastFetch/CheckoutPrefetcher.cs @@ -33,7 +33,7 @@ public CheckoutPrefetcher( } /// A specific branch to filter for, or null for all branches returned from info/refs - public override void Prefetch(string branchOrCommit, bool isBranch) + public override void Prefetch(string branchOrCommit, bool isBranch, bool force = false) { if (string.IsNullOrWhiteSpace(branchOrCommit)) { @@ -66,7 +66,7 @@ public override void Prefetch(string branchOrCommit, bool isBranch) // Configure pipeline // Checkout uses DiffHelper when running checkout.Start(), which we use instead of LsTreeHelper // Checkout diff output => FindMissingBlobs => BatchDownload => IndexPack => Checkout available blobs - CheckoutJob checkout = new CheckoutJob(this.checkoutThreadCount, this.FolderList, commitToFetch, this.Tracer, this.Enlistment); + CheckoutJob checkout = new CheckoutJob(this.checkoutThreadCount, this.FolderList, commitToFetch, this.Tracer, this.Enlistment, force: force); FindMissingBlobsJob blobFinder = new FindMissingBlobsJob(this.SearchThreadCount, checkout.RequiredBlobs, checkout.AvailableBlobShas, this.Tracer, this.Enlistment); BatchObjectDownloadJob downloader = new BatchObjectDownloadJob(this.DownloadThreadCount, this.ChunkSize, blobFinder.MissingBlobs, checkout.AvailableBlobShas, this.Tracer, this.Enlistment, this.ObjectRequestor, this.GitObjects); IndexPackJob packIndexer = new IndexPackJob(this.IndexThreadCount, downloader.AvailablePacks, checkout.AvailableBlobShas, this.Tracer, this.GitObjects); diff --git a/GVFS/FastFetch/FastFetchVerb.cs b/GVFS/FastFetch/FastFetchVerb.cs index 1c62a09b0..16f45dcab 100644 --- a/GVFS/FastFetch/FastFetchVerb.cs +++ b/GVFS/FastFetch/FastFetchVerb.cs @@ -135,6 +135,13 @@ public class FastFetchVerb HelpText = "The GUID of the caller - used for telemetry purposes.")] public string ParentActivityId { get; set; } + [Option( + "force", + Required = false, + Default = false, + HelpText = "Force FastFetch to download content as if the current repo was at commit id 0 (Had just been initialized).")] + public bool Force { get; set; } + public void Execute() { Environment.ExitCode = this.ExecuteWithExitCode(); @@ -237,7 +244,7 @@ private int ExecuteWithExitCode() try { bool isBranch = this.Commit == null; - prefetcher.Prefetch(commitish, isBranch); + prefetcher.Prefetch(commitish, isBranch, force: this.Force); return !prefetcher.HasFailures; } catch (BlobPrefetcher.FetchException e) diff --git a/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs b/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs index a3972b412..9b5455b97 100644 --- a/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs +++ b/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs @@ -162,13 +162,13 @@ public static void AppendToNewlineSeparatedFile(PhysicalFileSystem fileSystem, s } /// A specific branch to filter for, or null for all branches returned from info/refs - public virtual void Prefetch(string branchOrCommit, bool isBranch) + public virtual void Prefetch(string branchOrCommit, bool isBranch, bool force = false) { int matchedBlobCount; int downloadedBlobCount; int readFileCount; - this.PrefetchWithStats(branchOrCommit, isBranch, false, out matchedBlobCount, out downloadedBlobCount, out readFileCount); + this.PrefetchWithStats(branchOrCommit, isBranch, false, out matchedBlobCount, out downloadedBlobCount, out readFileCount, force: force); } public void PrefetchWithStats( @@ -177,7 +177,8 @@ public void PrefetchWithStats( bool readFilesAfterDownload, out int matchedBlobCount, out int downloadedBlobCount, - out int readFileCount) + out int readFileCount, + bool force = false) { matchedBlobCount = 0; downloadedBlobCount = 0; @@ -217,9 +218,9 @@ public void PrefetchWithStats( string previousCommit = null; - // Use the shallow file to find a recent commit to diff against to try and reduce the number of SHAs to check - DiffHelper blobEnumerator = new DiffHelper(this.Tracer, this.Enlistment, this.FileList, this.FolderList); - if (File.Exists(shallowFile)) + // Use the shallow file to find a recent commit to diff against to try and reduce the number of SHAs to check. + // Unless force flag has been given, in which case treat as if it's a fresh repo. + if (!force && File.Exists(shallowFile)) { previousCommit = File.ReadAllLines(shallowFile).Where(line => !string.IsNullOrWhiteSpace(line)).LastOrDefault(); if (string.IsNullOrWhiteSpace(previousCommit)) @@ -230,6 +231,8 @@ public void PrefetchWithStats( } } + DiffHelper blobEnumerator = new DiffHelper(this.Tracer, this.Enlistment, this.FileList, this.FolderList); + ThreadStart performDiff = () => { blobEnumerator.PerformDiff(previousCommit, commitToFetch); diff --git a/GVFS/GVFS.Common/Prefetch/Jobs/CheckoutJob.cs b/GVFS/GVFS.Common/Prefetch/Jobs/CheckoutJob.cs index bce0921cb..0a464a09c 100644 --- a/GVFS/GVFS.Common/Prefetch/Jobs/CheckoutJob.cs +++ b/GVFS/GVFS.Common/Prefetch/Jobs/CheckoutJob.cs @@ -19,6 +19,7 @@ public class CheckoutJob : Job private ITracer tracer; private Enlistment enlistment; private string targetCommitSha; + private bool force; private DiffHelper diff; @@ -31,13 +32,14 @@ public class CheckoutJob : Job // Checkout requires synchronization between the delete/directory/add stages, so control the parallelization private int maxParallel; - public CheckoutJob(int maxParallel, IEnumerable folderList, string targetCommitSha, ITracer tracer, Enlistment enlistment) + public CheckoutJob(int maxParallel, IEnumerable folderList, string targetCommitSha, ITracer tracer, Enlistment enlistment, bool force = false) : base(1) { this.tracer = tracer.StartActivity(AreaPath, EventLevel.Informational, Keywords.Telemetry, metadata: null); this.enlistment = enlistment; this.diff = new DiffHelper(tracer, enlistment, new string[0], folderList); this.targetCommitSha = targetCommitSha; + this.force = force; this.AvailableBlobShas = new BlockingCollection(); // Keep track of how parallel we're expected to be later during DoWork @@ -62,7 +64,17 @@ public bool UpdatedWholeTree protected override void DoBeforeWork() { - this.diff.PerformDiff(this.targetCommitSha); + if (this.force) + { + // When using force set the sourceCommitSha to null to act like an uninitialized repo + this.diff.PerformDiff(null, this.targetCommitSha); + } + else + { + // This variant of diff uses the HEAD as the SourceCommitSha. + this.diff.PerformDiff(this.targetCommitSha); + } + this.HasFailures = this.diff.HasFailures; } diff --git a/GVFS/GVFS.FunctionalTests/Tests/FastFetchTests.cs b/GVFS/GVFS.FunctionalTests/Tests/FastFetchTests.cs index 979c72649..521193ee7 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/FastFetchTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/FastFetchTests.cs @@ -100,6 +100,62 @@ public void CanFetchAndCheckoutASingleFolderIntoEmptyGitRepo() this.AllFetchedFilePathsShouldPassCheck(path => path.StartsWith("GVFS", StringComparison.OrdinalIgnoreCase)); } + [TestCase] + public void CanFetchAndCheckoutMultipleTimesUsingForceFlag() + { + this.RunFastFetch($"--checkout --folders \"/GVFS\" -b {Settings.Default.Commitish}"); + + this.CurrentBranchShouldEqual(Settings.Default.Commitish); + + this.fastFetchRepoRoot.ShouldBeADirectory(FileSystemRunner.DefaultRunner); + List dirs = Directory.EnumerateFileSystemEntries(this.fastFetchRepoRoot).ToList(); + dirs.SequenceEqual(new[] + { + Path.Combine(this.fastFetchRepoRoot, ".git"), + Path.Combine(this.fastFetchRepoRoot, "GVFS"), + Path.Combine(this.fastFetchRepoRoot, "GVFS.sln") + }); + + Directory.EnumerateFileSystemEntries(Path.Combine(this.fastFetchRepoRoot, "GVFS"), "*", SearchOption.AllDirectories) + .Count() + .ShouldEqual(345); + this.AllFetchedFilePathsShouldPassCheck(path => path.StartsWith("GVFS", StringComparison.OrdinalIgnoreCase)); + + // Run a second time in the same repo on the same branch with more folders. + this.RunFastFetch($"--checkout --folders \"/GVFS;/Scripts\" -b {Settings.Default.Commitish} --force"); + dirs = Directory.EnumerateFileSystemEntries(this.fastFetchRepoRoot).ToList(); + dirs.SequenceEqual(new[] + { + Path.Combine(this.fastFetchRepoRoot, ".git"), + Path.Combine(this.fastFetchRepoRoot, "GVFS"), + Path.Combine(this.fastFetchRepoRoot, "Scripts"), + Path.Combine(this.fastFetchRepoRoot, "GVFS.sln") + }); + Directory.EnumerateFileSystemEntries(Path.Combine(this.fastFetchRepoRoot, "Scripts"), "*", SearchOption.AllDirectories) + .Count() + .ShouldEqual(5); + } + + [TestCase] + public void CanFetchWithoutCheckoutMultipleTimesUsingForceFlagAndThenCheckout() + { + this.RunFastFetch($"--folders \"/GVFS\" -b {Settings.Default.Commitish}"); + + this.GetRefTreeSha("remotes/origin/" + Settings.Default.Commitish).ShouldNotBeNull(); + + // Run a second time in the same repo on the same branch with more folders. + this.RunFastFetch($"--folders \"/GVFS;/Scripts\" -b {Settings.Default.Commitish} --force"); + + this.RunFastFetch($"--checkout -b {Settings.Default.Commitish}"); + Directory.EnumerateFileSystemEntries(Path.Combine(this.fastFetchRepoRoot, "GVFS"), "*", SearchOption.AllDirectories) + .Count() + .ShouldEqual(345); + + Directory.EnumerateFileSystemEntries(Path.Combine(this.fastFetchRepoRoot, "Scripts"), "*", SearchOption.AllDirectories) + .Count() + .ShouldEqual(5); + } + [TestCase] public void FastFetchFolderWithOnlyOneFile() { From 2a6b4dac88af4a1ca4def288c4f5bd013c82daf8 Mon Sep 17 00:00:00 2001 From: Kyle Rader Date: Mon, 13 Aug 2018 14:48:09 -0700 Subject: [PATCH 2/4] Simplify help text for force flag --- GVFS/FastFetch/FastFetchVerb.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GVFS/FastFetch/FastFetchVerb.cs b/GVFS/FastFetch/FastFetchVerb.cs index 16f45dcab..ce3ce312d 100644 --- a/GVFS/FastFetch/FastFetchVerb.cs +++ b/GVFS/FastFetch/FastFetchVerb.cs @@ -139,7 +139,7 @@ public class FastFetchVerb "force", Required = false, Default = false, - HelpText = "Force FastFetch to download content as if the current repo was at commit id 0 (Had just been initialized).")] + HelpText = "Force FastFetch to download content as if the current repository was just initialized.")] public bool Force { get; set; } public void Execute() From 22e41b56931dc8d31cda633286ee41e186d7956b Mon Sep 17 00:00:00 2001 From: Kyle Rader Date: Tue, 14 Aug 2018 10:13:01 -0700 Subject: [PATCH 3/4] Rename force to force-checkout and pull into FastFetch CheckoutJob --- .../Jobs => FastFetch}/CheckoutJob.cs | 20 +++++++------- GVFS/FastFetch/CheckoutPrefetcher.cs | 11 +++++--- GVFS/FastFetch/FastFetch.csproj | 1 + GVFS/FastFetch/FastFetchVerb.cs | 27 ++++++++++++------- GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs | 9 +++---- .../Tests/FastFetchTests.cs | 22 +++++---------- 6 files changed, 48 insertions(+), 42 deletions(-) rename GVFS/{GVFS.Common/Prefetch/Jobs => FastFetch}/CheckoutJob.cs (93%) diff --git a/GVFS/GVFS.Common/Prefetch/Jobs/CheckoutJob.cs b/GVFS/FastFetch/CheckoutJob.cs similarity index 93% rename from GVFS/GVFS.Common/Prefetch/Jobs/CheckoutJob.cs rename to GVFS/FastFetch/CheckoutJob.cs index 0a464a09c..a86079f22 100644 --- a/GVFS/GVFS.Common/Prefetch/Jobs/CheckoutJob.cs +++ b/GVFS/FastFetch/CheckoutJob.cs @@ -1,6 +1,8 @@ -using GVFS.Common.FileSystem; +using GVFS.Common; +using GVFS.Common.FileSystem; using GVFS.Common.Git; using GVFS.Common.Prefetch.Git; +using GVFS.Common.Prefetch.Jobs; using GVFS.Common.Tracing; using System; using System.Collections.Concurrent; @@ -9,7 +11,7 @@ using System.Threading; using System.Threading.Tasks; -namespace GVFS.Common.Prefetch.Jobs +namespace FastFetch { public class CheckoutJob : Job { @@ -19,7 +21,7 @@ public class CheckoutJob : Job private ITracer tracer; private Enlistment enlistment; private string targetCommitSha; - private bool force; + private bool forceCheckout; private DiffHelper diff; @@ -32,14 +34,14 @@ public class CheckoutJob : Job // Checkout requires synchronization between the delete/directory/add stages, so control the parallelization private int maxParallel; - public CheckoutJob(int maxParallel, IEnumerable folderList, string targetCommitSha, ITracer tracer, Enlistment enlistment, bool force = false) + public CheckoutJob(int maxParallel, IEnumerable folderList, string targetCommitSha, ITracer tracer, Enlistment enlistment, bool forceCheckout) : base(1) { this.tracer = tracer.StartActivity(AreaPath, EventLevel.Informational, Keywords.Telemetry, metadata: null); this.enlistment = enlistment; this.diff = new DiffHelper(tracer, enlistment, new string[0], folderList); this.targetCommitSha = targetCommitSha; - this.force = force; + this.forceCheckout = forceCheckout; this.AvailableBlobShas = new BlockingCollection(); // Keep track of how parallel we're expected to be later during DoWork @@ -64,14 +66,14 @@ public bool UpdatedWholeTree protected override void DoBeforeWork() { - if (this.force) + if (this.forceCheckout) { - // When using force set the sourceCommitSha to null to act like an uninitialized repo - this.diff.PerformDiff(null, this.targetCommitSha); + // Force search the entire tree by treating the repo as if it were brand new. + this.diff.PerformDiff(sourceTreeSha: null, targetTreeSha: this.targetCommitSha); } else { - // This variant of diff uses the HEAD as the SourceCommitSha. + // Let the diff find the sourceTreeSha on its own. this.diff.PerformDiff(this.targetCommitSha); } diff --git a/GVFS/FastFetch/CheckoutPrefetcher.cs b/GVFS/FastFetch/CheckoutPrefetcher.cs index b344a5847..863acca15 100644 --- a/GVFS/FastFetch/CheckoutPrefetcher.cs +++ b/GVFS/FastFetch/CheckoutPrefetcher.cs @@ -14,8 +14,9 @@ namespace FastFetch { public class CheckoutPrefetcher : BlobPrefetcher { - private readonly bool allowIndexMetadataUpdateFromWorkingTree; private readonly int checkoutThreadCount; + private readonly bool allowIndexMetadataUpdateFromWorkingTree; + private readonly bool forceCheckout; public CheckoutPrefetcher( ITracer tracer, @@ -26,14 +27,16 @@ public CheckoutPrefetcher( int downloadThreadCount, int indexThreadCount, int checkoutThreadCount, - bool allowIndexMetadataUpdateFromWorkingTree) : base(tracer, enlistment, objectRequestor, chunkSize, searchThreadCount, downloadThreadCount, indexThreadCount) + bool allowIndexMetadataUpdateFromWorkingTree, + bool forceCheckout) : base(tracer, enlistment, objectRequestor, chunkSize, searchThreadCount, downloadThreadCount, indexThreadCount) { this.checkoutThreadCount = checkoutThreadCount; this.allowIndexMetadataUpdateFromWorkingTree = allowIndexMetadataUpdateFromWorkingTree; + this.forceCheckout = forceCheckout; } /// A specific branch to filter for, or null for all branches returned from info/refs - public override void Prefetch(string branchOrCommit, bool isBranch, bool force = false) + public override void Prefetch(string branchOrCommit, bool isBranch) { if (string.IsNullOrWhiteSpace(branchOrCommit)) { @@ -66,7 +69,7 @@ public override void Prefetch(string branchOrCommit, bool isBranch, bool force = // Configure pipeline // Checkout uses DiffHelper when running checkout.Start(), which we use instead of LsTreeHelper // Checkout diff output => FindMissingBlobs => BatchDownload => IndexPack => Checkout available blobs - CheckoutJob checkout = new CheckoutJob(this.checkoutThreadCount, this.FolderList, commitToFetch, this.Tracer, this.Enlistment, force: force); + CheckoutJob checkout = new CheckoutJob(this.checkoutThreadCount, this.FolderList, commitToFetch, this.Tracer, this.Enlistment, this.forceCheckout); FindMissingBlobsJob blobFinder = new FindMissingBlobsJob(this.SearchThreadCount, checkout.RequiredBlobs, checkout.AvailableBlobShas, this.Tracer, this.Enlistment); BatchObjectDownloadJob downloader = new BatchObjectDownloadJob(this.DownloadThreadCount, this.ChunkSize, blobFinder.MissingBlobs, checkout.AvailableBlobShas, this.Tracer, this.Enlistment, this.ObjectRequestor, this.GitObjects); IndexPackJob packIndexer = new IndexPackJob(this.IndexThreadCount, downloader.AvailablePacks, checkout.AvailableBlobShas, this.Tracer, this.GitObjects); diff --git a/GVFS/FastFetch/FastFetch.csproj b/GVFS/FastFetch/FastFetch.csproj index 5658cdade..f4544cd62 100644 --- a/GVFS/FastFetch/FastFetch.csproj +++ b/GVFS/FastFetch/FastFetch.csproj @@ -56,6 +56,7 @@ CommonAssemblyVersion.cs + diff --git a/GVFS/FastFetch/FastFetchVerb.cs b/GVFS/FastFetch/FastFetchVerb.cs index ce3ce312d..bf961df91 100644 --- a/GVFS/FastFetch/FastFetchVerb.cs +++ b/GVFS/FastFetch/FastFetchVerb.cs @@ -54,6 +54,15 @@ public class FastFetchVerb HelpText = "Checkout the target commit into the working directory after fetching")] public bool Checkout { get; set; } + [Option( + "force-checkout", + Required = false, + Default = false, + HelpText = "Force FastFetch to fetch and checkout content as if the current repo had just been initialized." + + "This allows you to include more folders from the repo that were not originally checked out." + + "Can only be used with --checkout")] + public bool ForceCheckout { get; set; } + [Option( "search-thread-count", Required = false, @@ -135,13 +144,6 @@ public class FastFetchVerb HelpText = "The GUID of the caller - used for telemetry purposes.")] public string ParentActivityId { get; set; } - [Option( - "force", - Required = false, - Default = false, - HelpText = "Force FastFetch to download content as if the current repository was just initialized.")] - public bool Force { get; set; } - public void Execute() { Environment.ExitCode = this.ExecuteWithExitCode(); @@ -164,6 +166,12 @@ private int ExecuteWithExitCode() Console.WriteLine("Cannot specify both a commit sha and a branch name."); return ExitFailure; } + + if (this.ForceCheckout && !this.Checkout) + { + Console.WriteLine("Cannot use --force-checkout option without --checkout option."); + return ExitFailure; + } this.SearchThreadCount = this.SearchThreadCount > 0 ? this.SearchThreadCount : Environment.ProcessorCount; this.DownloadThreadCount = this.DownloadThreadCount > 0 ? this.DownloadThreadCount : Math.Min(Environment.ProcessorCount, MaxDefaultDownloadThreads); @@ -244,7 +252,7 @@ private int ExecuteWithExitCode() try { bool isBranch = this.Commit == null; - prefetcher.Prefetch(commitish, isBranch, force: this.Force); + prefetcher.Prefetch(commitish, isBranch); return !prefetcher.HasFailures; } catch (BlobPrefetcher.FetchException e) @@ -325,7 +333,8 @@ private BlobPrefetcher GetFolderPrefetcher(ITracer tracer, Enlistment enlistment this.DownloadThreadCount, this.IndexThreadCount, this.CheckoutThreadCount, - this.AllowIndexMetadataUpdateFromWorkingTree); + this.AllowIndexMetadataUpdateFromWorkingTree, + this.ForceCheckout); } else { diff --git a/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs b/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs index 9b5455b97..7c633a1de 100644 --- a/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs +++ b/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs @@ -162,13 +162,13 @@ public static void AppendToNewlineSeparatedFile(PhysicalFileSystem fileSystem, s } /// A specific branch to filter for, or null for all branches returned from info/refs - public virtual void Prefetch(string branchOrCommit, bool isBranch, bool force = false) + public virtual void Prefetch(string branchOrCommit, bool isBranch) { int matchedBlobCount; int downloadedBlobCount; int readFileCount; - this.PrefetchWithStats(branchOrCommit, isBranch, false, out matchedBlobCount, out downloadedBlobCount, out readFileCount, force: force); + this.PrefetchWithStats(branchOrCommit, isBranch, false, out matchedBlobCount, out downloadedBlobCount, out readFileCount); } public void PrefetchWithStats( @@ -177,8 +177,7 @@ public void PrefetchWithStats( bool readFilesAfterDownload, out int matchedBlobCount, out int downloadedBlobCount, - out int readFileCount, - bool force = false) + out int readFileCount) { matchedBlobCount = 0; downloadedBlobCount = 0; @@ -220,7 +219,7 @@ public void PrefetchWithStats( // Use the shallow file to find a recent commit to diff against to try and reduce the number of SHAs to check. // Unless force flag has been given, in which case treat as if it's a fresh repo. - if (!force && File.Exists(shallowFile)) + if (File.Exists(shallowFile)) { previousCommit = File.ReadAllLines(shallowFile).Where(line => !string.IsNullOrWhiteSpace(line)).LastOrDefault(); if (string.IsNullOrWhiteSpace(previousCommit)) diff --git a/GVFS/GVFS.FunctionalTests/Tests/FastFetchTests.cs b/GVFS/GVFS.FunctionalTests/Tests/FastFetchTests.cs index 521193ee7..69e1bdc5c 100644 --- a/GVFS/GVFS.FunctionalTests/Tests/FastFetchTests.cs +++ b/GVFS/GVFS.FunctionalTests/Tests/FastFetchTests.cs @@ -101,7 +101,7 @@ public void CanFetchAndCheckoutASingleFolderIntoEmptyGitRepo() } [TestCase] - public void CanFetchAndCheckoutMultipleTimesUsingForceFlag() + public void CanFetchAndCheckoutMultipleTimesUsingForceCheckoutFlag() { this.RunFastFetch($"--checkout --folders \"/GVFS\" -b {Settings.Default.Commitish}"); @@ -122,7 +122,7 @@ public void CanFetchAndCheckoutMultipleTimesUsingForceFlag() this.AllFetchedFilePathsShouldPassCheck(path => path.StartsWith("GVFS", StringComparison.OrdinalIgnoreCase)); // Run a second time in the same repo on the same branch with more folders. - this.RunFastFetch($"--checkout --folders \"/GVFS;/Scripts\" -b {Settings.Default.Commitish} --force"); + this.RunFastFetch($"--checkout --folders \"/GVFS;/Scripts\" -b {Settings.Default.Commitish} --force-checkout"); dirs = Directory.EnumerateFileSystemEntries(this.fastFetchRepoRoot).ToList(); dirs.SequenceEqual(new[] { @@ -137,23 +137,15 @@ public void CanFetchAndCheckoutMultipleTimesUsingForceFlag() } [TestCase] - public void CanFetchWithoutCheckoutMultipleTimesUsingForceFlagAndThenCheckout() + public void ForceCheckoutRequiresCheckout() { - this.RunFastFetch($"--folders \"/GVFS\" -b {Settings.Default.Commitish}"); - - this.GetRefTreeSha("remotes/origin/" + Settings.Default.Commitish).ShouldNotBeNull(); + this.RunFastFetch($"--checkout --folders \"/Scripts\" -b {Settings.Default.Commitish}"); // Run a second time in the same repo on the same branch with more folders. - this.RunFastFetch($"--folders \"/GVFS;/Scripts\" -b {Settings.Default.Commitish} --force"); - - this.RunFastFetch($"--checkout -b {Settings.Default.Commitish}"); - Directory.EnumerateFileSystemEntries(Path.Combine(this.fastFetchRepoRoot, "GVFS"), "*", SearchOption.AllDirectories) - .Count() - .ShouldEqual(345); + string result = this.RunFastFetch($"--force-checkout --folders \"/GVFS;/Scripts\" -b {Settings.Default.Commitish}"); - Directory.EnumerateFileSystemEntries(Path.Combine(this.fastFetchRepoRoot, "Scripts"), "*", SearchOption.AllDirectories) - .Count() - .ShouldEqual(5); + string[] expectedResults = new string[] { "Cannot use --force-checkout option without --checkout option." }; + result.ShouldContain(expectedResults); } [TestCase] From f41452da7ef70ca30f0a58c4d7b22a1fec9c7d83 Mon Sep 17 00:00:00 2001 From: Kyle Rader Date: Tue, 14 Aug 2018 13:21:30 -0700 Subject: [PATCH 4/4] Update comments and help text --- GVFS/FastFetch/FastFetchVerb.cs | 4 ++-- GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/GVFS/FastFetch/FastFetchVerb.cs b/GVFS/FastFetch/FastFetchVerb.cs index bf961df91..82cf59fcc 100644 --- a/GVFS/FastFetch/FastFetchVerb.cs +++ b/GVFS/FastFetch/FastFetchVerb.cs @@ -58,9 +58,9 @@ public class FastFetchVerb "force-checkout", Required = false, Default = false, - HelpText = "Force FastFetch to fetch and checkout content as if the current repo had just been initialized." + + HelpText = "Force FastFetch to checkout content as if the current repo had just been initialized." + "This allows you to include more folders from the repo that were not originally checked out." + - "Can only be used with --checkout")] + "Can only be used with the --checkout option.")] public bool ForceCheckout { get; set; } [Option( diff --git a/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs b/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs index 7c633a1de..66f1ad0f4 100644 --- a/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs +++ b/GVFS/GVFS.Common/Prefetch/BlobPrefetcher.cs @@ -218,7 +218,6 @@ public void PrefetchWithStats( string previousCommit = null; // Use the shallow file to find a recent commit to diff against to try and reduce the number of SHAs to check. - // Unless force flag has been given, in which case treat as if it's a fresh repo. if (File.Exists(shallowFile)) { previousCommit = File.ReadAllLines(shallowFile).Where(line => !string.IsNullOrWhiteSpace(line)).LastOrDefault();