@@ -109,6 +109,7 @@ impl Config {
109109 /// }
110110 /// }
111111 /// ```
112+ #[ allow( dead_code) ]
112113 pub fn load ( ) -> Result < Self > {
113114 if let Ok ( repo) = git2:: Repository :: discover ( "." ) {
114115 // Try to find .git-workers.toml in the default branch (main or master)
@@ -121,14 +122,105 @@ impl Config {
121122 Ok ( Config :: default ( ) )
122123 }
123124
125+ /// Loads configuration from a specific path context
126+ ///
127+ /// This method loads configuration using the specified directory as the base
128+ /// path for the configuration lookup strategy. This is useful for hook execution
129+ /// where the configuration should be loaded relative to the worktree path
130+ /// rather than the current working directory.
131+ ///
132+ /// # Process
133+ ///
134+ /// 1. Discovers Git repository from the target path
135+ /// 2. Applies the configuration lookup strategy using the target path as context
136+ /// 3. Does not modify the current working directory (thread-safe)
137+ ///
138+ /// # Arguments
139+ ///
140+ /// * `path` - The directory path to use as context for configuration loading
141+ ///
142+ /// # Returns
143+ ///
144+ /// A `Result` containing the loaded configuration or a default configuration
145+ /// if no config file is found.
146+ ///
147+ /// # Example
148+ ///
149+ /// ```no_run
150+ /// use git_workers::config::Config;
151+ /// use std::path::Path;
152+ ///
153+ /// let worktree_path = Path::new("/path/to/worktree");
154+ /// let config = Config::load_from_path(worktree_path)
155+ /// .expect("Failed to load config from worktree path");
156+ /// ```
157+ pub fn load_from_path ( path : & std:: path:: Path ) -> Result < Self > {
158+ if let Ok ( repo) = git2:: Repository :: discover ( path) {
159+ if let Some ( config) = Self :: load_from_path_context ( path, & repo) ? {
160+ return Ok ( config) ;
161+ }
162+ }
163+
164+ // Return default config if no repo found
165+ Ok ( Config :: default ( ) )
166+ }
167+
168+ /// Loads configuration from a specific path context
169+ ///
170+ /// This is the thread-safe implementation that loads configuration without
171+ /// changing the current working directory.
172+ ///
173+ /// # Arguments
174+ ///
175+ /// * `base_path` - The directory path to use as context
176+ /// * `repo` - The Git repository reference
177+ ///
178+ /// # Returns
179+ ///
180+ /// * `Ok(Some(config))` - Configuration was found and loaded
181+ /// * `Ok(None)` - No configuration file exists
182+ /// * `Err(...)` - An error occurred while loading
183+ fn load_from_path_context (
184+ base_path : & std:: path:: Path ,
185+ repo : & git2:: Repository ,
186+ ) -> Result < Option < Self > > {
187+ // Check parent directories first for main/master config (highest priority)
188+ if let Some ( parent) = base_path. parent ( ) {
189+ let main_path = parent. join ( "main" ) . join ( ".git-workers.toml" ) ;
190+ let master_path = parent. join ( "master" ) . join ( ".git-workers.toml" ) ;
191+
192+ if main_path. exists ( ) {
193+ return Self :: load_from_file ( & main_path, repo) ;
194+ } else if master_path. exists ( ) {
195+ return Self :: load_from_file ( & master_path, repo) ;
196+ }
197+ }
198+
199+ // Then check the base path directory
200+ let current_config = base_path. join ( ".git-workers.toml" ) ;
201+ if current_config. exists ( ) {
202+ return Self :: load_from_file ( & current_config, repo) ;
203+ }
204+
205+ // If not found, check the repository working directory
206+ if let Some ( workdir) = repo. workdir ( ) {
207+ let config_path = workdir. join ( ".git-workers.toml" ) ;
208+ if config_path. exists ( ) {
209+ return Self :: load_from_file ( & config_path, repo) ;
210+ }
211+ }
212+
213+ Ok ( None )
214+ }
215+
124216 /// Loads configuration from the default branch (main or master)
125217 ///
126218 /// This method implements the configuration lookup strategy:
127219 ///
128- /// 1. **Current directory**: First checks the current directory for `.git-workers.toml`
220+ /// 1. **Parent main/master**: First looks for config in the main/master worktree
221+ /// in the parent directory (for worktree structures)
222+ /// 2. **Current directory**: Then checks the current directory for `.git-workers.toml`
129223 /// (useful for bare repository worktrees)
130- /// 2. **Parent main/master**: If in a worktree structure, looks for config in the
131- /// main/master worktree in the parent directory
132224 /// 3. **Repository root**: Falls back to checking the current repository's
133225 /// working directory
134226 ///
@@ -144,15 +236,12 @@ impl Config {
144236 /// * `Ok(Some(config))` - Configuration was found and loaded
145237 /// * `Ok(None)` - No configuration file exists
146238 /// * `Err(...)` - An error occurred while loading
239+ #[ allow( dead_code) ]
147240 fn load_from_default_branch ( repo : & git2:: Repository ) -> Result < Option < Self > > {
148241 // First, check current directory (useful for bare repo worktrees)
149242 if let Ok ( cwd) = std:: env:: current_dir ( ) {
150- let current_config = cwd. join ( ".git-workers.toml" ) ;
151- if current_config. exists ( ) {
152- return Self :: load_from_file ( & current_config, repo) ;
153- }
154-
155243 // Check if we're in a worktree structure like /path/to/repo/branch/worktree-name
244+ // Check parent directories first for main/master config
156245 if let Some ( parent) = cwd. parent ( ) {
157246 // Look for main or master directories in the parent
158247 let main_path = parent. join ( "main" ) . join ( ".git-workers.toml" ) ;
@@ -164,6 +253,12 @@ impl Config {
164253 return Self :: load_from_file ( & master_path, repo) ;
165254 }
166255 }
256+
257+ // Then check current directory
258+ let current_config = cwd. join ( ".git-workers.toml" ) ;
259+ if current_config. exists ( ) {
260+ return Self :: load_from_file ( & current_config, repo) ;
261+ }
167262 }
168263
169264 // If not found in parent, check the current repository
0 commit comments