예제 #1
0
        private JsonTracer CreateTracer(GVFSEnlistment enlistment, EventLevel verbosity, Keywords keywords)
        {
            string enlistmentId = null;
            string mountId      = null;

            GitProcess git = new GitProcess(enlistment);

            GitProcess.ConfigResult configResult = git.GetFromLocalConfig(GVFSConstants.GitConfig.EnlistmentId);
            if (configResult.TryParseAsString(out enlistmentId, out string _, defaultValue: string.Empty))
            {
                enlistmentId = enlistmentId.Trim();
            }

            configResult = git.GetFromLocalConfig(GVFSConstants.GitConfig.MountId);
            if (configResult.TryParseAsString(out mountId, out string _, defaultValue: string.Empty))
            {
                mountId = mountId.Trim();
            }

            JsonTracer tracer = new JsonTracer(GVFSConstants.GVFSEtwProviderName, "GVFSMount", enlistmentId: enlistmentId, mountId: mountId);

            tracer.AddLogFileEventListener(
                GVFSEnlistment.GetNewGVFSLogFileName(enlistment.GVFSLogsRoot, GVFSConstants.LogFileTypes.MountProcess),
                verbosity,
                keywords);
            if (this.ShowDebugWindow)
            {
                tracer.AddDiagnosticConsoleEventListener(verbosity, keywords);
            }

            return(tracer);
        }
예제 #2
0
        private void GetLocalCachePaths(ScalarEnlistment enlistment, out string localCacheRoot, out string gitObjectsRoot)
        {
            localCacheRoot = null;
            gitObjectsRoot = null;

            try
            {
                using (ITracer tracer = new JsonTracer(ScalarConstants.ScalarEtwProviderName, "DiagnoseVerb"))
                {
                    string     error;
                    GitProcess process             = new GitProcess(enlistment);
                    GitProcess.ConfigResult result = process.GetFromLocalConfig(ScalarConstants.GitConfig.ObjectCache);
                    if (!result.TryParseAsString(out gitObjectsRoot, out error))
                    {
                        this.WriteMessage("Failed to determine local cache path and git objects root: " + error);
                    }

                    localCacheRoot = Path.GetDirectoryName(gitObjectsRoot);
                }
            }
            catch (Exception e)
            {
                this.WriteMessage(string.Format("Failed to determine local cache path and git objects root, Exception: {0}", e));
            }
        }
예제 #3
0
            protected void InitializeCachePaths(
                ITracer tracer,
                ScalarEnlistment enlistment)
            {
                string     error;
                string     gitObjectsRoot;
                GitProcess process = new GitProcess(enlistment);

                GitProcess.ConfigResult result = process.GetFromLocalConfig(ScalarConstants.GitConfig.ObjectCache);
                if (!result.TryParseAsString(out gitObjectsRoot, out error))
                {
                    this.ReportErrorAndExit("Failed to determine git objects root from git config: " + error);
                }

                string localCacheRoot;

                if (string.IsNullOrWhiteSpace(gitObjectsRoot))
                {
                    // We do not have an object cache. This is a vanilla Git repo!
                    localCacheRoot = enlistment.LocalObjectsRoot;
                    gitObjectsRoot = enlistment.LocalObjectsRoot;
                }
                else
                {
                    localCacheRoot = Path.GetDirectoryName(gitObjectsRoot);
                }

                if (string.IsNullOrWhiteSpace(localCacheRoot))
                {
                    this.ReportErrorAndExit(tracer, "Invalid local cache path (empty or whitespace)");
                }

                enlistment.InitializeCachePaths(localCacheRoot, gitObjectsRoot);
            }
예제 #4
0
 private string GetId(string key)
 {
     GitProcess.ConfigResult configResult = this.CreateGitProcess().GetFromLocalConfig(key);
     string value;
     string error;
     configResult.TryParseAsString(out value, out error, defaultValue: string.Empty);
     return value.Trim();
 }
예제 #5
0
        public void ConfigResult_TryParseAsString_FailsWhenErrors()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result(string.Empty, "errors", 1),
                "settingName");

            result.TryParseAsString(out string expectedValue, out string _).ShouldBeFalse();
        }
예제 #6
0
        public void ConfigResult_TryParseAsInt_FailsWithErrors()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result(string.Empty, "errors", 1),
                "settingName");

            result.TryParseAsInt(0, -1, out int value, out string error).ShouldBeFalse();
        }
예제 #7
0
        public void ConfigResult_TryParseAsInt_ParsesWhenWarnings()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result("32", "warning: ignored", 0),
                "settingName");

            result.TryParseAsInt(1, -1, out int value, out string error).ShouldBeTrue();
            value.ShouldEqual(32);
        }
예제 #8
0
        public void ConfigResult_TryParseAsString_OverridesDefaultOnSuccess()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result("expected", string.Empty, 0),
                "settingName");

            result.TryParseAsString(out string expectedValue, out string _, "default").ShouldBeTrue();
            expectedValue.ShouldEqual("expected");
        }
예제 #9
0
        public void ConfigResult_TryParseAsString_RespectsDefaultOnFailure()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result(string.Empty, string.Empty, 1),
                "settingName");

            result.TryParseAsString(out string expectedValue, out string _, "default").ShouldBeTrue();
            expectedValue.ShouldEqual("default");
        }
예제 #10
0
        public void ConfigResult_TryParseAsString_PassesThroughErrors()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result(string.Empty, "--local can only be used inside a git repository", 1),
                "settingName");

            result.TryParseAsString(out string expectedValue, out string error).ShouldBeFalse();
            error.Contains("--local").ShouldBeTrue();
        }
예제 #11
0
        public void ConfigResult_TryParseAsString_NullWhenUnsetAndWarnings()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result(string.Empty, "warning: ignored", 1),
                "settingName");

            result.TryParseAsString(out string expectedValue, out string _).ShouldBeTrue();
            expectedValue.ShouldBeNull();
        }
예제 #12
0
        public void ConfigResult_TryParseAsString_DefaultIsNull()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result(string.Empty, string.Empty, 1),
                "settingName");

            result.TryParseAsString(out string expectedValue, out string _).ShouldBeTrue();
            expectedValue.ShouldBeNull();
        }
예제 #13
0
        public void ConfigResult_TryParseAsInt_ParsesWhenOutputIncludesWhitespace()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result("\n\t 32\t\r\n", "warning: ignored", 0),
                "settingName");

            result.TryParseAsInt(1, -1, out int value, out string error).ShouldBeTrue();
            value.ShouldEqual(32);
        }
예제 #14
0
        public void ConfigResult_TryParseAsInt_ParsesWhenNoError()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result("32", string.Empty, 0),
                "settingName");

            result.TryParseAsInt(1, -1, out int value, out string error).ShouldBeTrue();
            value.ShouldEqual(32);
        }
예제 #15
0
        public void ConfigResult_TryParseAsInt_DefaultWhenUnset()
        {
            GitProcess.ConfigResult result = new GitProcess.ConfigResult(
                new GitProcess.Result(string.Empty, string.Empty, 1),
                "settingName");

            result.TryParseAsInt(1, -1, out int value, out string error).ShouldBeTrue();
            value.ShouldEqual(1);
        }
예제 #16
0
        public override IssueType HasIssue(List <string> messages)
        {
            GitProcess git = new GitProcess(this.Enlistment);

            GitProcess.ConfigResult originResult = git.GetOriginUrl();
            string error;
            string originUrl;

            if (!originResult.TryParseAsString(out originUrl, out error))
            {
                if (error.Contains("--local"))
                {
                    // example error: '--local can only be used inside a git repository'
                    // Corrupting the git config does not cause git to not recognize the current folder as "not a git repository".
                    // This is a symptom of deeper issues such as missing HEAD file or refs folders.
                    messages.Add("An issue was found that may be a side-effect of other issues. Fix them with 'gvfs repair --confirm' then 'gvfs repair' again.");
                    return(IssueType.CantFix);
                }

                messages.Add("Could not read origin url: " + error);
                return(IssueType.Fixable);
            }

            if (originUrl == null)
            {
                messages.Add("Remote 'origin' is not configured for this repo. You can fix this by running 'git remote add origin <repourl>'");
                return(IssueType.CantFix);
            }

            // We've validated the repo URL, so now make sure we can authenticate
            try
            {
                GVFSEnlistment enlistment = GVFSEnlistment.CreateFromDirectory(
                    this.Enlistment.EnlistmentRoot,
                    this.Enlistment.GitBinPath,
                    this.Enlistment.GVFSHooksRoot,
                    authentication: null);

                string authError;
                if (!enlistment.Authentication.TryInitialize(this.Tracer, enlistment, out authError))
                {
                    messages.Add("Authentication failed. Run 'gvfs log' for more info.");
                    messages.Add(".git\\config is valid and remote 'origin' is set, but may have a typo:");
                    messages.Add(originUrl.Trim());
                    return(IssueType.CantFix);
                }
            }
            catch (InvalidRepoException)
            {
                messages.Add("An issue was found that may be a side-effect of other issues. Fix them with 'gvfs repair --confirm' then 'gvfs repair' again.");
                return(IssueType.CantFix);
            }

            return(IssueType.None);
        }
예제 #17
0
        protected Enlistment(
            string enlistmentRoot,
            string workingDirectoryRoot,
            string repoUrl,
            string gitBinPath,
            bool flushFileBuffersForPacks,
            GitAuthentication authentication)
        {
            if (string.IsNullOrWhiteSpace(gitBinPath))
            {
                throw new ArgumentException("Path to git.exe must be set");
            }

            this.EnlistmentRoot           = enlistmentRoot;
            this.WorkingDirectoryRoot     = workingDirectoryRoot;
            this.DotGitRoot               = Path.Combine(this.WorkingDirectoryRoot, ScalarConstants.DotGit.Root);
            this.GitBinPath               = gitBinPath;
            this.FlushFileBuffersForPacks = flushFileBuffersForPacks;

            GitProcess gitProcess = new GitProcess(this);

            if (repoUrl != null)
            {
                this.RepoUrl = repoUrl;
            }
            else
            {
                GitProcess.ConfigResult originResult = gitProcess.GetOriginUrl();
                if (!originResult.TryParseAsString(out string originUrl, out string error))
                {
                    if (!gitProcess.TryGetRemotes(out string[] remotes, out error))
                    {
                        throw new InvalidRepoException(this.WorkingDirectoryRoot, $"Failed to load remotes with error: {error}");
                    }

                    if (remotes.Length > 0)
                    {
                        GitProcess.ConfigResult remoteResult = gitProcess.GetFromLocalConfig($"remote.{remotes[0]}.url");
                        if (!remoteResult.TryParseAsString(out originUrl, out error))
                        {
                            originUrl = null;
                        }
                    }
                }

                this.RepoUrl = originUrl?.Trim() ?? string.Empty;
            }

            this.Authentication = authentication ?? new GitAuthentication(gitProcess, this.RepoUrl, this.WorkingDirectoryRoot);
        }
예제 #18
0
        private static string GetValueFromConfig(GitProcess git, string configName, bool localOnly)
        {
            GitProcess.ConfigResult result =
                localOnly
                ? git.GetFromLocalConfig(configName)
                : git.GetFromConfig(configName);

            if (!result.TryParseAsString(out string value, out string error))
            {
                throw new InvalidRepoException(error);
            }

            return(value);
        }
예제 #19
0
        private static string GetConfigValue(string gitBinRoot, string configKey)
        {
            string value = string.Empty;
            string error;

            GitProcess.ConfigResult result = GitProcess.GetFromSystemConfig(gitBinRoot, configKey);
            if (!result.TryParseAsString(out value, out error, defaultValue: string.Empty) || string.IsNullOrWhiteSpace(value))
            {
                result = GitProcess.GetFromGlobalConfig(gitBinRoot, configKey);
                result.TryParseAsString(out value, out error, defaultValue: string.Empty);
            }

            return(value.TrimEnd('\r', '\n'));
        }
예제 #20
0
        protected Enlistment(
            string enlistmentRoot,
            string workingDirectoryRoot,
            string localStorageRoot,
            string repoUrl,
            string gitBinPath,
            string gvfsHooksRoot,
            bool flushFileBuffersForPacks,
            GitAuthentication authentication)
        {
            if (string.IsNullOrWhiteSpace(gitBinPath))
            {
                throw new ArgumentException("Path to git.exe must be set");
            }

            this.EnlistmentRoot              = enlistmentRoot;
            this.WorkingDirectoryRoot        = workingDirectoryRoot;
            this.WorkingDirectoryBackingRoot = localStorageRoot;
            this.DotGitRoot               = Path.Combine(this.WorkingDirectoryBackingRoot, GVFSConstants.DotGit.Root);
            this.GitBinPath               = gitBinPath;
            this.GVFSHooksRoot            = gvfsHooksRoot;
            this.FlushFileBuffersForPacks = flushFileBuffersForPacks;

            GitProcess gitProcess = new GitProcess(this);

            if (repoUrl != null)
            {
                this.RepoUrl = repoUrl;
            }
            else
            {
                GitProcess.ConfigResult originResult = gitProcess.GetOriginUrl();
                if (!originResult.TryParseAsString(out string originUrl, out string error))
                {
                    throw new InvalidRepoException("Could not get origin url. git error: " + error);
                }

                if (originUrl == null)
                {
                    throw new InvalidRepoException("Could not get origin url. remote 'origin' is not configured for this repo.'");
                }

                this.RepoUrl = originUrl.Trim();
            }

            this.Authentication = authentication ?? new GitAuthentication(gitProcess, this.RepoUrl);
        }
예제 #21
0
        private bool GetIsIndexSigningOff()
        {
            // The first bit of core.gvfs is set if index signing is turned off.
            const uint CoreGvfsUnsignedIndexFlag = 1;

            GitProcess git = new GitProcess(this.Enlistment);

            GitProcess.ConfigResult configCoreGvfs = git.GetFromConfig("core.gvfs");
            string coreGvfs;
            string error;

            if (!configCoreGvfs.TryParseAsString(out coreGvfs, out error))
            {
                return(false);
            }

            uint valueCoreGvfs;

            // No errors getting the configuration and it is either "true" or numeric with the right bit set.
            return(!string.IsNullOrEmpty(coreGvfs) &&
                   (coreGvfs.Equals("true", StringComparison.OrdinalIgnoreCase) ||
                    (uint.TryParse(coreGvfs, out valueCoreGvfs) &&
                     ((valueCoreGvfs & CoreGvfsUnsignedIndexFlag) == CoreGvfsUnsignedIndexFlag))));
        }
 private static bool TryGetFromGitConfig(GitProcess git, string configName, int defaultValue, int minValue, out int value, out string error)
 {
     GitProcess.ConfigResult result = git.GetFromConfig(configName);
     return(result.TryParseAsInt(defaultValue, minValue, out value, out error));
 }