Ejemplo n.º 1
0
        public override void Execute()
        {
            PhysicalFileSystem fileSystem = new PhysicalFileSystem();

            this.ValidatePathParameter(this.EnlistmentRootPathParameter);

            ScalarEnlistment enlistment = this.CreateEnlistment(this.EnlistmentRootPathParameter ?? Directory.GetCurrentDirectory(), null);

            using (JsonTracer tracer = new JsonTracer(ScalarConstants.ScalarEtwProviderName, RegisterVerb.RegisterVerbName))
            {
                if (this.TryRegisterRepo(tracer, enlistment, fileSystem, out string error))
                {
                    this.Output.WriteLine($"Successfully registered repo at '{enlistment.EnlistmentRoot}'");
                }
                else
                {
                    string message = $"Failed to register repo: {error}";
                    tracer.RelatedError(message);
                    this.ReportErrorAndExit(message);
                    return;
                }

                ScalarContext context = new ScalarContext(tracer, fileSystem, enlistment);
                new ConfigStep(context).Execute();
            }
        }
Ejemplo n.º 2
0
        private void TestSetup()
        {
            ITracer            tracer     = new MockTracer();
            ScalarEnlistment   enlistment = new MockScalarEnlistment();
            PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.EnlistmentRoot, null, null));

            this.context = new ScalarContext(tracer, fileSystem, enlistment);
        }
Ejemplo n.º 3
0
 public LooseObjectsStep(
     ScalarContext context,
     bool requireCacheLock = true,
     bool forceRun         = false,
     GitProcessChecker gitProcessChecker = null)
     : base(context, requireCacheLock, gitProcessChecker)
 {
     this.forceRun = forceRun;
 }
Ejemplo n.º 4
0
 public FetchStep(
     ScalarContext context,
     GitObjects gitObjects,
     bool requireCacheLock = true,
     bool forceRun         = false)
     : base(context, requireCacheLock)
 {
     this.GitObjects = gitObjects;
     this.forceRun   = forceRun;
 }
Ejemplo n.º 5
0
 public PackfileMaintenanceStep(
     ScalarContext context,
     bool requireObjectCacheLock = true,
     bool forceRun    = false,
     string batchSize = null,
     GitProcessChecker gitProcessChecker = null)
     : base(context, requireObjectCacheLock, gitProcessChecker)
 {
     this.forceRun  = forceRun;
     this.batchSize = batchSize ?? DefaultBatchSizeBytes.ToString();
 }
Ejemplo n.º 6
0
        private void TestSetup()
        {
            this.gitProcess = new MockGitProcess();

            // Create enlistment using git process
            ScalarEnlistment enlistment = new MockScalarEnlistment(this.gitProcess);

            PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.EnlistmentRoot, null, null));

            // Create and return Context
            this.tracer  = new MockTracer();
            this.context = new ScalarContext(this.tracer, fileSystem, enlistment: enlistment);
        }
Ejemplo n.º 7
0
 public static bool EnlistmentRootReady(ScalarContext context)
 {
     // If a user locks their drive or disconnects an external drive while the process
     // is running, then it will appear as if the directories below do not exist or throw
     // a "Device is not ready" error.
     try
     {
         return(context.FileSystem.DirectoryExists(context.Enlistment.EnlistmentRoot) &&
                context.FileSystem.DirectoryExists(context.Enlistment.GitObjectsRoot));
     }
     catch (IOException)
     {
         return(false);
     }
 }
Ejemplo n.º 8
0
 public ConfigStep(ScalarContext context, bool?useGvfsProtocol = null) : base(context, requireObjectCacheLock: false)
 {
     this.UseGvfsProtocol = useGvfsProtocol;
 }
Ejemplo n.º 9
0
        private Result CreateClone()
        {
            Result initRepoResult = this.TryInitRepo();

            if (!initRepoResult.Success)
            {
                return(initRepoResult);
            }

            string errorMessage;

            if (!this.TrySetObjectCacheLocation(this.fileSystem, this.enlistment, out errorMessage))
            {
                return(new Result("Error configuring alternate: " + errorMessage));
            }

            this.context = new ScalarContext(this.tracer, this.fileSystem, this.enlistment);

            // Set required and optional config.
            // Explicitly pass useGvfsProtocol: true as the enlistment can not discover that setting from
            // Git config yet. Other verbs will discover this automatically from the config we set now.
            ConfigStep configStep = new ConfigStep(context, useGvfsProtocol: true);

            if (!configStep.TrySetConfig(out string configError))
            {
                return(new Result($"Failed to set initial config: {configError}"));
            }

            CacheServerResolver cacheServerResolver = new CacheServerResolver(this.tracer, this.enlistment);

            if (!cacheServerResolver.TrySaveUrlToLocalConfig(this.cacheServer, out errorMessage))
            {
                return(new Result("Unable to configure cache server: " + errorMessage));
            }

            if (!this.TryDownloadCommit(
                    this.refs.GetTipCommitId(this.Branch),
                    this.enlistment,
                    out errorMessage))
            {
                return(new Result(errorMessage));
            }

            this.git = new GitProcess(this.enlistment);
            string originBranchName = "origin/" + this.Branch;

            GitProcess.Result createBranchResult = this.git.CreateBranchWithUpstream(this.Branch, originBranchName);
            if (createBranchResult.ExitCodeIsFailure)
            {
                return(new Result("Unable to create branch '" + originBranchName + "': " + createBranchResult.Errors + "\r\n" + createBranchResult.Output));
            }

            File.WriteAllText(
                Path.Combine(this.enlistment.WorkingDirectoryRoot, ScalarConstants.DotGit.Head),
                "ref: refs/heads/" + this.Branch);

            try
            {
                this.LogEnlistmentInfoAndSetConfigValues(this.tracer, this.git, this.enlistment);
            }
            catch (Exception e)
            {
                this.tracer.RelatedError(e.ToString());
                return(new Result(e.Message));
            }

            return(new Result(true));
        }
Ejemplo n.º 10
0
        private void TestSetup(DateTime lastRun)
        {
            string lastRunTime = EpochConverter.ToUnixEpochSeconds(lastRun).ToString();

            // Create GitProcess
            this.gitProcess = new MockGitProcess();
            this.gitProcess.SetExpectedCommandResult(
                PrunePackedCommand,
                () => new GitProcess.Result(string.Empty, string.Empty, GitProcess.Result.SuccessCode));

            // Create enlistment using git process
            ScalarEnlistment enlistment = new MockScalarEnlistment(this.gitProcess);

            string packPrefix = Path.Combine(enlistment.GitPackRoot, "from-loose");

            this.packCommand = $"pack-objects {packPrefix} --non-empty --window=0 --depth=0 -q";

            this.gitProcess.SetExpectedCommandResult(
                this.packCommand,
                () => new GitProcess.Result(string.Empty, string.Empty, GitProcess.Result.SuccessCode));

            // Create a last run time file
            MockFile timeFile = new MockFile(Path.Combine(enlistment.GitObjectsRoot, "info", LooseObjectsStep.LooseObjectsLastRunFileName), lastRunTime);

            // Create info directory to hold last run time file
            MockDirectory infoRoot = new MockDirectory(Path.Combine(enlistment.GitObjectsRoot, "info"), null, new List <MockFile>()
            {
                timeFile
            });

            // Create Hex Folder 1 with 1 File
            MockDirectory hex1 = new MockDirectory(
                Path.Combine(enlistment.GitObjectsRoot, "AA"),
                null,
                new List <MockFile>()
            {
                new MockFile(Path.Combine(enlistment.GitObjectsRoot, "AA", "1156f4f2b850673090c285289ea8475d629fe1"), "one")
            });

            // Create Hex Folder 2 with 2 Files
            MockDirectory hex2 = new MockDirectory(
                Path.Combine(enlistment.GitObjectsRoot, "F1"),
                null,
                new List <MockFile>()
            {
                new MockFile(Path.Combine(enlistment.GitObjectsRoot, "F1", "1156f4f2b850673090c285289ea8475d629fe2"), "two"),
                new MockFile(Path.Combine(enlistment.GitObjectsRoot, "F1", "1156f4f2b850673090c285289ea8475d629fe3"), "three")
            });

            // Create NonHex Folder with 4 Files
            MockDirectory nonhex = new MockDirectory(
                Path.Combine(enlistment.GitObjectsRoot, "ZZ"),
                null,
                new List <MockFile>()
            {
                new MockFile(Path.Combine(enlistment.GitObjectsRoot, "ZZ", "1156f4f2b850673090c285289ea8475d629fe4"), "4"),
                new MockFile(Path.Combine(enlistment.GitObjectsRoot, "ZZ", "1156f4f2b850673090c285289ea8475d629fe5"), "5"),
                new MockFile(Path.Combine(enlistment.GitObjectsRoot, "ZZ", "1156f4f2b850673090c285289ea8475d629fe6"), "6"),
                new MockFile(Path.Combine(enlistment.GitObjectsRoot, "ZZ", "1156f4f2b850673090c285289ea8475d629fe7"), "7")
            });

            MockDirectory pack = new MockDirectory(
                enlistment.GitPackRoot,
                null,
                new List <MockFile>());

            // Create git objects directory
            MockDirectory gitObjectsRoot = new MockDirectory(enlistment.GitObjectsRoot, new List <MockDirectory>()
            {
                infoRoot, hex1, hex2, nonhex, pack
            }, null);

            // Add object directory to file System
            List <MockDirectory> directories = new List <MockDirectory>()
            {
                gitObjectsRoot
            };
            PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.EnlistmentRoot, directories, null));

            // Create and return Context
            this.tracer  = new MockTracer();
            this.context = new ScalarContext(this.tracer, fileSystem, enlistment: enlistment);
        }
Ejemplo n.º 11
0
        private Result GitClone()
        {
            string gitBinPath = ScalarPlatform.Instance.GitInstallation.GetInstalledGitBinPath();

            if (string.IsNullOrWhiteSpace(gitBinPath))
            {
                return(new Result(ScalarConstants.GitIsNotInstalledError));
            }

            GitProcess git = new GitProcess(this.enlistment);

            // protocol.version=2 is broken right now.
            git.SetInLocalConfig("protocol.version", "1");

            git.SetInLocalConfig("remote.origin.url", this.RepositoryURL);
            git.SetInLocalConfig("remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*");
            git.SetInLocalConfig("remote.origin.promisor", "true");
            git.SetInLocalConfig("remote.origin.partialCloneFilter", "blob:none");

            string branch = this.Branch ?? "master";

            git.SetInLocalConfig($"branch.{branch}.remote", "origin");
            git.SetInLocalConfig($"branch.{branch}.merge", $"refs/heads/{branch}");

            if (!this.FullClone)
            {
                GitProcess.SparseCheckoutInit(this.enlistment);
            }

            this.context = new ScalarContext(this.tracer, this.fileSystem, this.enlistment);

            // Set required and optional config.
            // Explicitly pass useGvfsProtocol: true as the enlistment can not discover that setting from
            // Git config yet. Other verbs will discover this automatically from the config we set now.
            ConfigStep configStep = new ConfigStep(this.context, useGvfsProtocol: false);

            if (!configStep.TrySetConfig(out string configError))
            {
                return(new Result($"Failed to set initial config: {configError}"));
            }

            GitProcess.Result fetchResult = null;
            if (!this.ShowStatusWhileRunning(() =>
            {
                using (ITracer activity = this.tracer.StartActivity("git-fetch-partial", EventLevel.LogAlways))
                {
                    fetchResult = git.ForegroundFetch("origin");
                    return(fetchResult.ExitCodeIsSuccess);
                }
            },
                                             "Fetching objects from remote"))
            {
                if (!fetchResult.Errors.Contains("filtering not recognized by server"))
                {
                    return(new Result($"Failed to complete regular clone: {fetchResult?.Errors}"));
                }
            }

            if (fetchResult.ExitCodeIsFailure &&
                !this.ShowStatusWhileRunning(() =>
            {
                using (ITracer activity = this.tracer.StartActivity("git-fetch", EventLevel.LogAlways))
                {
                    git.DeleteFromLocalConfig("remote.origin.promisor");
                    git.DeleteFromLocalConfig("remote.origin.partialCloneFilter");
                    fetchResult = git.ForegroundFetch("origin");
                    return(fetchResult.ExitCodeIsSuccess);
                }
            },
                                             "Fetching objects from remote"))
            {
                return(new Result($"Failed to complete regular clone: {fetchResult?.Errors}"));
            }

            GitProcess.Result checkoutResult = null;

            if (!this.ShowStatusWhileRunning(() =>
            {
                using (ITracer activity = this.tracer.StartActivity("git-checkout", EventLevel.LogAlways))
                {
                    checkoutResult = git.ForceCheckout(branch);
                    return(checkoutResult.ExitCodeIsSuccess);
                }
            },
                                             $"Checking out '{branch}'"))
            {
                return(new Result($"Failed to complete regular clone: {checkoutResult?.Errors}"));
            }
            return(new Result(true));
        }
Ejemplo n.º 12
0
        private void TestSetup(DateTime lastRun, bool failOnVerify = false)
        {
            string lastRunTime = EpochConverter.ToUnixEpochSeconds(lastRun).ToString();

            this.gitProcess = new MockGitProcess();

            // Create enlistment using git process
            ScalarEnlistment enlistment = new MockScalarEnlistment(this.gitProcess);

            // Create a last run time file
            MockFile timeFile = new MockFile(Path.Combine(enlistment.GitObjectsRoot, "info", PackfileMaintenanceStep.PackfileLastRunFileName), lastRunTime);

            // Create info directory to hold last run time file
            MockDirectory info = new MockDirectory(
                Path.Combine(enlistment.GitObjectsRoot, "info"),
                null,
                new List <MockFile>()
            {
                timeFile
            });

            // Create pack info
            MockDirectory pack = new MockDirectory(
                enlistment.GitPackRoot,
                null,
                new List <MockFile>()
            {
                new MockFile(Path.Combine(enlistment.GitPackRoot, "pack-1.pack"), "one"),
                new MockFile(Path.Combine(enlistment.GitPackRoot, "pack-1.idx"), "1"),
                new MockFile(Path.Combine(enlistment.GitPackRoot, "pack-2.pack"), "two"),
                new MockFile(Path.Combine(enlistment.GitPackRoot, "pack-2.idx"), "2"),
                new MockFile(Path.Combine(enlistment.GitPackRoot, "pack-3.pack"), "three"),
                new MockFile(Path.Combine(enlistment.GitPackRoot, "pack-3.idx"), "3"),
                new MockFile(Path.Combine(enlistment.GitPackRoot, KeepName), string.Empty),
                new MockFile(Path.Combine(enlistment.GitPackRoot, StaleIdxName), "4"),
            });

            // Create git objects directory
            MockDirectory gitObjectsRoot = new MockDirectory(enlistment.GitObjectsRoot, new List <MockDirectory>()
            {
                info, pack
            }, null);

            // Add object directory to file System
            List <MockDirectory> directories = new List <MockDirectory>()
            {
                gitObjectsRoot
            };
            PhysicalFileSystem fileSystem = new MockFileSystem(new MockDirectory(enlistment.EnlistmentRoot, directories, null));

            // Create and return Context
            this.tracer  = new MockTracer();
            this.context = new ScalarContext(this.tracer, fileSystem, enlistment);

            this.gitProcess.SetExpectedCommandResult(
                this.WriteCommand,
                () => new GitProcess.Result(string.Empty, string.Empty, GitProcess.Result.SuccessCode));
            this.gitProcess.SetExpectedCommandResult(
                this.ExpireCommand,
                () => new GitProcess.Result(string.Empty, string.Empty, GitProcess.Result.SuccessCode));
            this.gitProcess.SetExpectedCommandResult(
                this.VerifyCommand,
                () => new GitProcess.Result(string.Empty, string.Empty, failOnVerify ? GitProcess.Result.GenericFailureCode : GitProcess.Result.SuccessCode));
            this.gitProcess.SetExpectedCommandResult(
                this.RepackCommand,
                () => new GitProcess.Result(string.Empty, string.Empty, GitProcess.Result.SuccessCode));
        }
Ejemplo n.º 13
0
 public GitMaintenanceStep(ScalarContext context, bool requireObjectCacheLock, GitProcessChecker gitProcessChecker = null)
 {
     this.Context = context;
     this.RequireObjectCacheLock = requireObjectCacheLock;
     this.GitProcessChecker      = gitProcessChecker ?? new GitProcessChecker();
 }
Ejemplo n.º 14
0
        protected override void Execute(ScalarEnlistment enlistment)
        {
            using (JsonTracer tracer = new JsonTracer(ScalarConstants.ScalarEtwProviderName, RunVerbName))
            {
                string cacheServerUrl = CacheServerResolver.GetUrlFromConfig(enlistment);

                string logFileName = ScalarEnlistment.GetNewScalarLogFileName(
                    enlistment.ScalarLogsRoot,
                    ScalarConstants.LogFileTypes.Maintenance,
                    logId: this.StartedByService ? "service" : null);

                List <GitMaintenanceStep> steps = new List <GitMaintenanceStep>();

                tracer.AddLogFileEventListener(
                    logFileName,
                    EventLevel.Informational,
                    Keywords.Any);
                tracer.WriteStartEvent(
                    enlistment.EnlistmentRoot,
                    enlistment.RepoUrl,
                    cacheServerUrl,
                    this.AddVerbDataToMetadata(
                        new EventMetadata
                {
                    { nameof(this.MaintenanceTask), this.MaintenanceTask },
                    { nameof(this.PackfileMaintenanceBatchSize), this.PackfileMaintenanceBatchSize },
                    { nameof(this.EnlistmentRootPathParameter), this.EnlistmentRootPathParameter },
                    { nameof(this.StartedByService), this.StartedByService },
                }));

                this.InitializeCachePaths(tracer, enlistment);
                PhysicalFileSystem fileSystem = new PhysicalFileSystem();
                using (ScalarContext context = new ScalarContext(tracer, fileSystem, enlistment))
                {
                    try
                    {
                        GitObjectsHttpRequestor objectRequestor = null;
                        CacheServerInfo         cacheServer;
                        GitObjects gitObjects;

                        switch (this.MaintenanceTask)
                        {
                        case ScalarConstants.VerbParameters.Maintenance.AllTasksName:
                            steps.Add(new ConfigStep(context));
                            this.InitializeServerConnection(tracer, enlistment, cacheServerUrl, out objectRequestor, out cacheServer);
                            gitObjects = new GitObjects(tracer, enlistment, objectRequestor, fileSystem);
                            steps.Add(new FetchStep(context, gitObjects, requireCacheLock: false, forceRun: !this.StartedByService));
                            steps.Add(new CommitGraphStep(context, requireObjectCacheLock: false));
                            steps.Add(new LooseObjectsStep(context, forceRun: !this.StartedByService));
                            steps.Add(new PackfileMaintenanceStep(
                                          context,
                                          forceRun: !this.StartedByService,
                                          batchSize: string.IsNullOrWhiteSpace(this.PackfileMaintenanceBatchSize) ?
                                          PackfileMaintenanceStep.DefaultBatchSizeBytes.ToString() :
                                          this.PackfileMaintenanceBatchSize));
                            break;

                        case ScalarConstants.VerbParameters.Maintenance.LooseObjectsTaskName:
                            this.FailIfBatchSizeSet(tracer);
                            steps.Add(new LooseObjectsStep(context, forceRun: !this.StartedByService));
                            break;

                        case ScalarConstants.VerbParameters.Maintenance.PackFilesTaskName:
                            steps.Add(new PackfileMaintenanceStep(
                                          context,
                                          forceRun: !this.StartedByService,
                                          batchSize: string.IsNullOrWhiteSpace(this.PackfileMaintenanceBatchSize) ?
                                          PackfileMaintenanceStep.DefaultBatchSizeBytes.ToString() :
                                          this.PackfileMaintenanceBatchSize));
                            break;

                        case ScalarConstants.VerbParameters.Maintenance.FetchTaskName:
                            this.FailIfBatchSizeSet(tracer);
                            this.InitializeServerConnection(tracer, enlistment, cacheServerUrl, out objectRequestor, out cacheServer);
                            gitObjects = new GitObjects(tracer, enlistment, objectRequestor, fileSystem);
                            steps.Add(new FetchStep(context, gitObjects, requireCacheLock: false, forceRun: !this.StartedByService));
                            break;

                        case ScalarConstants.VerbParameters.Maintenance.CommitGraphTaskName:
                            this.FailIfBatchSizeSet(tracer);
                            steps.Add(new CommitGraphStep(context, requireObjectCacheLock: false));
                            break;

                        case ScalarConstants.VerbParameters.Maintenance.ConfigTaskName:
                            this.FailIfBatchSizeSet(tracer);
                            steps.Add(new ConfigStep(context));
                            break;

                        default:
                            this.ReportErrorAndExit($"Unknown maintenance task requested: '{this.MaintenanceTask}'");
                            break;
                        }

                        foreach (GitMaintenanceStep step in steps)
                        {
                            this.ShowStatusWhileRunning(() => { step.Execute(); return(true); }, step.ProgressMessage);
                        }
                    }
                    catch (VerbAbortedException)
                    {
                        throw;
                    }
                    catch (AggregateException aggregateException)
                    {
                        string error = $"AggregateException thrown while running '{this.MaintenanceTask}' task: {aggregateException.Message}";
                        tracer.RelatedError(this.CreateEventMetadata(aggregateException), error);
                        foreach (Exception innerException in aggregateException.Flatten().InnerExceptions)
                        {
                            tracer.RelatedError(
                                this.CreateEventMetadata(innerException),
                                $"Unhandled {innerException.GetType().Name}: {innerException.Message}");
                        }

                        this.ReportErrorAndExit(tracer, ReturnCode.GenericError, error);
                    }
                    catch (Exception e)
                    {
                        string error = $"Exception thrown while running '{this.MaintenanceTask}' task: {e.Message}";
                        tracer.RelatedError(this.CreateEventMetadata(e), error);
                        this.ReportErrorAndExit(tracer, ReturnCode.GenericError, error);
                    }
                }
            }
        }
Ejemplo n.º 15
0
 public CommitGraphStep(ScalarContext context, bool requireObjectCacheLock = true)
     : base(context, requireObjectCacheLock)
 {
 }
Ejemplo n.º 16
0
 public CheckMethodStep(ScalarContext context, WhenToStop when)
     : base(context, requireObjectCacheLock: true)
 {
     this.when = when;
 }