public static bool TryParse(string resourceId, out AzureDevOpsIdentifier azureDevOpsIdentifier) { azureDevOpsIdentifier = null; if (string.IsNullOrWhiteSpace(resourceId)) { return(false); } foreach (var expression in new Regex[] { ResourceExpression, ProjectExpression }) { var match = expression.Match(SanitizeResourceId(resourceId, out var _)); if (match.Success) { azureDevOpsIdentifier = expression switch { Regex exp when(expression == ProjectExpression) => new AzureDevOpsIdentifier() { Organization = match.Groups[1].Value, Project = match.Groups[2].Value }, Regex exp when(expression == ResourceExpression) => new AzureDevOpsIdentifier() { Organization = match.Groups[1].Value, Project = match.Groups[2].Value, ResourcePath = match.Groups[3].Value }, _ => default }; } if (azureDevOpsIdentifier is not null) { break; } } return(azureDevOpsIdentifier is not null); }
public static AzureDevOpsIdentifier FromUrl(string url) { if (string.IsNullOrWhiteSpace(url)) { throw new ArgumentException($"'{nameof(url)}' cannot be null or whitespace.", nameof(url)); } if (!Uri.TryCreate(url, UriKind.Absolute, out var urlParsed)) { throw new ArgumentException($"{nameof(url)} must be an absolute URL.", nameof(url)); } var segments = urlParsed.Segments .Select(s => s.Trim('/')) .Where(s => !string.IsNullOrWhiteSpace(s)) .Select(s => HttpUtility.UrlDecode(s)); if (!IsServiceHostname(urlParsed.Host)) { segments = segments .SkipWhile(s => !s.Equals("tfs", StringComparison.OrdinalIgnoreCase)); } var coreSegments = segments .TakeWhile(s => !s.Equals("_apis", StringComparison.OrdinalIgnoreCase)); var areaSegments = segments .SkipWhile(s => !s.Equals("_apis", StringComparison.OrdinalIgnoreCase)) .Skip(1); // skip one item to get rid of _apis in enumeration AzureDevOpsIdentifier identifier; if (IsServiceHostname(urlParsed.Host)) { if (urlParsed.Host.Equals(DEFAULT_HOSTNAME, StringComparison.OrdinalIgnoreCase)) { identifier = new AzureDevOpsIdentifier() { Organization = coreSegments.ElementAtOrDefault(0), Project = coreSegments.ElementAtOrDefault(1) }; } else { identifier = new AzureDevOpsIdentifier() { Organization = urlParsed.Host.Substring(0, urlParsed.Host.IndexOf(".", StringComparison.OrdinalIgnoreCase)), Project = coreSegments.ElementAtOrDefault(1) }; } } else { identifier = new AzureDevOpsIdentifier() { Organization = coreSegments.ElementAtOrDefault(0), Project = coreSegments.ElementAtOrDefault(1) }; } if (PROJECTS_SEGMENT.Equals(areaSegments.FirstOrDefault(), StringComparison.OrdinalIgnoreCase)) { identifier.Project ??= areaSegments.Skip(1).FirstOrDefault(); identifier.ResourcePath = string.Join('/', areaSegments.Skip(2)); } else { identifier.ResourcePath = string.Join('/', areaSegments.Skip(1)); } return(identifier); }