Skip to content

Commit 6b49a75

Browse files
committed
Introduce helper to create symlinks that knows about index_state
On Windows, symbolic links actually have a type depending on the target: it can be a file or a directory. In certain circumstances, this poses problems, e.g. when a symbolic link is supposed to point into a submodule that is not checked out, so there is no way for Git to auto-detect the type. To help with that, we will add support over the course of the next commits to specify that symlink type via the Git attributes. This requires an index_state, though, something that Git for Windows' `symlink()` replacement cannot know about because the function signature is defined by the POSIX standard and not ours to change. So let's introduce a helper function to create symbolic links that *does* know about the index_state. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 12a55ec commit 6b49a75

File tree

9 files changed

+20
-9
lines changed

9 files changed

+20
-9
lines changed

apply.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -4376,7 +4376,7 @@ static int try_create_file(struct apply_state *state, const char *path,
43764376
/* Although buf:size is counted string, it also is NUL
43774377
* terminated.
43784378
*/
4379-
return !!symlink(buf, path);
4379+
return !!create_symlink(state && state->repo ? state->repo->index : NULL, buf, path);
43804380

43814381
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
43824382
if (fd < 0)

builtin/difftool.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
516516
}
517517
add_path(&wtdir, wtdir_len, dst_path);
518518
if (symlinks) {
519-
if (symlink(wtdir.buf, rdir.buf)) {
519+
if (create_symlink(lstate.istate, wtdir.buf, rdir.buf)) {
520520
ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf);
521521
goto finish;
522522
}

builtin/init-db.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
7878
if (strbuf_readlink(&lnk, template_path->buf,
7979
st_template.st_size) < 0)
8080
die_errno(_("cannot readlink '%s'"), template_path->buf);
81-
if (symlink(lnk.buf, path->buf))
81+
if (create_symlink(NULL, lnk.buf, path->buf))
8282
die_errno(_("cannot symlink '%s' '%s'"),
8383
lnk.buf, path->buf);
8484
strbuf_release(&lnk);
@@ -300,7 +300,7 @@ static int create_default_files(const char *template_path,
300300
path = git_path_buf(&buf, "tXXXXXX");
301301
if (!close(xmkstemp(path)) &&
302302
!unlink(path) &&
303-
!symlink("testing", path) &&
303+
!create_symlink(NULL, "testing", path) &&
304304
!lstat(path, &st1) &&
305305
S_ISLNK(st1.st_mode))
306306
unlink(path); /* good */

compat/mingw.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2902,7 +2902,7 @@ int link(const char *oldpath, const char *newpath)
29022902
return 0;
29032903
}
29042904

2905-
int symlink(const char *target, const char *link)
2905+
int mingw_create_symlink(struct index_state *index, const char *target, const char *link)
29062906
{
29072907
wchar_t wtarget[MAX_LONG_PATH], wlink[MAX_LONG_PATH];
29082908
int len;

compat/mingw.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,10 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
215215
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
216216
int link(const char *oldpath, const char *newpath);
217217
int uname(struct utsname *buf);
218-
int symlink(const char *target, const char *link);
219218
int readlink(const char *path, char *buf, size_t bufsiz);
219+
struct index_state;
220+
int mingw_create_symlink(struct index_state *index, const char *target, const char *link);
221+
#define create_symlink mingw_create_symlink
220222

221223
/*
222224
* replacements of existing functions

entry.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
306306
if (!has_symlinks || to_tempfile)
307307
goto write_file_entry;
308308

309-
ret = symlink(new_blob, path);
309+
ret = create_symlink(state->istate, new_blob, path);
310310
free(new_blob);
311311
if (ret)
312312
return error_errno("unable to create symlink %s", path);

git-compat-util.h

+9
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,15 @@ static inline int git_has_dir_sep(const char *path)
566566
#define is_mount_point is_mount_point_via_stat
567567
#endif
568568

569+
#ifndef create_symlink
570+
struct index_state;
571+
static inline int git_create_symlink(struct index_state *index, const char *target, const char *link)
572+
{
573+
return symlink(target, link);
574+
}
575+
#define create_symlink git_create_symlink
576+
#endif
577+
569578
#ifndef query_user_email
570579
#define query_user_email() NULL
571580
#endif

merge-recursive.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,7 @@ static int update_file_flags(struct merge_options *opt,
993993
char *lnk = xmemdupz(buf, size);
994994
safe_create_leading_directories_const(path);
995995
unlink(path);
996-
if (symlink(lnk, path))
996+
if (create_symlink(&opt->priv->orig_index, lnk, path))
997997
ret = err(opt, _("failed to symlink '%s': %s"),
998998
path, strerror(errno));
999999
free(lnk);

refs/files-backend.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1871,7 +1871,7 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target)
18711871
#ifndef NO_SYMLINK_HEAD
18721872
char *ref_path = get_locked_file_path(&lock->lk);
18731873
unlink(ref_path);
1874-
ret = symlink(target, ref_path);
1874+
ret = create_symlink(NULL, target, ref_path);
18751875
free(ref_path);
18761876

18771877
if (ret)

0 commit comments

Comments
 (0)