@@ -221,6 +221,32 @@ pub fn get_repo_from_remote(repo: &str) -> String {
221221 obj. id
222222}
223223
224+ /// Like get_repo_from_remote but preserves the original case of the repository name.
225+ /// This is used specifically for build upload where case preservation is important.
226+ pub fn get_repo_from_remote_preserve_case ( repo : & str ) -> String {
227+ // First get the lowercase version to ensure we handle all the complex VCS URL patterns correctly
228+ let lowercase_result = get_repo_from_remote ( repo) ;
229+
230+ // Then try to extract the case-preserved repository path using simple regex patterns
231+ lazy_static ! {
232+ // Matches most common Git URL patterns to extract the repository path
233+ static ref REPO_PATH_RE : Regex = Regex :: new(
234+ r"(?:https?://[^/]+/|git@[^:/]+[:/]|ssh://(?:[^@]+@)?[^/]+/)(.+?)(?:\.git)?/?$"
235+ ) . unwrap( ) ;
236+ }
237+
238+ if let Some ( caps) = REPO_PATH_RE . captures ( repo) {
239+ let case_preserved_path = & caps[ 1 ] ;
240+ // Use the case-preserved version if it looks like a valid repo path (contains '/')
241+ if case_preserved_path. contains ( '/' ) && case_preserved_path. len ( ) > 1 {
242+ return case_preserved_path. to_string ( ) ;
243+ }
244+ }
245+
246+ // Fall back to the lowercase version if regex extraction fails
247+ lowercase_result
248+ }
249+
224250pub fn get_provider_from_remote ( remote : & str ) -> String {
225251 let obj = VcsUrl :: parse ( remote) ;
226252 extract_provider_name ( & obj. provider ) . to_owned ( )
@@ -292,6 +318,19 @@ fn find_merge_base_ref(
292318/// Prefers "upstream" remote if it exists, then "origin", otherwise uses the first available remote.
293319/// Returns the base repository name if a remote is found.
294320pub fn git_repo_base_repo_name ( repo : & git2:: Repository ) -> Result < Option < String > > {
321+ git_repo_base_repo_name_impl ( repo, false )
322+ }
323+
324+ /// Like git_repo_base_repo_name but preserves the original case of the repository name.
325+ /// This is used specifically for build upload where case preservation is important.
326+ pub fn git_repo_base_repo_name_preserve_case ( repo : & git2:: Repository ) -> Result < Option < String > > {
327+ git_repo_base_repo_name_impl ( repo, true )
328+ }
329+
330+ fn git_repo_base_repo_name_impl (
331+ repo : & git2:: Repository ,
332+ preserve_case : bool ,
333+ ) -> Result < Option < String > > {
295334 let remotes = repo. remotes ( ) ?;
296335 let remote_names: Vec < & str > = remotes. iter ( ) . flatten ( ) . collect ( ) ;
297336
@@ -312,7 +351,12 @@ pub fn git_repo_base_repo_name(repo: &git2::Repository) -> Result<Option<String>
312351 match git_repo_remote_url ( repo, chosen_remote) {
313352 Ok ( remote_url) => {
314353 debug ! ( "Found remote '{}': {}" , chosen_remote, remote_url) ;
315- Ok ( Some ( get_repo_from_remote ( & remote_url) ) )
354+ let repo_name = if preserve_case {
355+ get_repo_from_remote_preserve_case ( & remote_url)
356+ } else {
357+ get_repo_from_remote ( & remote_url)
358+ } ;
359+ Ok ( Some ( repo_name) )
316360 }
317361 Err ( e) => {
318362 warn ! ( "Could not get URL for remote '{}': {}" , chosen_remote, e) ;
@@ -927,6 +971,43 @@ mod tests {
927971 ) ;
928972 }
929973
974+ #[ test]
975+ fn test_get_repo_from_remote_preserve_case ( ) {
976+ // Test that case-preserving function maintains original casing
977+ assert_eq ! (
978+ get_repo_from_remote_preserve_case( "https://github.com/MyOrg/MyRepo" ) ,
979+ "MyOrg/MyRepo"
980+ ) ;
981+ assert_eq ! (
982+ get_repo_from_remote_preserve_case( "git@github.com:SentryOrg/SentryRepo.git" ) ,
983+ "SentryOrg/SentryRepo"
984+ ) ;
985+ assert_eq ! (
986+ get_repo_from_remote_preserve_case( "https://gitlab.com/MyCompany/MyProject" ) ,
987+ "MyCompany/MyProject"
988+ ) ;
989+ assert_eq ! (
990+ get_repo_from_remote_preserve_case( "git@bitbucket.org:TeamName/ProjectName.git" ) ,
991+ "TeamName/ProjectName"
992+ ) ;
993+ assert_eq ! (
994+ get_repo_from_remote_preserve_case( "ssh://git@github.com/MyUser/MyRepo.git" ) ,
995+ "MyUser/MyRepo"
996+ ) ;
997+
998+ // Test that regular function still lowercases
999+ assert_eq ! (
1000+ get_repo_from_remote( "https://github.com/MyOrg/MyRepo" ) ,
1001+ "myorg/myrepo"
1002+ ) ;
1003+
1004+ // Test edge cases - should fall back to lowercase when regex doesn't match
1005+ assert_eq ! (
1006+ get_repo_from_remote_preserve_case( "invalid-url" ) ,
1007+ get_repo_from_remote( "invalid-url" )
1008+ ) ;
1009+ }
1010+
9301011 #[ test]
9311012 fn test_extract_provider_name ( ) {
9321013 // Test basic provider name extraction
0 commit comments