Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Konrad Jamrozik committed Jan 7, 2023
1 parent 5d55bb5 commit 86ed4fe
Showing 1 changed file with 51 additions and 32 deletions.
83 changes: 51 additions & 32 deletions tools/code-owners-parser/CodeOwnersParser/MatchedCodeOwnerEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,9 @@ internal class MatchedCodeOwnerEntry
public readonly CodeOwnerEntry Value;

/// <summary>
/// The entry is valid if it obeys following conditions:
/// - The Value was obtained with a call to Azure.Sdk.Tools.CodeOwnersParser.CodeOwnersFile.ParseContent().
/// - As a consequence, in the case of no match, the entry is not valid.
/// - the Value.PathExpression starts with "/".
///
/// Once the validation described in the following issue is implemented:
/// https://github.com/Azure/azure-sdk-tools/issues/4859
/// To be valid, the entry will also have to obey following conditions:
/// - if the Value.PathExpression ends with "/", at least one corresponding
/// directory exists in the repository
/// - if the Value.PathExpression does not end with "/", at least one corresponding
/// file exists in the repository.
/// See comment on IsCodeOwnersPathValid
/// </summary>
public bool IsValid => this.Value.PathExpression.StartsWith("/");
public bool IsValid => IsCodeOwnersPathValid(this.Value.PathExpression);

/// <summary>
/// Any CODEOWNERS path with these characters will be skipped.
Expand Down Expand Up @@ -132,12 +121,7 @@ private static string NormalizeTargetPath(string targetPath, string codeownersPa

private static Regex ConvertToRegex(string codeownersPath)
{
// CODEOWNERS paths that do not start with "/" are relative and considered invalid.
// However, here we handle such cases to accomodate for parsing CODEOWNERS file
// paths that somehow slipped through validation. We do so by instead treating
// such paths as if they were absolute to repository root, i.e. starting with "/".
if (!codeownersPath.StartsWith("/"))
codeownersPath = "/" + codeownersPath;
codeownersPath = ConvertPathIfInvalid(codeownersPath);

string pattern = codeownersPath;

Expand All @@ -148,29 +132,64 @@ private static Regex ConvertToRegex(string codeownersPath)

pattern = Regex.Escape(pattern);

// Denote that all paths are absolute by prepending "beginning of string" symbol.
pattern = AddStringAnchors(pattern);

// Note that the "/**/" case is implicitly covered by "**/".
pattern = pattern.Replace("_DOUBLE_STAR_/", "(.*)");
// This case is necessary to cover suffix case, e.g. "/foo/bar/**".
pattern = pattern.Replace("/_DOUBLE_STAR_", "(.*)");
// This case is necessary to cover inline **, e.g. "/a**b/".
pattern = pattern.Replace("_DOUBLE_STAR_", "(.*)");
pattern = pattern.Replace("_SINGLE_STAR_", "([^/]*)");
return new Regex(pattern);
}

private static string ConvertPathIfInvalid(string codeownersPath)
{
// CODEOWNERS paths that do not start with "/" are relative and considered invalid.
// However, here we handle such cases to accomodate for parsing CODEOWNERS file
// paths that somehow slipped through validation. We do so by instead treating
// such paths as if they were absolute to repository root, i.e. starting with "/".
if (!IsCodeOwnersPathValid(codeownersPath))
codeownersPath = "/" + codeownersPath;
return codeownersPath;
}

private static string AddStringAnchors(string pattern)
{
// Denote that all paths are absolute by pre-pending "beginning of string" symbol.
pattern = "^" + pattern;

// Lack of slash at the end denotes the path is a path to a file,
// per our validation logic.
// Note we assume this is the case even if the path is invalid,
// even though in such case it might not necessarily be true.
if (!(pattern.EndsWith("/")
|| pattern.EndsWith("_DOUBLE_STAR_")))
// Note we assume this is path to a file even if the path is invalid,
// even though in such case the path might be a path to a directory.
if (!pattern.EndsWith("/"))
{
// Append "end of string", symbol, denoting the match has to be exact,
// not a substring, as we are dealing with a file.
pattern += "$";
}

// Note that the "/**/" case is implicitly covered by "**/".
pattern = pattern.Replace("_DOUBLE_STAR_/", "(.*)");
// This case is necessary to cover suffix case, e.g. "/foo/bar/**".
pattern = pattern.Replace("/_DOUBLE_STAR_", "(.*)");
// This case is necessary to cover inline **, e.g. "/a**b/".
pattern = pattern.Replace("_DOUBLE_STAR_", "(.*)");
pattern = pattern.Replace("_SINGLE_STAR_", "([^/]*)");
return new Regex(pattern);
return pattern;
}

/// <summary>
/// The entry is valid if it obeys following conditions:
/// - The Value was obtained with a call to
/// Azure.Sdk.Tools.CodeOwnersParser.CodeOwnersFile.ParseContent().
/// - As a consequence, in the case of no match, the entry is not valid.
/// - the Value.PathExpression starts with "/".
///
/// Once the validation described in the following issue is implemented:
/// https://github.com/Azure/azure-sdk-tools/issues/4859
/// To be valid, the entry will also have to obey following conditions:
/// - if the Value.PathExpression ends with "/", at least one corresponding
/// directory exists in the repository
/// - if the Value.PathExpression does not end with "/", at least one corresponding
/// file exists in the repository.
/// </summary>
private static bool IsCodeOwnersPathValid(string codeownersPath)
=> codeownersPath.StartsWith("/");
}
}

0 comments on commit 86ed4fe

Please sign in to comment.