Skip to content

Commit e6f9511

Browse files
author
Junio C Hamano
committed
Merge branch 'js/symlink'
* js/symlink: Tell multi-parent diff about core.symlinks. Handle core.symlinks=false case in merge-recursive. Add core.symlinks to mark filesystems that do not support symbolic links.
2 parents 784b11c + a249a9b commit e6f9511

15 files changed

+175
-13
lines changed

Documentation/config.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ core.fileMode::
117117
the working copy are ignored; useful on broken filesystems like FAT.
118118
See gitlink:git-update-index[1]. True by default.
119119

120+
core.symlinks::
121+
If false, symbolic links are checked out as small plain files that
122+
contain the link text. gitlink:git-update-index[1] and
123+
gitlink:git-add[1] will not change the recorded type to regular
124+
file. Useful on filesystems like FAT that do not support
125+
symbolic links. True by default.
126+
120127
core.gitProxy::
121128
A "proxy command" to execute (as 'command host port') instead
122129
of establishing direct connection to the remote server when

Documentation/git-update-index.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,11 @@ in the index and the file mode on the filesystem if they differ only on
295295
executable bit. On such an unfortunate filesystem, you may
296296
need to use `git-update-index --chmod=`.
297297

298+
Quite similarly, if `core.symlinks` configuration variable is set
299+
to 'false' (see gitlink:git-config[1]), symbolic links are checked out
300+
as plain files, and this command does not modify a recorded file mode
301+
from symbolic link to regular file.
302+
298303
The command looks at `core.ignorestat` configuration variable. See
299304
'Using "assume unchanged" bit' section above.
300305

builtin-apply.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2359,7 +2359,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
23592359
char *nbuf;
23602360
unsigned long nsize;
23612361

2362-
if (S_ISLNK(mode))
2362+
if (has_symlinks && S_ISLNK(mode))
23632363
/* Although buf:size is counted string, it also is NUL
23642364
* terminated.
23652365
*/

builtin-update-index.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ static int add_file_to_cache(const char *path)
109109
ce->ce_flags = htons(namelen);
110110
fill_stat_cache_info(ce, &st);
111111

112-
if (trust_executable_bit)
112+
if (trust_executable_bit && has_symlinks)
113113
ce->ce_mode = create_ce_mode(st.st_mode);
114114
else {
115-
/* If there is an existing entry, pick the mode bits
116-
* from it, otherwise assume unexecutable.
115+
/* If there is an existing entry, pick the mode bits and type
116+
* from it, otherwise assume unexecutable regular file.
117117
*/
118118
struct cache_entry *ent;
119119
int pos = cache_name_pos(path, namelen);

cache.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ static inline unsigned int create_ce_mode(unsigned int mode)
108108
}
109109
static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode)
110110
{
111-
extern int trust_executable_bit;
111+
extern int trust_executable_bit, has_symlinks;
112+
if (!has_symlinks && S_ISREG(mode) &&
113+
ce && S_ISLNK(ntohl(ce->ce_mode)))
114+
return ce->ce_mode;
112115
if (!trust_executable_bit && S_ISREG(mode)) {
113116
if (ce && S_ISREG(ntohl(ce->ce_mode)))
114117
return ce->ce_mode;
@@ -215,6 +218,7 @@ extern int delete_ref(const char *, unsigned char *sha1);
215218
/* Environment bits from configuration mechanism */
216219
extern int use_legacy_headers;
217220
extern int trust_executable_bit;
221+
extern int has_symlinks;
218222
extern int assume_unchanged;
219223
extern int prefer_symlink_refs;
220224
extern int log_all_ref_updates;

combine-diff.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,8 +699,18 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
699699
!fstat(fd, &st)) {
700700
size_t len = st.st_size;
701701
size_t sz = 0;
702+
int is_file, i;
702703

703704
elem->mode = canon_mode(st.st_mode);
705+
/* if symlinks don't work, assume symlink if all parents
706+
* are symlinks
707+
*/
708+
is_file = has_symlinks;
709+
for (i = 0; !is_file && i < num_parent; i++)
710+
is_file = !S_ISLNK(elem->parent[i].mode);
711+
if (!is_file)
712+
elem->mode = canon_mode(S_IFLNK);
713+
704714
result_size = len;
705715
result = xmalloc(len + 1);
706716
while (sz < len) {

config.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ int git_default_config(const char *var, const char *value)
269269
return 0;
270270
}
271271

272+
if (!strcmp(var, "core.symlinks")) {
273+
has_symlinks = git_config_bool(var, value);
274+
return 0;
275+
}
276+
272277
if (!strcmp(var, "core.bare")) {
273278
is_bare_repository_cfg = git_config_bool(var, value);
274279
return 0;

diff-lib.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,9 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
412412
S_ISREG(newmode) && S_ISREG(oldmode) &&
413413
((newmode ^ oldmode) == 0111))
414414
newmode = oldmode;
415+
else if (!has_symlinks &&
416+
S_ISREG(newmode) && S_ISLNK(oldmode))
417+
newmode = oldmode;
415418
diff_change(&revs->diffopt, oldmode, newmode,
416419
ce->sha1, (changed ? null_sha1 : ce->sha1),
417420
ce->name, NULL);

entry.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,12 @@ static int write_entry(struct cache_entry *ce, char *path, struct checkout *stat
111111
return error("git-checkout-index: unable to write file %s", path);
112112
break;
113113
case S_IFLNK:
114-
if (to_tempfile) {
115-
strcpy(path, ".merge_link_XXXXXX");
116-
fd = mkstemp(path);
114+
if (to_tempfile || !has_symlinks) {
115+
if (to_tempfile) {
116+
strcpy(path, ".merge_link_XXXXXX");
117+
fd = mkstemp(path);
118+
} else
119+
fd = create_file(path, 0666);
117120
if (fd < 0) {
118121
free(new);
119122
return error("git-checkout-index: unable to create "

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ char git_default_email[MAX_GITNAME];
1313
char git_default_name[MAX_GITNAME];
1414
int use_legacy_headers = 1;
1515
int trust_executable_bit = 1;
16+
int has_symlinks = 1;
1617
int assume_unchanged;
1718
int prefer_symlink_refs;
1819
int is_bare_repository_cfg = -1; /* unspecified */

0 commit comments

Comments
 (0)