-
-
Couldn't load subscription status.
- Fork 235
feat(build): preserve repository name case for build upload #2777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
ad1dc4c
ffd38bb
6f24dd7
6e4c6d7
d0b5024
39346bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -108,6 +108,10 @@ fn strip_git_suffix(s: &str) -> &str { | |
|
|
||
| impl VcsUrl { | ||
| pub fn parse(url: &str) -> VcsUrl { | ||
| Self::parse_preserve_case(url).into_lowercase() | ||
| } | ||
|
|
||
| pub fn parse_preserve_case(url: &str) -> VcsUrl { | ||
| lazy_static! { | ||
| static ref GIT_URL_RE: Regex = | ||
| Regex::new(r"^(?:(?:git\+)?(?:git|ssh|https?))://(?:[^@]+@)?([^/]+)/(.+)$") | ||
|
|
@@ -129,6 +133,13 @@ impl VcsUrl { | |
| } | ||
| } | ||
|
|
||
| fn into_lowercase(self) -> VcsUrl { | ||
| VcsUrl { | ||
| provider: self.provider, | ||
| id: self.id.to_lowercase(), | ||
| } | ||
| } | ||
runningcode marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| fn from_git_parts(host: &str, path: &str) -> VcsUrl { | ||
| // Azure Devops has multiple domains and multiple URL styles for the | ||
| // various different API versions. | ||
|
|
@@ -157,13 +168,13 @@ impl VcsUrl { | |
| if let Some(caps) = VS_GIT_PATH_RE.captures(path) { | ||
| return VcsUrl { | ||
| provider: host.to_lowercase(), | ||
| id: format!("{}/{}", username.to_lowercase(), &caps[1].to_lowercase()), | ||
| id: format!("{username}/{}", &caps[1]), | ||
| }; | ||
| } | ||
| if let Some(caps) = VS_TRAILING_GIT_PATH_RE.captures(path) { | ||
| return VcsUrl { | ||
| provider: host.to_lowercase(), | ||
| id: caps[1].to_lowercase(), | ||
| id: caps[1].to_string(), | ||
| }; | ||
| } | ||
| } | ||
|
|
@@ -173,13 +184,13 @@ impl VcsUrl { | |
| if let Some(caps) = AZUREDEV_VERSION_PATH_RE.captures(path) { | ||
| return VcsUrl { | ||
| provider: hostname.into(), | ||
| id: format!("{}/{}", &caps[1].to_lowercase(), &caps[2].to_lowercase()), | ||
| id: format!("{}/{}", &caps[1], &caps[2]), | ||
| }; | ||
| } | ||
| if let Some(caps) = VS_TRAILING_GIT_PATH_RE.captures(path) { | ||
| return VcsUrl { | ||
| provider: hostname.to_lowercase(), | ||
| id: caps[1].to_lowercase(), | ||
| id: caps[1].to_string(), | ||
| }; | ||
| } | ||
| } | ||
|
|
@@ -196,13 +207,13 @@ impl VcsUrl { | |
| if let Some(caps) = BITBUCKET_SERVER_PATH_RE.captures(path) { | ||
| return VcsUrl { | ||
| provider: host.to_lowercase(), | ||
| id: format!("{}/{}", &caps[1].to_lowercase(), &caps[2].to_lowercase()), | ||
| id: format!("{}/{}", &caps[1], &caps[2]), | ||
| }; | ||
| } | ||
|
|
||
| VcsUrl { | ||
| provider: host.to_lowercase(), | ||
| id: strip_git_suffix(path).to_lowercase(), | ||
| id: strip_git_suffix(path).to_owned(), | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -221,6 +232,13 @@ pub fn get_repo_from_remote(repo: &str) -> String { | |
| obj.id | ||
| } | ||
|
|
||
| /// Like get_repo_from_remote but preserves the original case of the repository name. | ||
| /// This is used specifically for build upload where case preservation is important. | ||
| pub fn get_repo_from_remote_preserve_case(repo: &str) -> String { | ||
| let obj = VcsUrl::parse_preserve_case(repo); | ||
| obj.id | ||
| } | ||
|
|
||
| pub fn get_provider_from_remote(remote: &str) -> String { | ||
| let obj = VcsUrl::parse(remote); | ||
| extract_provider_name(&obj.provider).to_owned() | ||
|
|
@@ -288,10 +306,9 @@ fn find_merge_base_ref( | |
| Ok(merge_base_sha) | ||
| } | ||
|
|
||
| /// Attempts to get the base repository name from git remotes. | ||
| /// Prefers "upstream" remote if it exists, then "origin", otherwise uses the first available remote. | ||
| /// Returns the base repository name if a remote is found. | ||
| pub fn git_repo_base_repo_name(repo: &git2::Repository) -> Result<Option<String>> { | ||
| /// Like git_repo_base_repo_name but preserves the original case of the repository name. | ||
| /// This is used specifically for build upload where case preservation is important. | ||
| pub fn git_repo_base_repo_name_preserve_case(repo: &git2::Repository) -> Result<Option<String>> { | ||
| let remotes = repo.remotes()?; | ||
| let remote_names: Vec<&str> = remotes.iter().flatten().collect(); | ||
|
|
||
|
|
@@ -312,7 +329,8 @@ pub fn git_repo_base_repo_name(repo: &git2::Repository) -> Result<Option<String> | |
| match git_repo_remote_url(repo, chosen_remote) { | ||
| Ok(remote_url) => { | ||
| debug!("Found remote '{}': {}", chosen_remote, remote_url); | ||
| Ok(Some(get_repo_from_remote(&remote_url))) | ||
| let repo_name = get_repo_from_remote_preserve_case(&remote_url); | ||
| Ok(Some(repo_name)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Git Function Renamed, Case Sensitivity ChangedThe |
||
| } | ||
| Err(e) => { | ||
| warn!("Could not get URL for remote '{}': {}", chosen_remote, e); | ||
|
|
@@ -942,6 +960,43 @@ mod tests { | |
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_get_repo_from_remote_preserve_case() { | ||
| // Test that case-preserving function maintains original casing | ||
| assert_eq!( | ||
| get_repo_from_remote_preserve_case("https://github.com/MyOrg/MyRepo"), | ||
| "MyOrg/MyRepo" | ||
| ); | ||
| assert_eq!( | ||
| get_repo_from_remote_preserve_case("[email protected]:SentryOrg/SentryRepo.git"), | ||
| "SentryOrg/SentryRepo" | ||
| ); | ||
| assert_eq!( | ||
| get_repo_from_remote_preserve_case("https://gitlab.com/MyCompany/MyProject"), | ||
| "MyCompany/MyProject" | ||
| ); | ||
| assert_eq!( | ||
| get_repo_from_remote_preserve_case("[email protected]:TeamName/ProjectName.git"), | ||
| "TeamName/ProjectName" | ||
| ); | ||
| assert_eq!( | ||
| get_repo_from_remote_preserve_case("ssh://[email protected]/MyUser/MyRepo.git"), | ||
| "MyUser/MyRepo" | ||
| ); | ||
|
|
||
| // Test that regular function still lowercases | ||
| assert_eq!( | ||
| get_repo_from_remote("https://github.com/MyOrg/MyRepo"), | ||
| "myorg/myrepo" | ||
| ); | ||
|
|
||
| // Test edge cases - should fall back to lowercase when regex doesn't match | ||
| assert_eq!( | ||
| get_repo_from_remote_preserve_case("invalid-url"), | ||
| get_repo_from_remote("invalid-url") | ||
| ); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_extract_provider_name() { | ||
| // Test basic provider name extraction | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had these two clippy warning with function you suggested so I adjusted it to what I have in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, if clippy complained, then this is the right thing to do!