Skip to content

Commit b3b0d1c

Browse files
derrickstoleedscho
authored andcommitted
Merge pull request git-for-windows#468: maintenance: delete stale lock files, fix loose-objects task
The maintenance.lock file exists to prevent concurrent maintenance processes from writing to a repository at the same time. However, it has the downside of causing maintenance to start failing without recovery if there is any reason why the maintenance command failed without cleaning up the lock-file. This change makes it such that maintenance will delete a lock file that was modified over 6 hours ago. This will auto-heal repositories that are stuck with failed maintenance (and maybe it will fail again, but we will get a message other than the lock file exists). The intention here is to get users out of a bad state without weakening the maintenance lock _too_ much. I'm open to other thoughts, including expanding the timeframe from 6 to 24 hours. --- The `fixup!` commit fixes the use of the `gvfs.sharedcache` config value around the loose-objects task. Specifically, the loose-objects step might fail because it is calling `git pack-objects {garbage}/pack/loose` which fails.
2 parents d66465e + e1d605d commit b3b0d1c

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

builtin/gc.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,8 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts)
12851285
char *lock_path = xstrfmt("%s/maintenance", r->objects->odb->path);
12861286

12871287
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) {
1288+
struct stat st;
1289+
struct strbuf lock_dot_lock = STRBUF_INIT;
12881290
/*
12891291
* Another maintenance command is running.
12901292
*
@@ -1295,6 +1297,25 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts)
12951297
if (!opts->auto_flag && !opts->quiet)
12961298
warning(_("lock file '%s' exists, skipping maintenance"),
12971299
lock_path);
1300+
1301+
/*
1302+
* Check timestamp on .lock file to see if we should
1303+
* delete it to recover from a fail state.
1304+
*/
1305+
strbuf_addstr(&lock_dot_lock, lock_path);
1306+
strbuf_addstr(&lock_dot_lock, ".lock");
1307+
if (lstat(lock_dot_lock.buf, &st))
1308+
warning_errno(_("unable to stat '%s'"), lock_dot_lock.buf);
1309+
else {
1310+
if (st.st_mtime < time(NULL) - (6 * 60 * 60)) {
1311+
if (unlink(lock_dot_lock.buf))
1312+
warning_errno(_("unable to delete stale lock file"));
1313+
else
1314+
warning(_("deleted stale lock file"));
1315+
}
1316+
}
1317+
1318+
strbuf_release(&lock_dot_lock);
12981319
free(lock_path);
12991320
return 0;
13001321
}

t/t7900-maintenance.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ test_expect_success 'run [--auto|--quiet]' '
5454
test_subcommand git gc --no-quiet <run-no-quiet.txt
5555
'
5656

57+
test_expect_success 'lock file behavior' '
58+
test_when_finished git config --unset maintenance.commit-graph.schedule &&
59+
git config maintenance.commit-graph.schedule hourly &&
60+
61+
touch .git/objects/maintenance.lock &&
62+
git maintenance run --schedule=hourly --no-quiet 2>err &&
63+
grep "lock file .* exists, skipping maintenance" err &&
64+
65+
test-tool chmtime =-22000 .git/objects/maintenance.lock &&
66+
git maintenance run --schedule=hourly --no-quiet 2>err &&
67+
grep "deleted stale lock file" err &&
68+
test_path_is_missing .git/objects/maintenance.lock &&
69+
70+
git maintenance run --schedule=hourly 2>err &&
71+
test_must_be_empty err
72+
'
73+
5774
test_expect_success 'maintenance.auto config option' '
5875
GIT_TRACE2_EVENT="$(pwd)/default" git commit --quiet --allow-empty -m 1 &&
5976
test_subcommand git maintenance run --auto --quiet <default &&

0 commit comments

Comments
 (0)