Skip to content

Commit cd9ae41

Browse files
committed
Merge pull request #156 from kblees/kb/symlinks
Symlink support
2 parents 30f1a27 + 6f3590a commit cd9ae41

File tree

10 files changed

+568
-200
lines changed

10 files changed

+568
-200
lines changed

compat/mingw.c

+533-173
Large diffs are not rendered by default.

compat/mingw.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,6 @@ struct utsname {
123123
* trivial stubs
124124
*/
125125

126-
static inline int readlink(const char *path, char *buf, size_t bufsiz)
127-
{ errno = ENOSYS; return -1; }
128-
static inline int symlink(const char *oldpath, const char *newpath)
129-
{ errno = ENOSYS; return -1; }
130126
static inline int fchmod(int fildes, mode_t mode)
131127
{ errno = ENOSYS; return -1; }
132128
#ifndef __MINGW64_VERSION_MAJOR
@@ -225,6 +221,8 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
225221
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
226222
int link(const char *oldpath, const char *newpath);
227223
int uname(struct utsname *buf);
224+
int symlink(const char *target, const char *link);
225+
int readlink(const char *path, char *buf, size_t bufsiz);
228226

229227
/*
230228
* replacements of existing functions
@@ -457,6 +455,8 @@ static inline void convert_slashes(char *path)
457455
int mingw_offset_1st_component(const char *path);
458456
#define offset_1st_component mingw_offset_1st_component
459457
#define PATH_SEP ';'
458+
extern char *mingw_query_user_email(void);
459+
#define query_user_email mingw_query_user_email
460460
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
461461
#define PRIuMAX "I64u"
462462
#define PRId64 "I64d"

compat/win32.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
#include <windows.h>
77
#endif
88

9-
static inline int file_attr_to_st_mode (DWORD attr)
9+
static inline int file_attr_to_st_mode (DWORD attr, DWORD tag)
1010
{
1111
int fMode = S_IREAD;
12-
if (attr & FILE_ATTRIBUTE_DIRECTORY)
12+
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) && tag == IO_REPARSE_TAG_SYMLINK)
13+
fMode |= S_IFLNK;
14+
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
1315
fMode |= S_IFDIR;
1416
else
1517
fMode |= S_IFREG;

compat/win32/dirent.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
1616
xwcstoutf(ent->d_name, fdata->cFileName, MAX_PATH * 3);
1717

1818
/* Set file type, based on WIN32_FIND_DATA */
19-
if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
19+
if ((fdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
20+
&& fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
21+
ent->d_type = DT_LNK;
22+
else if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2023
ent->d_type = DT_DIR;
2124
else
2225
ent->d_type = DT_REG;

compat/win32/fscache.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,10 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
149149

150150
fse = fsentry_alloc(list, buf, len);
151151

152-
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes);
153-
fse->st_size = (((off64_t) (fdata->nFileSizeHigh)) << 32)
154-
| fdata->nFileSizeLow;
152+
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes,
153+
fdata->dwReserved0);
154+
fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
155+
fdata->nFileSizeLow | (((off_t) fdata->nFileSizeHigh) << 32);
155156
fse->st_atime = filetime_to_time_t(&(fdata->ftLastAccessTime));
156157
fse->st_mtime = filetime_to_time_t(&(fdata->ftLastWriteTime));
157158
fse->st_ctime = filetime_to_time_t(&(fdata->ftCreationTime));
@@ -442,7 +443,8 @@ static struct dirent *fscache_readdir(DIR *base_dir)
442443
if (!next)
443444
return NULL;
444445
dir->pfsentry = next;
445-
dir->dirent.d_type = S_ISDIR(next->st_mode) ? DT_DIR : DT_REG;
446+
dir->dirent.d_type = S_ISREG(next->st_mode) ? DT_REG :
447+
S_ISDIR(next->st_mode) ? DT_DIR : DT_LNK;
446448
dir->dirent.d_name = (char*) next->name;
447449
return &(dir->dirent);
448450
}

compat/winansi.c

+5-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <wingdi.h>
88
#include <winreg.h>
99
#include "win32.h"
10+
#include "win32/lazyload.h"
1011

1112
static int fd_is_interactive[3] = { 0, 0, 0 };
1213
#define FD_CONSOLE 0x1
@@ -41,26 +42,21 @@ typedef struct _CONSOLE_FONT_INFOEX {
4142
#endif
4243
#endif
4344

44-
typedef BOOL (WINAPI *PGETCURRENTCONSOLEFONTEX)(HANDLE, BOOL,
45-
PCONSOLE_FONT_INFOEX);
46-
4745
static void warn_if_raster_font(void)
4846
{
4947
DWORD fontFamily = 0;
50-
PGETCURRENTCONSOLEFONTEX pGetCurrentConsoleFontEx;
48+
DECLARE_PROC_ADDR(kernel32.dll, BOOL, GetCurrentConsoleFontEx,
49+
HANDLE, BOOL, PCONSOLE_FONT_INFOEX);
5150

5251
/* don't bother if output was ascii only */
5352
if (!non_ascii_used)
5453
return;
5554

5655
/* GetCurrentConsoleFontEx is available since Vista */
57-
pGetCurrentConsoleFontEx = (PGETCURRENTCONSOLEFONTEX) GetProcAddress(
58-
GetModuleHandle("kernel32.dll"),
59-
"GetCurrentConsoleFontEx");
60-
if (pGetCurrentConsoleFontEx) {
56+
if (INIT_PROC_ADDR(GetCurrentConsoleFontEx)) {
6157
CONSOLE_FONT_INFOEX cfi;
6258
cfi.cbSize = sizeof(cfi);
63-
if (pGetCurrentConsoleFontEx(console, 0, &cfi))
59+
if (GetCurrentConsoleFontEx(console, 0, &cfi))
6460
fontFamily = cfi.FontFamily;
6561
} else {
6662
/* pre-Vista: check default console font in registry */

git-compat-util.h

+4
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,10 @@ static inline char *git_find_last_dir_sep(const char *path)
392392
#define find_last_dir_sep git_find_last_dir_sep
393393
#endif
394394

395+
#ifndef query_user_email
396+
#define query_user_email() NULL
397+
#endif
398+
395399
#if defined(__HP_cc) && (__HP_cc >= 61000)
396400
#define NORETURN __attribute__((noreturn))
397401
#define NORETURN_PTR

ident.c

+3
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ const char *ident_default_email(void)
168168
strbuf_addstr(&git_default_email, email);
169169
committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
170170
author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
171+
} else if ((email = query_user_email()) && email[0]) {
172+
strbuf_addstr(&git_default_email, email);
173+
free((char *)email);
171174
} else
172175
copy_email(xgetpwuid_self(&default_email_is_bogus),
173176
&git_default_email, &default_email_is_bogus);

lockfile.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ static void trim_last_path_component(struct strbuf *path)
1717
int i = path->len;
1818

1919
/* back up past trailing slashes, if any */
20-
while (i && path->buf[i - 1] == '/')
20+
while (i && is_dir_sep(path->buf[i - 1]))
2121
i--;
2222

2323
/*
2424
* then go backwards until a slash, or the beginning of the
2525
* string
2626
*/
27-
while (i && path->buf[i - 1] != '/')
27+
while (i && !is_dir_sep(path->buf[i - 1]))
2828
i--;
2929

3030
strbuf_setlen(path, i);

strbuf.c

+3-5
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,6 @@ ssize_t strbuf_write(struct strbuf *sb, FILE *f)
468468
}
469469

470470

471-
#define STRBUF_MAXLINK (2*PATH_MAX)
472-
473471
int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
474472
{
475473
size_t oldalloc = sb->alloc;
@@ -480,12 +478,12 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
480478
while (hint < STRBUF_MAXLINK) {
481479
ssize_t len;
482480

483-
strbuf_grow(sb, hint);
484-
len = readlink(path, sb->buf, hint);
481+
strbuf_grow(sb, hint + 1);
482+
len = readlink(path, sb->buf, hint + 1);
485483
if (len < 0) {
486484
if (errno != ERANGE)
487485
break;
488-
} else if (len < hint) {
486+
} else if (len <= hint) {
489487
strbuf_setlen(sb, len);
490488
return 0;
491489
}

0 commit comments

Comments
 (0)