예제 #1
0
            private bool IsIncludePath(GitVariableName key, string configFilePath)
            {
                // unconditional:
                if (key.Equals(new GitVariableName("include", "", "path")))
                {
                    return(true);
                }

                // conditional:
                if (GitVariableName.SectionNameComparer.Equals(key.SectionName, "includeIf") &&
                    GitVariableName.VariableNameComparer.Equals(key.VariableName, "path") &&
                    key.SubsectionName != "")
                {
                    bool   ignoreCase;
                    string pattern;

                    const string caseSensitiveGitDirPrefix   = "gitdir:";
                    const string caseInsensitiveGitDirPrefix = "gitdir/i:";

                    if (key.SubsectionName.StartsWith(caseSensitiveGitDirPrefix, StringComparison.Ordinal))
                    {
                        pattern    = key.SubsectionName.Substring(caseSensitiveGitDirPrefix.Length);
                        ignoreCase = false;
                    }
                    else if (key.SubsectionName.StartsWith(caseInsensitiveGitDirPrefix, StringComparison.Ordinal))
                    {
                        pattern    = key.SubsectionName.Substring(caseInsensitiveGitDirPrefix.Length);
                        ignoreCase = true;
                    }
                    else
                    {
                        return(false);
                    }

                    if (pattern.Length >= 2 && pattern[0] == '.' && pattern[1] == '/')
                    {
                        // leading './' is substituted with the path to the directory containing the current config file.
                        pattern = PathUtils.CombinePosixPaths(PathUtils.ToPosixPath(Path.GetDirectoryName(configFilePath) !), pattern.Substring(2));
                    }
                    else if (pattern.Length >= 2 && pattern[0] == '~' && pattern[1] == '/')
                    {
                        // leading '~/' is substituted with HOME path
                        pattern = PathUtils.CombinePosixPaths(PathUtils.ToPosixPath(_environment.GetHomeDirectoryForPathExpansion(pattern)), pattern.Substring(2));
                    }
                    else if (!PathUtils.IsAbsolute(pattern))
                    {
                        pattern = "**/" + pattern;
                    }

                    if (pattern[pattern.Length - 1] == '/')
                    {
                        pattern += "**";
                    }

                    return(Glob.IsMatch(pattern, _gitDirectoryPosix, ignoreCase, matchWildCardWithDirectorySeparator: true));
                }

                return(false);
            }
예제 #2
0
            /// <exception cref="InvalidDataException"/>
            private string NormalizeRelativePath(string relativePath, string basePath, GitVariableName key)
            {
                string root;

                if (relativePath.Length >= 2 && relativePath[0] == '~' && PathUtils.IsDirectorySeparator(relativePath[1]))
                {
                    root         = _environment.GetHomeDirectoryForPathExpansion(relativePath);
                    relativePath = relativePath.Substring(2);
                }
                else
                {
                    root = Path.GetDirectoryName(basePath) ?? "";
                }

                try
                {
                    return(Path.GetFullPath(Path.Combine(root, relativePath)));
                }
                catch
                {
                    throw new InvalidDataException(string.Format(Resources.ValueOfIsNotValidPath, key.ToString(), relativePath));
                }
            }
예제 #3
0
            /// <exception cref="IOException"/>
            /// <exception cref="InvalidDataException"/>
            internal void LoadVariablesFrom(string path, Dictionary <GitVariableName, List <string> > variables, int includeDepth)
            {
                // https://git-scm.com/docs/git-config#_syntax

                // The following is allowed:
                //   [section][section]var = x
                //   [section]#[section]

                if (includeDepth > MaxIncludeDepth)
                {
                    throw new InvalidDataException(string.Format(Resources.ConfigurationFileRecursionExceededMaximumAllowedDepth, MaxIncludeDepth));
                }

                TextReader reader;

                try
                {
                    reader = _fileOpener(path);
                }
                catch (Exception e) when(e is FileNotFoundException || e is DirectoryNotFoundException)
                {
                    return;
                }
                catch (Exception e) when(!(e is IOException))
                {
                    throw new IOException(e.Message, e);
                }

                using (reader)
                {
                    string sectionName    = "";
                    string subsectionName = "";

                    while (true)
                    {
                        SkipMultilineWhitespace(reader);

                        int c = reader.Peek();
                        if (c == -1)
                        {
                            break;
                        }

                        // Comment to the end of the line:
                        if (IsCommentStart(c))
                        {
                            ReadToLineEnd(reader);
                            continue;
                        }

                        if (c == '[')
                        {
                            ReadSectionHeader(reader, _reusableBuffer, out sectionName, out subsectionName);
                            continue;
                        }

                        ReadVariableDeclaration(reader, _reusableBuffer, out var variableName, out var variableValue);

                        // Variable declared outside of a section is allowed (has no section name prefix).

                        var key = new GitVariableName(sectionName, subsectionName, variableName);
                        if (!variables.TryGetValue(key, out var values))
                        {
                            variables.Add(key, values = new List <string>());
                        }

                        values.Add(variableValue);

                        // Spec https://git-scm.com/docs/git-config#_includes:
                        if (IsIncludePath(key, path))
                        {
                            string includedConfigPath = NormalizeRelativePath(relativePath: variableValue, basePath: path, key);
                            LoadVariablesFrom(includedConfigPath, variables, includeDepth + 1);
                        }
                    }
                }
            }