]> git.ipfire.org Git - thirdparty/git.git/blame - lockfile.c
t4039: abstract away SHA-1-specific constants
[thirdparty/git.git] / lockfile.c
CommitLineData
021b6e45
JH
1/*
2 * Copyright (c) 2005, Junio C Hamano
3 */
2db69de8 4
021b6e45 5#include "cache.h"
697cc8ef 6#include "lockfile.h"
021b6e45 7
5d5a7a67 8/*
0c0d6e86 9 * path = absolute or relative path name
5d5a7a67 10 *
0c0d6e86
MH
11 * Remove the last path name element from path (leaving the preceding
12 * "/", if any). If path is empty or the root directory ("/"), set
13 * path to the empty string.
5d5a7a67 14 */
0c0d6e86 15static void trim_last_path_component(struct strbuf *path)
5d5a7a67 16{
0c0d6e86 17 int i = path->len;
5d5a7a67
BS
18
19 /* back up past trailing slashes, if any */
0c0d6e86
MH
20 while (i && path->buf[i - 1] == '/')
21 i--;
5d5a7a67
BS
22
23 /*
0c0d6e86
MH
24 * then go backwards until a slash, or the beginning of the
25 * string
5d5a7a67 26 */
0c0d6e86
MH
27 while (i && path->buf[i - 1] != '/')
28 i--;
29
30 strbuf_setlen(path, i);
5d5a7a67
BS
31}
32
33
34/* We allow "recursive" symbolic links. Only within reason, though */
35#define MAXDEPTH 5
36
37/*
6cad8053 38 * path contains a path that might be a symlink.
5d5a7a67 39 *
6cad8053
MH
40 * If path is a symlink, attempt to overwrite it with a path to the
41 * real file or directory (which may or may not exist), following a
42 * chain of symlinks if necessary. Otherwise, leave path unmodified.
5d5a7a67 43 *
6cad8053
MH
44 * This is a best-effort routine. If an error occurs, path will
45 * either be left unmodified or will name a different symlink in a
46 * symlink chain that started with the original path.
5d5a7a67 47 */
6cad8053 48static void resolve_symlink(struct strbuf *path)
5d5a7a67
BS
49{
50 int depth = MAXDEPTH;
5025d845 51 static struct strbuf link = STRBUF_INIT;
5d5a7a67
BS
52
53 while (depth--) {
6cad8053 54 if (strbuf_readlink(&link, path->buf, path->len) < 0)
5025d845 55 break;
5d5a7a67 56
6cad8053 57 if (is_absolute_path(link.buf))
5d5a7a67 58 /* absolute path simply replaces p */
6cad8053 59 strbuf_reset(path);
0c0d6e86 60 else
5d5a7a67 61 /*
5025d845 62 * link is a relative path, so replace the
5d5a7a67
BS
63 * last element of p with it.
64 */
0c0d6e86 65 trim_last_path_component(path);
6cad8053
MH
66
67 strbuf_addbuf(path, &link);
5d5a7a67 68 }
5025d845 69 strbuf_reset(&link);
5d5a7a67
BS
70}
71
447ff1bf 72/* Make sure errno contains a meaningful value on error */
acd3b9ec 73static int lock_file(struct lock_file *lk, const char *path, int flags)
021b6e45 74{
1a9d15db 75 struct strbuf filename = STRBUF_INIT;
04e57d4d 76
1a9d15db
MH
77 strbuf_addstr(&filename, path);
78 if (!(flags & LOCK_NO_DEREF))
79 resolve_symlink(&filename);
fa137f67 80
1a9d15db 81 strbuf_addstr(&filename, LOCK_SUFFIX);
076aa2cb 82 lk->tempfile = create_tempfile(filename.buf);
1a9d15db 83 strbuf_release(&filename);
076aa2cb 84 return lk->tempfile ? lk->tempfile->fd : -1;
021b6e45
JH
85}
86
044b6a9e
MH
87/*
88 * Constants defining the gaps between attempts to lock a file. The
89 * first backoff period is approximately INITIAL_BACKOFF_MS
90 * milliseconds. The longest backoff period is approximately
91 * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds.
92 */
93#define INITIAL_BACKOFF_MS 1L
94#define BACKOFF_MAX_MULTIPLIER 1000
95
96/*
97 * Try locking path, retrying with quadratic backoff for at least
98 * timeout_ms milliseconds. If timeout_ms is 0, try locking the file
99 * exactly once. If timeout_ms is -1, try indefinitely.
100 */
101static int lock_file_timeout(struct lock_file *lk, const char *path,
102 int flags, long timeout_ms)
103{
104 int n = 1;
105 int multiplier = 1;
a8a17756 106 long remaining_ms = 0;
044b6a9e
MH
107 static int random_initialized = 0;
108
109 if (timeout_ms == 0)
110 return lock_file(lk, path, flags);
111
112 if (!random_initialized) {
1e9676ec 113 srand((unsigned int)getpid());
044b6a9e
MH
114 random_initialized = 1;
115 }
116
a8a17756
JS
117 if (timeout_ms > 0)
118 remaining_ms = timeout_ms;
044b6a9e
MH
119
120 while (1) {
a8a17756 121 long backoff_ms, wait_ms;
044b6a9e
MH
122 int fd;
123
124 fd = lock_file(lk, path, flags);
125
126 if (fd >= 0)
127 return fd; /* success */
128 else if (errno != EEXIST)
129 return -1; /* failure other than lock held */
a8a17756 130 else if (timeout_ms > 0 && remaining_ms <= 0)
044b6a9e
MH
131 return -1; /* failure due to timeout */
132
133 backoff_ms = multiplier * INITIAL_BACKOFF_MS;
134 /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */
a8a17756 135 wait_ms = (750 + rand() % 500) * backoff_ms / 1000;
30f8160d 136 sleep_millisec(wait_ms);
a8a17756 137 remaining_ms -= wait_ms;
044b6a9e
MH
138
139 /* Recursion: (n+1)^2 = n^2 + 2n + 1 */
140 multiplier += 2*n + 1;
141 if (multiplier > BACKOFF_MAX_MULTIPLIER)
142 multiplier = BACKOFF_MAX_MULTIPLIER;
143 else
144 n++;
145 }
146}
147
6af926e8 148void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
e43a6fd3 149{
bdfd739d 150 if (err == EEXIST) {
3030c295 151 strbuf_addf(buf, _("Unable to create '%s.lock': %s.\n\n"
aed7480c
MM
152 "Another git process seems to be running in this repository, e.g.\n"
153 "an editor opened by 'git commit'. Please make sure all processes\n"
154 "are terminated then try again. If it still fails, a git process\n"
155 "may have crashed in this repository earlier:\n"
156 "remove the file manually to continue."),
e2a57aac 157 absolute_path(path), strerror(err));
1b018fd9 158 } else
3030c295 159 strbuf_addf(buf, _("Unable to create '%s.lock': %s"),
e2a57aac 160 absolute_path(path), strerror(err));
1b018fd9
MV
161}
162
e197c218 163NORETURN void unable_to_lock_die(const char *path, int err)
1b018fd9 164{
6af926e8
RS
165 struct strbuf buf = STRBUF_INIT;
166
167 unable_to_lock_message(path, err, &buf);
168 die("%s", buf.buf);
e43a6fd3
MM
169}
170
447ff1bf 171/* This should return a meaningful errno on failure */
044b6a9e
MH
172int hold_lock_file_for_update_timeout(struct lock_file *lk, const char *path,
173 int flags, long timeout_ms)
40aaae88 174{
044b6a9e 175 int fd = lock_file_timeout(lk, path, flags, timeout_ms);
3f061bf5
JH
176 if (fd < 0) {
177 if (flags & LOCK_DIE_ON_ERROR)
178 unable_to_lock_die(path, errno);
179 if (flags & LOCK_REPORT_ON_ERROR) {
180 struct strbuf buf = STRBUF_INIT;
181 unable_to_lock_message(path, errno, &buf);
182 error("%s", buf.buf);
183 strbuf_release(&buf);
184 }
185 }
40aaae88
JH
186 return fd;
187}
188
ec38b4e4
MH
189char *get_locked_file_path(struct lock_file *lk)
190{
1a9d15db 191 struct strbuf ret = STRBUF_INIT;
013870cd 192
076aa2cb 193 strbuf_addstr(&ret, get_tempfile_path(lk->tempfile));
1a9d15db
MH
194 if (ret.len <= LOCK_SUFFIX_LEN ||
195 strcmp(ret.buf + ret.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
033abf97 196 BUG("get_locked_file_path() called for malformed lock object");
9c77381d 197 /* remove ".lock": */
1a9d15db
MH
198 strbuf_setlen(&ret, ret.len - LOCK_SUFFIX_LEN);
199 return strbuf_detach(&ret, NULL);
93dcaea2
JH
200}
201
751baced 202int commit_lock_file(struct lock_file *lk)
021b6e45 203{
9c77381d 204 char *result_path = get_locked_file_path(lk);
8a1c7533 205
9c77381d 206 if (commit_lock_file_to(lk, result_path)) {
1b1648f4 207 int save_errno = errno;
9c77381d 208 free(result_path);
1b1648f4 209 errno = save_errno;
d6cf61bf 210 return -1;
1b1648f4 211 }
9c77381d 212 free(result_path);
d6cf61bf 213 return 0;
021b6e45 214}