11use  anyhow:: Context ; 
22use  gitbutler_error:: error:: Code ; 
33use  gix:: prelude:: ObjectIdExt ; 
4+ use  std:: io:: Write ; 
45
56use  crate :: { GitConfigSettings ,  commit:: TreeKind } ; 
67
@@ -14,6 +15,13 @@ pub trait RepositoryExt {
1415fn  commit_signatures ( & self )  -> anyhow:: Result < ( gix:: actor:: Signature ,  gix:: actor:: Signature ) > ; 
1516    /// Return labels that would be written into the conflict markers when merging blobs. 
1617fn  default_merge_labels ( & self )  -> gix:: merge:: blob:: builtin_driver:: text:: Labels < ' static > ; 
18+ 
19+     /// Return the configuration freshly loaded from `.git/config` so that it can be changed in memory, 
20+ /// and possibly written back with [Self::write_local_config()]. 
21+ fn  local_common_config_for_editing ( & self )  -> anyhow:: Result < gix:: config:: File < ' static > > ; 
22+     /// Write the given `local_config` to `.git/config` of the common repository. 
23+ /// Note that we never write linked worktree-local configuration. 
24+ fn  write_local_common_config ( & self ,  local_config :  & gix:: config:: File )  -> anyhow:: Result < ( ) > ; 
1725    /// Cherry-pick the changes in the tree of `to_rebase_commit_id` onto `new_base_commit_id`. 
1826/// This method deals with the presence of conflicting commits to select the correct trees 
1927/// for the cheery-pick merge. 
@@ -105,9 +113,40 @@ impl RepositoryExt for gix::Repository {
105113        let  config = repo. config_snapshot ( ) ; 
106114        GitConfigSettings :: try_from_snapshot ( & config) 
107115    } 
116+ 
108117    fn  set_git_settings ( & self ,  settings :  & GitConfigSettings )  -> anyhow:: Result < ( ) >  { 
109118        settings. persist_to_local_config ( self ) 
110119    } 
120+ 
121+     fn  local_common_config_for_editing ( & self )  -> anyhow:: Result < gix:: config:: File < ' static > >  { 
122+         let  local_config_path = self . common_dir ( ) . join ( "config" ) ; 
123+         let  config = gix:: config:: File :: from_path_no_includes ( 
124+             local_config_path. clone ( ) , 
125+             gix:: config:: Source :: Local , 
126+         ) ?; 
127+         Ok ( config) 
128+     } 
129+ 
130+     fn  write_local_common_config ( & self ,  local_config :  & gix:: config:: File )  -> anyhow:: Result < ( ) >  { 
131+         // Note: we don't use a lock file here to not risk changing the mode, and it's what Git does. 
132+         //       But we lock the file so there is no raciness. 
133+         let  local_config_path = self . common_dir ( ) . join ( "config" ) ; 
134+         let  _lock = gix:: lock:: Marker :: acquire_to_hold_resource ( 
135+             & local_config_path, 
136+             gix:: lock:: acquire:: Fail :: Immediately , 
137+             None , 
138+         ) ?; 
139+         let  mut  config_file = std:: io:: BufWriter :: new ( 
140+             std:: fs:: File :: options ( ) 
141+                 . write ( true ) 
142+                 . truncate ( true ) 
143+                 . create ( false ) 
144+                 . open ( local_config_path) ?, 
145+         ) ; 
146+         local_config. write_to ( & mut  config_file) ?; 
147+         config_file. flush ( ) ?; 
148+         Ok ( ( ) ) 
149+     } 
111150} 
112151
113152const  GITBUTLER_COMMIT_AUTHOR_NAME :  & str  = "GitButler" ; 
0 commit comments