Merge branch 'nd/multiple-work-trees'
A replacement for contrib/workdir/git-new-workdir that does not rely on symbolic links and make sharing of objects and refs safer by making the borrowee and borrowers aware of each other. * nd/multiple-work-trees: (41 commits) prune --worktrees: fix expire vs worktree existence condition t1501: fix test with split index t2026: fix broken &&-chain t2026 needs procondition SANITY git-checkout.txt: a note about multiple checkout support for submodules checkout: add --ignore-other-wortrees checkout: pass whole struct to parse_branchname_arg instead of individual flags git-common-dir: make "modules/" per-working-directory directory checkout: do not fail if target is an empty directory t2025: add a test to make sure grafts is working from a linked checkout checkout: don't require a work tree when checking out into a new one git_path(): keep "info/sparse-checkout" per work-tree count-objects: report unused files in $GIT_DIR/worktrees/... gc: support prune --worktrees gc: factor out gc.pruneexpire parsing code gc: style change -- no SP before closing parenthesis checkout: clean up half-prepared directories in --to mode checkout: reject if the branch is already checked out elsewhere prune: strategies for linked checkouts checkout: support checking out into a new working directory ...
This commit is contained in:
59
refs.c
59
refs.c
@ -1382,7 +1382,7 @@ static int resolve_gitlink_ref_recursive(struct ref_cache *refs,
|
||||
{
|
||||
int fd, len;
|
||||
char buffer[128], *p;
|
||||
char *path;
|
||||
const char *path;
|
||||
|
||||
if (recursion > MAXDEPTH || strlen(refname) > MAXREFLEN)
|
||||
return -1;
|
||||
@ -1475,7 +1475,11 @@ static int resolve_missing_loose_ref(const char *refname,
|
||||
}
|
||||
|
||||
/* This function needs to return a meaningful errno on failure */
|
||||
const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
|
||||
static const char *resolve_ref_unsafe_1(const char *refname,
|
||||
int resolve_flags,
|
||||
unsigned char *sha1,
|
||||
int *flags,
|
||||
struct strbuf *sb_path)
|
||||
{
|
||||
int depth = MAXDEPTH;
|
||||
ssize_t len;
|
||||
@ -1506,7 +1510,7 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
|
||||
bad_name = 1;
|
||||
}
|
||||
for (;;) {
|
||||
char path[PATH_MAX];
|
||||
const char *path;
|
||||
struct stat st;
|
||||
char *buf;
|
||||
int fd;
|
||||
@ -1516,7 +1520,9 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
|
||||
return NULL;
|
||||
}
|
||||
|
||||
git_snpath(path, sizeof(path), "%s", refname);
|
||||
strbuf_reset(sb_path);
|
||||
strbuf_git_path(sb_path, "%s", refname);
|
||||
path = sb_path->buf;
|
||||
|
||||
/*
|
||||
* We might have to loop back here to avoid a race
|
||||
@ -1643,6 +1649,16 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
|
||||
unsigned char *sha1, int *flags)
|
||||
{
|
||||
struct strbuf sb_path = STRBUF_INIT;
|
||||
const char *ret = resolve_ref_unsafe_1(refname, resolve_flags,
|
||||
sha1, flags, &sb_path);
|
||||
strbuf_release(&sb_path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *resolve_refdup(const char *ref, int resolve_flags, unsigned char *sha1, int *flags)
|
||||
{
|
||||
return xstrdup_or_null(resolve_ref_unsafe(ref, resolve_flags, sha1, flags));
|
||||
@ -2274,7 +2290,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
|
||||
const struct string_list *skip,
|
||||
unsigned int flags, int *type_p)
|
||||
{
|
||||
char *ref_file;
|
||||
const char *ref_file;
|
||||
const char *orig_refname = refname;
|
||||
struct ref_lock *lock;
|
||||
int last_errno = 0;
|
||||
@ -2343,7 +2359,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
|
||||
ref_file = git_path("%s", refname);
|
||||
|
||||
retry:
|
||||
switch (safe_create_leading_directories(ref_file)) {
|
||||
switch (safe_create_leading_directories_const(ref_file)) {
|
||||
case SCLD_OK:
|
||||
break; /* success */
|
||||
case SCLD_VANISHED:
|
||||
@ -2721,7 +2737,7 @@ static int rename_tmp_log(const char *newrefname)
|
||||
int attempts_remaining = 4;
|
||||
|
||||
retry:
|
||||
switch (safe_create_leading_directories(git_path("logs/%s", newrefname))) {
|
||||
switch (safe_create_leading_directories_const(git_path("logs/%s", newrefname))) {
|
||||
case SCLD_OK:
|
||||
break; /* success */
|
||||
case SCLD_VANISHED:
|
||||
@ -2907,11 +2923,15 @@ static int copy_msg(char *buf, const char *msg)
|
||||
}
|
||||
|
||||
/* This function must set a meaningful errno on failure */
|
||||
int log_ref_setup(const char *refname, char *logfile, int bufsize)
|
||||
int log_ref_setup(const char *refname, struct strbuf *sb_logfile)
|
||||
{
|
||||
int logfd, oflags = O_APPEND | O_WRONLY;
|
||||
char *logfile;
|
||||
|
||||
git_snpath(logfile, bufsize, "logs/%s", refname);
|
||||
strbuf_git_path(sb_logfile, "logs/%s", refname);
|
||||
logfile = sb_logfile->buf;
|
||||
/* make sure the rest of the function can't change "logfile" */
|
||||
sb_logfile = NULL;
|
||||
if (log_all_ref_updates &&
|
||||
(starts_with(refname, "refs/heads/") ||
|
||||
starts_with(refname, "refs/remotes/") ||
|
||||
@ -2982,18 +3002,22 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int log_ref_write(const char *refname, const unsigned char *old_sha1,
|
||||
const unsigned char *new_sha1, const char *msg)
|
||||
static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,
|
||||
const unsigned char *new_sha1, const char *msg,
|
||||
struct strbuf *sb_log_file)
|
||||
{
|
||||
int logfd, result, oflags = O_APPEND | O_WRONLY;
|
||||
char log_file[PATH_MAX];
|
||||
char *log_file;
|
||||
|
||||
if (log_all_ref_updates < 0)
|
||||
log_all_ref_updates = !is_bare_repository();
|
||||
|
||||
result = log_ref_setup(refname, log_file, sizeof(log_file));
|
||||
result = log_ref_setup(refname, sb_log_file);
|
||||
if (result)
|
||||
return result;
|
||||
log_file = sb_log_file->buf;
|
||||
/* make sure the rest of the function can't change "log_file" */
|
||||
sb_log_file = NULL;
|
||||
|
||||
logfd = open(log_file, oflags);
|
||||
if (logfd < 0)
|
||||
@ -3016,6 +3040,15 @@ static int log_ref_write(const char *refname, const unsigned char *old_sha1,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int log_ref_write(const char *refname, const unsigned char *old_sha1,
|
||||
const unsigned char *new_sha1, const char *msg)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
int ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb);
|
||||
strbuf_release(&sb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int is_branch(const char *refname)
|
||||
{
|
||||
return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
|
||||
|
Reference in New Issue
Block a user