@@ -167,11 +167,69 @@ static int need_to_gc(void)
167167 return 1 ;
168168}
169169
170+ /* return NULL on success, else hostname running the gc */
171+ static const char * lock_repo_for_gc (int force , pid_t * ret_pid )
172+ {
173+ static struct lock_file lock ;
174+ static char locking_host [128 ];
175+ char my_host [128 ];
176+ struct strbuf sb = STRBUF_INIT ;
177+ struct stat st ;
178+ uintmax_t pid ;
179+ FILE * fp ;
180+ int fd , should_exit ;
181+
182+ if (gethostname (my_host , sizeof (my_host )))
183+ strcpy (my_host , "unknown" );
184+
185+ fd = hold_lock_file_for_update (& lock , git_path ("gc.pid" ),
186+ LOCK_DIE_ON_ERROR );
187+ if (!force ) {
188+ fp = fopen (git_path ("gc.pid" ), "r" );
189+ memset (locking_host , 0 , sizeof (locking_host ));
190+ should_exit =
191+ fp != NULL &&
192+ !fstat (fileno (fp ), & st ) &&
193+ /*
194+ * 12 hour limit is very generous as gc should
195+ * never take that long. On the other hand we
196+ * don't really need a strict limit here,
197+ * running gc --auto one day late is not a big
198+ * problem. --force can be used in manual gc
199+ * after the user verifies that no gc is
200+ * running.
201+ */
202+ time (NULL ) - st .st_mtime <= 12 * 3600 &&
203+ fscanf (fp , "%" PRIuMAX " %127c" , & pid , locking_host ) == 2 &&
204+ /* be gentle to concurrent "gc" on remote hosts */
205+ (strcmp (locking_host , my_host ) || !kill (pid , 0 ));
206+ if (fp != NULL )
207+ fclose (fp );
208+ if (should_exit ) {
209+ if (fd >= 0 )
210+ rollback_lock_file (& lock );
211+ * ret_pid = pid ;
212+ return locking_host ;
213+ }
214+ }
215+
216+ strbuf_addf (& sb , "%" PRIuMAX " %s" ,
217+ (uintmax_t ) getpid (), my_host );
218+ write_in_full (fd , sb .buf , sb .len );
219+ strbuf_release (& sb );
220+ commit_lock_file (& lock );
221+
222+ return NULL ;
223+ }
224+
170225int cmd_gc (int argc , const char * * argv , const char * prefix )
171226{
172227 int aggressive = 0 ;
173228 int auto_gc = 0 ;
174229 int quiet = 0 ;
230+ int force = 0 ;
231+ const char * name ;
232+ pid_t pid ;
175233
176234 struct option builtin_gc_options [] = {
177235 OPT__QUIET (& quiet , N_ ("suppress progress reporting" )),
@@ -180,6 +238,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
180238 PARSE_OPT_OPTARG , NULL , (intptr_t )prune_expire },
181239 OPT_BOOLEAN (0 , "aggressive" , & aggressive , N_ ("be more thorough (increased runtime)" )),
182240 OPT_BOOLEAN (0 , "auto" , & auto_gc , N_ ("enable auto-gc mode" )),
241+ OPT_BOOL (0 , "force" , & force , N_ ("force running gc even if there may be another gc running" )),
183242 OPT_END ()
184243 };
185244
@@ -225,6 +284,14 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
225284 } else
226285 add_repack_all_option ();
227286
287+ name = lock_repo_for_gc (force , & pid );
288+ if (name ) {
289+ if (auto_gc )
290+ return 0 ; /* be quiet on --auto */
291+ die (_ ("gc is already running on machine '%s' pid %" PRIuMAX " (use --force if not)" ),
292+ name , (uintmax_t )pid );
293+ }
294+
228295 if (pack_refs && run_command_v_opt (pack_refs_cmd .argv , RUN_GIT_CMD ))
229296 return error (FAILED_RUN , pack_refs_cmd .argv [0 ]);
230297
0 commit comments