diff --git a/.gitignore b/.gitignore index 47672b0c15..51a37b1af7 100644 --- a/.gitignore +++ b/.gitignore @@ -179,3 +179,14 @@ configure tags TAGS cscope* +*.obj +*.lib +*.sln +*.suo +*.ncb +*.vcproj +*.user +*.idb +*.pdb +Debug/ +Release/ diff --git a/.mailmap b/.mailmap index 373476bdc0..975e6758ef 100644 --- a/.mailmap +++ b/.mailmap @@ -41,6 +41,7 @@ Michele Ballabio Nanako Shiraishi Nanako Shiraishi Nguyễn Thái Ngọc Duy + Philippe Bruhat Ramsay Allan Jones René Scharfe diff --git a/Documentation/RelNotes-1.6.4.4.txt b/Documentation/RelNotes-1.6.4.4.txt new file mode 100644 index 0000000000..0ead45fc72 --- /dev/null +++ b/Documentation/RelNotes-1.6.4.4.txt @@ -0,0 +1,26 @@ +GIT v1.6.4.4 Release Notes +========================== + +Fixes since v1.6.4.4 +-------------------- + +* The workaround for Github server that sometimes gave 500 (Internal server + error) response to HEAD requests in 1.6.4.3 introduced a regression that + caused re-fetching projects over http to segfault in certain cases due + to uninitialized pointer being freed. + +* "git pull" on an unborn branch used to consider anything in the work + tree and the index discardable. + +* "git diff -b/w" did not work well on the incomplete line at the end of + the file, due to an incorrect hashing of lines in the low-level xdiff + routines. + +* "git checkout-index --prefix=$somewhere" used to work when $somewhere is + a symbolic link to a directory elsewhere, but v1.6.4.2 broke it. + +* "git unpack-objects --strict", invoked when receive.fsckobjects + configuration is set in the receiving repository of "git push", did not + properly check the objects, especially the submodule links, it received. + +Other minor documentation updates are included. diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt index 92444ddf10..3d1c1e75b7 100644 --- a/Documentation/git-archive.txt +++ b/Documentation/git-archive.txt @@ -10,7 +10,7 @@ SYNOPSIS -------- [verse] 'git archive' [--format=] [--list] [--prefix=/] [] - [--output=] [--worktree-attributes] + [-o | --output=] [--worktree-attributes] [--remote= [--exec=]] [path...] @@ -34,8 +34,11 @@ OPTIONS ------- --format=:: - Format of the resulting archive: 'tar' or 'zip'. The default - is 'tar'. + Format of the resulting archive: 'tar' or 'zip'. If this option + is not given, and the output file is specified, the format is + inferred from the filename if possible (e.g. writing to "foo.zip" + makes the output to be in the zip format). Otherwise the output + format is `tar`. -l:: --list:: @@ -48,6 +51,7 @@ OPTIONS --prefix=/:: Prepend / to each filename in the archive. +-o :: --output=:: Write the archive to instead of stdout. @@ -129,6 +133,12 @@ git archive --format=zip --prefix=git-docs/ HEAD:Documentation/ > git-1.4.0-docs Put everything in the current head's Documentation/ directory into 'git-1.4.0-docs.zip', with the prefix 'git-docs/'. +git archive -o latest.zip HEAD:: + + Create a Zip archive that contains the contents of the latest + commit on the current branch. Note that the output format is + inferred by the extension of the output file. + SEE ALSO -------- diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index f23100e509..aacf4fd327 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -130,7 +130,7 @@ objects from the source repository into a pack in the cloned repository. --branch :: -b :: Instead of pointing the newly created HEAD to the branch pointed - to by the cloned repositoroy's HEAD, point to branch + to by the cloned repository's HEAD, point to branch instead. In a non-bare repository, this is the branch that will be checked out. diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 64f94cfe12..0578a40d84 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git commit' [-a | --interactive] [-s] [-v] [-u] [--amend] [--dry-run] - [(-c | -C) ] [-F | -m ] [--dry-run] + [(-c | -C) ] [-F | -m ] [--allow-empty] [--no-verify] [-e] [--author=] [--cleanup=] [--] [[-i | -o ]...] @@ -69,12 +69,6 @@ OPTIONS Like '-C', but with '-c' the editor is invoked, so that the user can further edit the commit message. ---dry-run:: - Do not actually make a commit, but show the list of paths - with updates in the index, paths with changes in the work tree, - and paths that are untracked, similar to the one that is given - in the commit log editor. - -F :: --file=:: Take the commit message from the given file. Use '-' to diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index 58d2bd5d4a..ba6a8a2fb2 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects SYNOPSIS -------- [verse] -'git push' [--all | --mirror | --tags] [--dry-run] [--receive-pack=] +'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=] [--repo=] [-f | --force] [-v | --verbose] [ ...] @@ -82,6 +82,7 @@ nor in any Push line of the corresponding remotes file---see below). if the configuration option `remote..mirror` is set. +-n:: --dry-run:: Do everything except actually send the updates. diff --git a/Documentation/git.txt b/Documentation/git.txt index f91cabb4ce..20b573e37c 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.6.4.3/git.html[documentation for release 1.6.4.3] +* link:v1.6.4.4/git.html[documentation for release 1.6.4.4] * release notes for + link:RelNotes-1.6.4.4.txt[1.6.4.4], link:RelNotes-1.6.4.3.txt[1.6.4.3], link:RelNotes-1.6.4.2.txt[1.6.4.2], link:RelNotes-1.6.4.1.txt[1.6.4.1], diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt index 79f633e837..06e0f315c3 100644 --- a/Documentation/githooks.txt +++ b/Documentation/githooks.txt @@ -245,7 +245,7 @@ Both standard output and standard error output are forwarded to for the user. The default 'update' hook, when enabled--and with -`hooks.allowunannotated` config option turned on--prevents +`hooks.allowunannotated` config option unset or set to false--prevents unannotated tags to be pushed. [[post-receive]] diff --git a/Makefile b/Makefile index d4958b832a..12defd4c97 100644 --- a/Makefile +++ b/Makefile @@ -876,6 +876,59 @@ ifneq (,$(findstring CYGWIN,$(uname_S))) COMPAT_OBJS += compat/cygwin.o UNRELIABLE_FSTAT = UnfortunatelyYes endif +ifdef MSVC + GIT_VERSION := $(GIT_VERSION).MSVC + pathsep = ; + NO_PREAD = YesPlease + NO_OPENSSL = YesPlease + NO_LIBGEN_H = YesPlease + NO_SYMLINK_HEAD = YesPlease + NO_IPV6 = YesPlease + NO_SETENV = YesPlease + NO_UNSETENV = YesPlease + NO_STRCASESTR = YesPlease + NO_STRLCPY = YesPlease + NO_MEMMEM = YesPlease + # NEEDS_LIBICONV = YesPlease + NO_ICONV = YesPlease + NO_C99_FORMAT = YesPlease + NO_STRTOUMAX = YesPlease + NO_STRTOULL = YesPlease + NO_MKDTEMP = YesPlease + NO_MKSTEMPS = YesPlease + SNPRINTF_RETURNS_BOGUS = YesPlease + NO_SVN_TESTS = YesPlease + NO_PERL_MAKEMAKER = YesPlease + RUNTIME_PREFIX = YesPlease + NO_POSIX_ONLY_PROGRAMS = YesPlease + NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease + NO_NSEC = YesPlease + USE_WIN32_MMAP = YesPlease + # USE_NED_ALLOCATOR = YesPlease + UNRELIABLE_FSTAT = UnfortunatelyYes + OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo + NO_REGEX = YesPlease + NO_CURL = YesPlease + NO_PTHREADS = YesPlease + + CC = compat/vcbuild/scripts/clink.pl + AR = compat/vcbuild/scripts/lib.pl + CFLAGS = + BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32-D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE + COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o + COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -DSTRIP_EXTENSION=\".exe\" + BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib + EXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib + lib = +ifndef DEBUG + BASIC_CFLAGS += -GL -Os -MT + BASIC_LDFLAGS += -LTCG + AR += -LTCG +else + BASIC_CFLAGS += -Zi -MTd +endif + X = .exe +else ifneq (,$(findstring MINGW,$(uname_S))) pathsep = ; NO_PREAD = YesPlease @@ -924,6 +977,7 @@ else NO_PTHREADS = YesPlease endif endif +endif -include config.mak.autogen -include config.mak @@ -1326,7 +1380,7 @@ strip: $(PROGRAMS) git$X git.o: git.c common-cmds.h GIT-CFLAGS $(QUIET_CC)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ '-DGIT_HTML_PATH="$(htmldir_SQ)"' \ - $(ALL_CFLAGS) -c $(filter %.c,$^) + $(ALL_CFLAGS) -o $@ -c $(filter %.c,$^) git$X: git.o $(BUILTIN_OBJS) $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \ diff --git a/archive.c b/archive.c index 0bca9ca403..73b8e8a56d 100644 --- a/archive.c +++ b/archive.c @@ -283,7 +283,7 @@ static int parse_archive_args(int argc, const char **argv, OPT_STRING(0, "format", &format, "fmt", "archive format"), OPT_STRING(0, "prefix", &base, "prefix", "prepend prefix to each pathname in the archive"), - OPT_STRING(0, "output", &output, "file", + OPT_STRING('o', "output", &output, "file", "write the archive to this file"), OPT_BOOLEAN(0, "worktree-attributes", &worktree_attributes, "read .gitattributes in working directory"), diff --git a/builtin-archive.c b/builtin-archive.c index f9a4bea41e..12351e9dd5 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -60,6 +60,17 @@ static int run_remote_archiver(int argc, const char **argv, return !!rv; } +static const char *format_from_name(const char *filename) +{ + const char *ext = strrchr(filename, '.'); + if (!ext) + return NULL; + ext++; + if (!strcasecmp(ext, "zip")) + return "zip"; + return NULL; +} + #define PARSE_OPT_KEEP_ALL ( PARSE_OPT_KEEP_DASHDASH | \ PARSE_OPT_KEEP_ARGV0 | \ PARSE_OPT_KEEP_UNKNOWN | \ @@ -70,21 +81,39 @@ int cmd_archive(int argc, const char **argv, const char *prefix) const char *exec = "git-upload-archive"; const char *output = NULL; const char *remote = NULL; + const char *format = NULL; struct option local_opts[] = { - OPT_STRING(0, "output", &output, "file", + OPT_STRING('o', "output", &output, "file", "write the archive to this file"), OPT_STRING(0, "remote", &remote, "repo", "retrieve the archive from remote repository "), OPT_STRING(0, "exec", &exec, "cmd", "path to the remote git-upload-archive command"), + OPT_STRING(0, "format", &format, "fmt", "archive format"), OPT_END() }; + char fmt_opt[32]; argc = parse_options(argc, argv, prefix, local_opts, NULL, PARSE_OPT_KEEP_ALL); - if (output) + if (output) { create_output_file(output); + if (!format) + format = format_from_name(output); + } + + if (format) { + sprintf(fmt_opt, "--format=%s", format); + /* + * This is safe because either --format and/or --output must + * have been given on the original command line if we get to + * this point, and parse_options() must have eaten at least + * one argument, i.e. we have enough room to append to argv[]. + */ + argv[argc++] = fmt_opt; + argv[argc] = NULL; + } if (remote) return run_remote_archiver(argc, argv, remote, exec); diff --git a/builtin-bundle.c b/builtin-bundle.c index 9b58152047..2006cc5cd5 100644 --- a/builtin-bundle.c +++ b/builtin-bundle.c @@ -9,7 +9,11 @@ * bundle supporting "fetch", "pull", and "ls-remote". */ -static const char *bundle_usage="git bundle (create | verify | list-heads [refname]... | unbundle [refname]... )"; +static const char builtin_bundle_usage[] = + "git bundle create \n" + " or: git bundle verify \n" + " or: git bundle list-heads [refname...]\n" + " or: git bundle unbundle [refname...]"; int cmd_bundle(int argc, const char **argv, const char *prefix) { @@ -20,7 +24,7 @@ int cmd_bundle(int argc, const char **argv, const char *prefix) char buffer[PATH_MAX]; if (argc < 3) - usage(bundle_usage); + usage(builtin_bundle_usage); cmd = argv[1]; bundle_file = argv[2]; @@ -59,5 +63,5 @@ int cmd_bundle(int argc, const char **argv, const char *prefix) return !!unbundle(&header, bundle_fd) || list_bundle_refs(&header, argc, argv); } else - usage(bundle_usage); + usage(builtin_bundle_usage); } diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 7a390e1d44..02f9246cdb 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -22,15 +22,15 @@ #include #endif -static const char pack_usage[] = "\ -git pack-objects [{ -q | --progress | --all-progress }] \n\ - [--max-pack-size=N] [--local] [--incremental] \n\ - [--window=N] [--window-memory=N] [--depth=N] \n\ - [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\ - [--threads=N] [--non-empty] [--revs [--unpacked | --all]*] [--reflog] \n\ - [--stdout | base-name] [--include-tag] \n\ - [--keep-unreachable | --unpack-unreachable] \n\ - [] [--repo=] [-f | --force] [-v] [ ...]", + "git push [--all | --mirror] [-n | --dry-run] [--porcelain] [--tags] [--receive-pack=] [--repo=] [-f | --force] [-v] [ ...]", NULL, }; @@ -182,7 +182,7 @@ int cmd_push(int argc, const char **argv, const char *prefix) OPT_BIT( 0 , "mirror", &flags, "mirror all refs", (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)), OPT_BOOLEAN( 0 , "tags", &tags, "push tags"), - OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN), + OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN), OPT_BIT( 0, "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN), OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE), OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"), diff --git a/compat/mingw.c b/compat/mingw.c index 36ef8d3214..6b5b5b2c70 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -3,7 +3,7 @@ #include #include "../strbuf.h" -unsigned int _CRT_fmode = _O_BINARY; +#include static int err_win_to_posix(DWORD winerr) { @@ -123,13 +123,17 @@ int mingw_open (const char *filename, int oflags, ...) { va_list args; unsigned mode; + int fd; + va_start(args, oflags); mode = va_arg(args, int); va_end(args); if (!strcmp(filename, "/dev/null")) filename = "nul"; - int fd = open(filename, oflags, mode); + + fd = open(filename, oflags, mode); + if (fd < 0 && (oflags & O_CREAT) && errno == EACCES) { DWORD attrs = GetFileAttributes(filename); if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)) @@ -580,10 +584,11 @@ static char **get_path_split(void) static void free_path_split(char **path) { + char **p = path; + if (!path) return; - char **p = path; while (*p) free(*p++); free(path); @@ -1024,7 +1029,7 @@ static sig_handler_t timer_fn = SIG_DFL; * length to call the signal handler. */ -static __stdcall unsigned ticktack(void *dummy) +static unsigned __stdcall ticktack(void *dummy) { while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) { if (timer_fn == SIG_DFL) @@ -1120,9 +1125,9 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out) #undef signal sig_handler_t mingw_signal(int sig, sig_handler_t handler) { + sig_handler_t old = timer_fn; if (sig != SIGALRM) return signal(sig, handler); - sig_handler_t old = timer_fn; timer_fn = handler; return old; } @@ -1151,7 +1156,7 @@ void mingw_open_html(const char *unixpath) int link(const char *oldpath, const char *newpath) { - typedef BOOL WINAPI (*T)(const char*, const char*, LPSECURITY_ATTRIBUTES); + typedef BOOL (WINAPI *T)(const char*, const char*, LPSECURITY_ATTRIBUTES); static T create_hard_link = NULL; if (!create_hard_link) { create_hard_link = (T) GetProcAddress( @@ -1209,8 +1214,9 @@ struct dirent *mingw_readdir(DIR *dir) if (dir->dd_handle == (long)INVALID_HANDLE_VALUE && dir->dd_stat == 0) { + DWORD lasterr; handle = FindFirstFileA(dir->dd_name, &buf); - DWORD lasterr = GetLastError(); + lasterr = GetLastError(); dir->dd_handle = (long)handle; if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES)) { errno = err_win_to_posix(lasterr); diff --git a/compat/mingw.h b/compat/mingw.h index c43917cd6e..5b5258bceb 100644 --- a/compat/mingw.h +++ b/compat/mingw.h @@ -41,6 +41,7 @@ struct passwd { extern char *getpass(const char *prompt); +#ifndef POLLIN struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ @@ -48,6 +49,7 @@ struct pollfd { }; #define POLLIN 1 #define POLLHUP 2 +#endif typedef void (__cdecl *sig_handler_t)(int); struct sigaction { @@ -227,12 +229,17 @@ void free_environ(char **env); /* * A replacement of main() that ensures that argv[0] has a path + * and that default fmode and std(in|out|err) are in binary mode */ #define main(c,v) dummy_decl_mingw_main(); \ static int mingw_main(); \ int main(int argc, const char **argv) \ { \ + _fmode = _O_BINARY; \ + _setmode(_fileno(stdin), _O_BINARY); \ + _setmode(_fileno(stdout), _O_BINARY); \ + _setmode(_fileno(stderr), _O_BINARY); \ argv[0] = xstrdup(_pgmptr); \ return mingw_main(argc, argv); \ } \ diff --git a/compat/msvc.c b/compat/msvc.c new file mode 100644 index 0000000000..ac04a4ccbd --- /dev/null +++ b/compat/msvc.c @@ -0,0 +1,35 @@ +#include "../git-compat-util.h" +#include "win32.h" +#include +#include "../strbuf.h" + +DIR *opendir(const char *name) +{ + int len; + DIR *p; + p = (DIR*)malloc(sizeof(DIR)); + memset(p, 0, sizeof(DIR)); + strncpy(p->dd_name, name, PATH_MAX); + len = strlen(p->dd_name); + p->dd_name[len] = '/'; + p->dd_name[len+1] = '*'; + + if (p == NULL) + return NULL; + + p->dd_handle = _findfirst(p->dd_name, &p->dd_dta); + + if (p->dd_handle == -1) { + free(p); + return NULL; + } + return p; +} +int closedir(DIR *dir) +{ + _findclose(dir->dd_handle); + free(dir); + return 0; +} + +#include "mingw.c" diff --git a/compat/msvc.h b/compat/msvc.h new file mode 100644 index 0000000000..9c753a560f --- /dev/null +++ b/compat/msvc.h @@ -0,0 +1,50 @@ +#ifndef __MSVC__HEAD +#define __MSVC__HEAD + +#include +#include +#include + +/* porting function */ +#define inline __inline +#define __inline__ __inline +#define __attribute__(x) +#define va_copy(dst, src) ((dst) = (src)) +#define strncasecmp _strnicmp +#define ftruncate _chsize + +static __inline int strcasecmp (const char *s1, const char *s2) +{ + int size1 = strlen(s1); + int sisz2 = strlen(s2); + return _strnicmp(s1, s2, sisz2 > size1 ? sisz2 : size1); +} + +#undef ERROR +#undef stat +#undef _stati64 +#include "compat/mingw.h" +#undef stat +#define stat _stati64 +#define _stat64(x,y) mingw_lstat(x,y) + +/* + Even though _stati64 is normally just defined at _stat64 + on Windows, we specify it here as a proper struct to avoid + compiler warnings about macro redefinition due to magic in + mingw.h. Struct taken from ReactOS (GNU GPL license). +*/ +struct _stati64 { + _dev_t st_dev; + _ino_t st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + _dev_t st_rdev; + __int64 st_size; + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +}; +#endif diff --git a/compat/regex/regex.c b/compat/regex/regex.c index 5ea007567d..67d5c370a0 100644 --- a/compat/regex/regex.c +++ b/compat/regex/regex.c @@ -4852,11 +4852,8 @@ regexec (preg, string, nmatch, pmatch, eflags) from either regcomp or regexec. We don't use PREG here. */ size_t -regerror (errcode, preg, errbuf, errbuf_size) - int errcode; - const regex_t *preg; - char *errbuf; - size_t errbuf_size; +regerror(int errcode, const regex_t *preg, + char *errbuf, size_t errbuf_size) { const char *msg; size_t msg_size; diff --git a/compat/snprintf.c b/compat/snprintf.c index 4d07087abd..e1e0e7543d 100644 --- a/compat/snprintf.c +++ b/compat/snprintf.c @@ -2,12 +2,14 @@ /* * The size parameter specifies the available space, i.e. includes - * the trailing NUL byte; but Windows's vsnprintf expects the - * number of characters to write, and does not necessarily write the - * trailing NUL. + * the trailing NUL byte; but Windows's vsnprintf uses the entire + * buffer and avoids the trailing NUL, should the buffer be exactly + * big enough for the result. Defining SNPRINTF_SIZE_CORR to 1 will + * therefore remove 1 byte from the reported buffer size, so we + * always have room for a trailing NUL byte. */ #ifndef SNPRINTF_SIZE_CORR -#if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ < 4 +#if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) #define SNPRINTF_SIZE_CORR 1 #else #define SNPRINTF_SIZE_CORR 0 diff --git a/compat/vcbuild/README b/compat/vcbuild/README new file mode 100644 index 0000000000..df8a6574c9 --- /dev/null +++ b/compat/vcbuild/README @@ -0,0 +1,50 @@ +The Steps of Build Git with VS2008 + +1. You need the build environment, which contains the Git dependencies + to be able to compile, link and run Git with MSVC. + + You can either use the binary repository: + + WWW: http://repo.or.cz/w/msvcgit.git + Git: git clone git://repo.or.cz/msvcgit.git + Zip: http://repo.or.cz/w/msvcgit.git?a=snapshot;h=master;sf=zip + + and call the setup_32bit_env.cmd batch script before compiling Git, + (see repo/package README for details), or the source repository: + + WWW: http://repo.or.cz/w/gitbuild.git + Git: git clone git://repo.or.cz/gitbuild.git + Zip: (None, as it's a project with submodules) + + and build the support libs as instructed in that repo/package. + +2. Ensure you have the msysgit environment in your path, so you have + GNU Make, bash and perl available. + + WWW: http://repo.or.cz/w/msysgit.git + Git: git clone git://repo.or.cz/msysgit.git + Zip: http://repo.or.cz/w/msysgit.git?a=snapshot;h=master;sf=zip + + This environment is also needed when you use the resulting + executables, since Git might need to run scripts which are part of + the git operations. + +3. Inside Git's directory run the command: + make common-cmds.h + to generate the common-cmds.h file needed to compile git. + +4. Then either build Git with the GNU Make Makefile in the Git projects + root + make MSVC=1 + or generate Visual Studio solution/projects (.sln/.vcproj) with the + command + perl contrib/buildsystems/generate -g Vcproj + and open and build the solution with the IDE + devenv git.sln /useenv + or build with the IDE build engine directly from the command line + devenv git.sln /useenv /build "Release|Win32" + The /useenv option is required, so Visual Studio picks up the + environment variables for the support libraries required to build + Git, which you set up in step 1. + +Done! diff --git a/compat/vcbuild/include/alloca.h b/compat/vcbuild/include/alloca.h new file mode 100644 index 0000000000..c0d7985b7e --- /dev/null +++ b/compat/vcbuild/include/alloca.h @@ -0,0 +1 @@ +#include diff --git a/compat/vcbuild/include/arpa/inet.h b/compat/vcbuild/include/arpa/inet.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/arpa/inet.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/dirent.h b/compat/vcbuild/include/dirent.h new file mode 100644 index 0000000000..440618db0d --- /dev/null +++ b/compat/vcbuild/include/dirent.h @@ -0,0 +1,128 @@ +/* + * DIRENT.H (formerly DIRLIB.H) + * This file has no copyright assigned and is placed in the Public Domain. + * This file is a part of the mingw-runtime package. + * + * The mingw-runtime package and its code is distributed in the hope that it + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You are free to use this package and its code without limitation. + */ +#ifndef _DIRENT_H_ +#define _DIRENT_H_ +#include + +#define PATH_MAX 512 + +#define __MINGW_NOTHROW + +#ifndef RC_INVOKED + +#ifdef __cplusplus +extern "C" { +#endif + +struct dirent +{ + long d_ino; /* Always zero. */ + unsigned short d_reclen; /* Always zero. */ + unsigned short d_namlen; /* Length of name in d_name. */ + char d_name[FILENAME_MAX]; /* File name. */ +}; + +/* + * This is an internal data structure. Good programmers will not use it + * except as an argument to one of the functions below. + * dd_stat field is now int (was short in older versions). + */ +typedef struct +{ + /* disk transfer area for this dir */ + struct _finddata_t dd_dta; + + /* dirent struct to return from dir (NOTE: this makes this thread + * safe as long as only one thread uses a particular DIR struct at + * a time) */ + struct dirent dd_dir; + + /* _findnext handle */ + long dd_handle; + + /* + * Status of search: + * 0 = not started yet (next entry to read is first entry) + * -1 = off the end + * positive = 0 based index of next entry + */ + int dd_stat; + + /* given path for dir with search pattern (struct is extended) */ + char dd_name[PATH_MAX+3]; +} DIR; + +DIR* __cdecl __MINGW_NOTHROW opendir (const char*); +struct dirent* __cdecl __MINGW_NOTHROW readdir (DIR*); +int __cdecl __MINGW_NOTHROW closedir (DIR*); +void __cdecl __MINGW_NOTHROW rewinddir (DIR*); +long __cdecl __MINGW_NOTHROW telldir (DIR*); +void __cdecl __MINGW_NOTHROW seekdir (DIR*, long); + + +/* wide char versions */ + +struct _wdirent +{ + long d_ino; /* Always zero. */ + unsigned short d_reclen; /* Always zero. */ + unsigned short d_namlen; /* Length of name in d_name. */ + wchar_t d_name[FILENAME_MAX]; /* File name. */ +}; + +/* + * This is an internal data structure. Good programmers will not use it + * except as an argument to one of the functions below. + */ +typedef struct +{ + /* disk transfer area for this dir */ + //struct _wfinddata_t dd_dta; + + /* dirent struct to return from dir (NOTE: this makes this thread + * safe as long as only one thread uses a particular DIR struct at + * a time) */ + struct _wdirent dd_dir; + + /* _findnext handle */ + long dd_handle; + + /* + * Status of search: + * 0 = not started yet (next entry to read is first entry) + * -1 = off the end + * positive = 0 based index of next entry + */ + int dd_stat; + + /* given path for dir with search pattern (struct is extended) */ + wchar_t dd_name[1]; +} _WDIR; + + + +_WDIR* __cdecl __MINGW_NOTHROW _wopendir (const wchar_t*); +struct _wdirent* __cdecl __MINGW_NOTHROW _wreaddir (_WDIR*); +int __cdecl __MINGW_NOTHROW _wclosedir (_WDIR*); +void __cdecl __MINGW_NOTHROW _wrewinddir (_WDIR*); +long __cdecl __MINGW_NOTHROW _wtelldir (_WDIR*); +void __cdecl __MINGW_NOTHROW _wseekdir (_WDIR*, long); + + +#ifdef __cplusplus +} +#endif + +#endif /* Not RC_INVOKED */ + +#endif /* Not _DIRENT_H_ */ diff --git a/compat/vcbuild/include/grp.h b/compat/vcbuild/include/grp.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/grp.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/inttypes.h b/compat/vcbuild/include/inttypes.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/inttypes.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/netdb.h b/compat/vcbuild/include/netdb.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/netdb.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/netinet/in.h b/compat/vcbuild/include/netinet/in.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/netinet/in.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/netinet/tcp.h b/compat/vcbuild/include/netinet/tcp.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/netinet/tcp.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/pwd.h b/compat/vcbuild/include/pwd.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/pwd.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/sys/ioctl.h b/compat/vcbuild/include/sys/ioctl.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/sys/ioctl.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/sys/param.h b/compat/vcbuild/include/sys/param.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/sys/param.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/sys/poll.h b/compat/vcbuild/include/sys/poll.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/sys/poll.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/sys/select.h b/compat/vcbuild/include/sys/select.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/sys/select.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/sys/socket.h b/compat/vcbuild/include/sys/socket.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/sys/socket.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/sys/time.h b/compat/vcbuild/include/sys/time.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/sys/time.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/sys/utime.h b/compat/vcbuild/include/sys/utime.h new file mode 100644 index 0000000000..582589c70a --- /dev/null +++ b/compat/vcbuild/include/sys/utime.h @@ -0,0 +1,34 @@ +#ifndef _UTIME_H_ +#define _UTIME_H_ +/* + * UTIME.H + * This file has no copyright assigned and is placed in the Public Domain. + * This file is a part of the mingw-runtime package. + * + * The mingw-runtime package and its code is distributed in the hope that it + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You are free to use this package and its code without limitation. + */ + +/* + * Structure used by _utime function. + */ +struct _utimbuf +{ + time_t actime; /* Access time */ + time_t modtime; /* Modification time */ +}; + +#ifndef _NO_OLDNAMES +/* NOTE: Must be the same as _utimbuf above. */ +struct utimbuf +{ + time_t actime; + time_t modtime; +}; +#endif /* Not _NO_OLDNAMES */ + +#endif diff --git a/compat/vcbuild/include/sys/wait.h b/compat/vcbuild/include/sys/wait.h new file mode 100644 index 0000000000..0d8552a2c6 --- /dev/null +++ b/compat/vcbuild/include/sys/wait.h @@ -0,0 +1 @@ +/* Intentionally empty file to support building git with MSVC */ diff --git a/compat/vcbuild/include/unistd.h b/compat/vcbuild/include/unistd.h new file mode 100644 index 0000000000..2a4f276869 --- /dev/null +++ b/compat/vcbuild/include/unistd.h @@ -0,0 +1,92 @@ +#ifndef _UNISTD_ +#define _UNISTD_ + +/* Win32 define for porting git*/ + +#ifndef _MODE_T_ +#define _MODE_T_ +typedef unsigned short _mode_t; + +#ifndef _NO_OLDNAMES +typedef _mode_t mode_t; +#endif +#endif /* Not _MODE_T_ */ + +#ifndef _SSIZE_T_ +#define _SSIZE_T_ +typedef long _ssize_t; + +#ifndef _OFF_T_ +#define _OFF_T_ +typedef long _off_t; + +#ifndef _NO_OLDNAMES +typedef _off_t off_t; +#endif +#endif /* Not _OFF_T_ */ + + +#ifndef _NO_OLDNAMES +typedef _ssize_t ssize_t; +#endif +#endif /* Not _SSIZE_T_ */ + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; + +typedef long long intmax_t; +typedef unsigned long long uintmax_t; + +typedef int64_t off64_t; + +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +/* Some defines for _access nAccessMode (MS doesn't define them, but + * it doesn't seem to hurt to add them). */ +#define F_OK 0 /* Check for file existence */ +/* Well maybe it does hurt. On newer versions of MSVCRT, an access mode + of 1 causes invalid parameter error. */ +#define X_OK 0 /* MS access() doesn't check for execute permission. */ +#define W_OK 2 /* Check for write permission */ +#define R_OK 4 /* Check for read permission */ + +#define _S_IFIFO 0x1000 /* FIFO */ +#define _S_IFCHR 0x2000 /* Character */ +#define _S_IFBLK 0x3000 /* Block: Is this ever set under w32? */ +#define _S_IFDIR 0x4000 /* Directory */ +#define _S_IFREG 0x8000 /* Regular */ + +#define _S_IFMT 0xF000 /* File type mask */ + +#define _S_IXUSR _S_IEXEC +#define _S_IWUSR _S_IWRITE +#define _S_IRUSR _S_IREAD +#define _S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) + +#define S_IFIFO _S_IFIFO +#define S_IFCHR _S_IFCHR +#define S_IFBLK _S_IFBLK +#define S_IFDIR _S_IFDIR +#define S_IFREG _S_IFREG +#define S_IFMT _S_IFMT +#define S_IEXEC _S_IEXEC +#define S_IWRITE _S_IWRITE +#define S_IREAD _S_IREAD +#define S_IRWXU _S_IRWXU +#define S_IXUSR _S_IXUSR +#define S_IWUSR _S_IWUSR +#define S_IRUSR _S_IRUSR + + +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) + +#endif diff --git a/compat/vcbuild/include/utime.h b/compat/vcbuild/include/utime.h new file mode 100644 index 0000000000..8285f38fde --- /dev/null +++ b/compat/vcbuild/include/utime.h @@ -0,0 +1 @@ +#include diff --git a/compat/vcbuild/scripts/clink.pl b/compat/vcbuild/scripts/clink.pl new file mode 100644 index 0000000000..0ffd59f9fb --- /dev/null +++ b/compat/vcbuild/scripts/clink.pl @@ -0,0 +1,48 @@ +#!/usr/bin/perl -w +###################################################################### +# Compiles or links files +# +# This is a wrapper to facilitate the compilation of Git with MSVC +# using GNU Make as the build system. So, instead of manipulating the +# Makefile into something nasty, just to support non-space arguments +# etc, we use this wrapper to fix the command line options +# +# Copyright (C) 2009 Marius Storm-Olsen +###################################################################### +use strict; +my @args = (); +my @cflags = (); +my $is_linking = 0; +while (@ARGV) { + my $arg = shift @ARGV; + if ("$arg" =~ /^-[DIMGO]/) { + push(@cflags, $arg); + } elsif ("$arg" eq "-o") { + my $file_out = shift @ARGV; + if ("$file_out" =~ /exe$/) { + $is_linking = 1; + push(@args, "-OUT:$file_out"); + } else { + push(@args, "-Fo$file_out"); + } + } elsif ("$arg" eq "-lz") { + push(@args, "zlib.lib"); + } elsif ("$arg" eq "-liconv") { + push(@args, "iconv.lib"); + } elsif ("$arg" =~ /^-L/ && "$arg" ne "-LTCG") { + $arg =~ s/^-L/-LIBPATH:/; + push(@args, $arg); + } elsif ("$arg" =~ /^-R/) { + # eat + } else { + push(@args, $arg); + } +} +if ($is_linking) { + unshift(@args, "link.exe"); +} else { + unshift(@args, "cl.exe"); + push(@args, @cflags); +} +#printf("**** @args\n"); +exit system(@args); diff --git a/compat/vcbuild/scripts/lib.pl b/compat/vcbuild/scripts/lib.pl new file mode 100644 index 0000000000..68f66446ea --- /dev/null +++ b/compat/vcbuild/scripts/lib.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl -w +###################################################################### +# Libifies files on Windows +# +# This is a wrapper to facilitate the compilation of Git with MSVC +# using GNU Make as the build system. So, instead of manipulating the +# Makefile into something nasty, just to support non-space arguments +# etc, we use this wrapper to fix the command line options +# +# Copyright (C) 2009 Marius Storm-Olsen +###################################################################### +use strict; +my @args = (); +while (@ARGV) { + my $arg = shift @ARGV; + if ("$arg" eq "rcs") { + # Consume the rcs option + } elsif ("$arg" =~ /\.a$/) { + push(@args, "-OUT:$arg"); + } else { + push(@args, $arg); + } +} +unshift(@args, "lib.exe"); +# printf("**** @args\n"); +exit system(@args); diff --git a/compat/win32.h b/compat/win32.h index c26384e595..8ce91048de 100644 --- a/compat/win32.h +++ b/compat/win32.h @@ -1,5 +1,10 @@ +#ifndef WIN32_H +#define WIN32_H + /* common Win32 functions for MinGW and Cygwin */ +#ifndef WIN32 /* Not defined by Cygwin */ #include +#endif static inline int file_attr_to_st_mode (DWORD attr) { @@ -32,3 +37,5 @@ static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fd return ENOENT; } } + +#endif diff --git a/compat/winansi.c b/compat/winansi.c index 9217c24b43..dedce2104e 100644 --- a/compat/winansi.c +++ b/compat/winansi.c @@ -2,7 +2,6 @@ * Copyright 2008 Peter Harris */ -#include #include "../git-compat-util.h" /* diff --git a/contrib/buildsystems/Generators.pm b/contrib/buildsystems/Generators.pm new file mode 100644 index 0000000000..408ef714b8 --- /dev/null +++ b/contrib/buildsystems/Generators.pm @@ -0,0 +1,42 @@ +package Generators; +require Exporter; + +use strict; +use File::Basename; +no strict 'refs'; +use vars qw($VERSION @AVAILABLE); + +our $VERSION = '1.00'; +our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE); +@ISA = qw(Exporter); + +BEGIN { + local(*D); + my $me = $INC{"Generators.pm"}; + die "Couldn't find myself in \@INC, which is required to load the generators!" if ("$me" eq ""); + $me = dirname($me); + if (opendir(D,"$me/Generators")) { + foreach my $gen (readdir(D)) { + next if ($gen =~ /^\.\.?$/); + require "${me}/Generators/$gen"; + $gen =~ s,\.pm,,; + push(@AVAILABLE, $gen); + } + closedir(D); + my $gens = join(', ', @AVAILABLE); + } + + push @EXPORT_OK, qw(available); +} + +sub available { + return @AVAILABLE; +} + +sub generate { + my ($gen, $git_dir, $out_dir, $rel_dir, %build_structure) = @_; + return eval("Generators::${gen}::generate(\$git_dir, \$out_dir, \$rel_dir, \%build_structure)") if grep(/^$gen$/, @AVAILABLE); + die "Generator \"${gen}\" is not available!\nAvailable generators are: @AVAILABLE\n"; +} + +1; diff --git a/contrib/buildsystems/Generators/QMake.pm b/contrib/buildsystems/Generators/QMake.pm new file mode 100644 index 0000000000..ff3b657e61 --- /dev/null +++ b/contrib/buildsystems/Generators/QMake.pm @@ -0,0 +1,189 @@ +package Generators::QMake; +require Exporter; + +use strict; +use vars qw($VERSION); + +our $VERSION = '1.00'; +our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE); +@ISA = qw(Exporter); + +BEGIN { + push @EXPORT_OK, qw(generate); +} + +sub generate { + my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; + + my @libs = @{$build_structure{"LIBS"}}; + foreach (@libs) { + createLibProject($_, $git_dir, $out_dir, $rel_dir, %build_structure); + } + + my @apps = @{$build_structure{"APPS"}}; + foreach (@apps) { + createAppProject($_, $git_dir, $out_dir, $rel_dir, %build_structure); + } + + createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure); + return 0; +} + +sub createLibProject { + my ($libname, $git_dir, $out_dir, $rel_dir, %build_structure) = @_; + print "Generate $libname lib project\n"; + $rel_dir = "../$rel_dir"; + + my $sources = join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"LIBS_${libname}_SOURCES"}}))); + my $defines = join(" \\\n\t", sort(@{$build_structure{"LIBS_${libname}_DEFINES"}})); + my $includes= join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"LIBS_${libname}_INCLUDES"}}))); + my $cflags = join(" ", sort(@{$build_structure{"LIBS_${libname}_CFLAGS"}})); + + my $cflags_debug = $cflags; + $cflags_debug =~ s/-MT/-MTd/; + $cflags_debug =~ s/-O.//; + + my $cflags_release = $cflags; + $cflags_release =~ s/-MTd/-MT/; + + my @tmp = @{$build_structure{"LIBS_${libname}_LFLAGS"}}; + my @tmp2 = (); + foreach (@tmp) { + if (/^-LTCG/) { + } elsif (/^-L/) { + $_ =~ s/^-L/-LIBPATH:$rel_dir\//; + } + push(@tmp2, $_); + } + my $lflags = join(" ", sort(@tmp)); + + my $target = $libname; + $target =~ s/\//_/g; + $defines =~ s/-D//g; + $defines =~ s/"/\\\\"/g; + $includes =~ s/-I//g; + mkdir "$target" || die "Could not create the directory $target for lib project!\n"; + open F, ">$target/$target.pro" || die "Could not open $target/$target.pro for writing!\n"; + print F << "EOM"; +TEMPLATE = lib +TARGET = $target +DESTDIR = $rel_dir + +CONFIG -= qt +CONFIG += static + +QMAKE_CFLAGS = +QMAKE_CFLAGS_RELEASE = $cflags_release +QMAKE_CFLAGS_DEBUG = $cflags_debug +QMAKE_LIBFLAGS = $lflags + +DEFINES += \\ + $defines + +INCLUDEPATH += \\ + $includes + +SOURCES += \\ + $sources +EOM + close F; +} + +sub createAppProject { + my ($appname, $git_dir, $out_dir, $rel_dir, %build_structure) = @_; + print "Generate $appname app project\n"; + $rel_dir = "../$rel_dir"; + + my $sources = join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"APPS_${appname}_SOURCES"}}))); + my $defines = join(" \\\n\t", sort(@{$build_structure{"APPS_${appname}_DEFINES"}})); + my $includes= join(" \\\n\t", sort(map("$rel_dir/$_", @{$build_structure{"APPS_${appname}_INCLUDES"}}))); + my $cflags = join(" ", sort(@{$build_structure{"APPS_${appname}_CFLAGS"}})); + + my $cflags_debug = $cflags; + $cflags_debug =~ s/-MT/-MTd/; + $cflags_debug =~ s/-O.//; + + my $cflags_release = $cflags; + $cflags_release =~ s/-MTd/-MT/; + + my $libs; + foreach (sort(@{$build_structure{"APPS_${appname}_LIBS"}})) { + $_ =~ s/\//_/g; + $libs .= " $_"; + } + my @tmp = @{$build_structure{"APPS_${appname}_LFLAGS"}}; + my @tmp2 = (); + foreach (@tmp) { + # next if ($_ eq "-NODEFAULTLIB:MSVCRT.lib"); + if (/^-LTCG/) { + } elsif (/^-L/) { + $_ =~ s/^-L/-LIBPATH:$rel_dir\//; + } + push(@tmp2, $_); + } + my $lflags = join(" ", sort(@tmp)); + + my $target = $appname; + $target =~ s/\.exe//; + $target =~ s/\//_/g; + $defines =~ s/-D//g; + $defines =~ s/"/\\\\"/g; + $includes =~ s/-I//g; + mkdir "$target" || die "Could not create the directory $target for app project!\n"; + open F, ">$target/$target.pro" || die "Could not open $target/$target.pro for writing!\n"; + print F << "EOM"; +TEMPLATE = app +TARGET = $target +DESTDIR = $rel_dir + +CONFIG -= qt embed_manifest_exe +CONFIG += console + +QMAKE_CFLAGS = +QMAKE_CFLAGS_RELEASE = $cflags_release +QMAKE_CFLAGS_DEBUG = $cflags_debug +QMAKE_LFLAGS = $lflags +LIBS = $libs + +DEFINES += \\ + $defines + +INCLUDEPATH += \\ + $includes + +win32:QMAKE_LFLAGS += -LIBPATH:$rel_dir +else: QMAKE_LFLAGS += -L$rel_dir + +SOURCES += \\ + $sources +EOM + close F; +} + +sub createGlueProject { + my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; + my $libs = join(" \\ \n", map("\t$_|$_.pro", @{$build_structure{"LIBS"}})); + my $apps = join(" \\ \n", map("\t$_|$_.pro", @{$build_structure{"APPS"}})); + $libs =~ s/\.a//g; + $libs =~ s/\//_/g; + $libs =~ s/\|/\//g; + $apps =~ s/\.exe//g; + $apps =~ s/\//_/g; + $apps =~ s/\|/\//g; + + my $filename = $out_dir; + $filename =~ s/.*\/([^\/]+)$/$1/; + $filename =~ s/\/$//; + print "Generate glue project $filename.pro\n"; + open F, ">$filename.pro" || die "Could not open $filename.pro for writing!\n"; + print F << "EOM"; +TEMPLATE = subdirs +CONFIG += ordered +SUBDIRS += \\ +$libs \\ +$apps +EOM + close F; +} + +1; diff --git a/contrib/buildsystems/Generators/Vcproj.pm b/contrib/buildsystems/Generators/Vcproj.pm new file mode 100644 index 0000000000..00ec0c1369 --- /dev/null +++ b/contrib/buildsystems/Generators/Vcproj.pm @@ -0,0 +1,639 @@ +package Generators::Vcproj; +require Exporter; + +use strict; +use vars qw($VERSION); + +our $VERSION = '1.00'; +our(@ISA, @EXPORT, @EXPORT_OK, @AVAILABLE); +@ISA = qw(Exporter); + +BEGIN { + push @EXPORT_OK, qw(generate); +} + +my $guid_index = 0; +my @GUIDS = ( + "{E07B9989-2BF7-4F21-8918-BE22BA467AC3}", + "{278FFB51-0296-4A44-A81A-22B87B7C3592}", + "{7346A2C4-F0FD-444F-9EBE-1AF23B2B5650}", + "{67F421AC-EB34-4D49-820B-3196807B423F}", + "{385DCFE1-CC8C-4211-A451-80FCFC31CA51}", + "{97CC46C5-D2CC-4D26-B634-E75792B79916}", + "{C7CE21FE-6EF8-4012-A5C7-A22BCEDFBA11}", + "{51575134-3FDF-42D1-BABD-3FB12669C6C9}", + "{0AE195E4-9823-4B87-8E6F-20C5614AF2FF}", + "{4B918255-67CA-43BB-A46C-26704B666E6B}", + "{18CCFEEF-C8EE-4CC1-A265-26F95C9F4649}", + "{5D5D90FA-01B7-4973-AFE5-CA88C53AC197}", + "{1F054320-036D-49E1-B384-FB5DF0BC8AC0}", + "{7CED65EE-F2D9-4171-825B-C7D561FE5786}", + "{8D341679-0F07-4664-9A56-3BA0DE88B9BC}", + "{C189FEDC-2957-4BD7-9FA4-7622241EA145}", + "{66844203-1B9F-4C53-9274-164FFF95B847}", + "{E4FEA145-DECC-440D-AEEA-598CF381FD43}", + "{73300A8E-C8AC-41B0-B555-4F596B681BA7}", + "{873FDEB1-D01D-40BF-A1BF-8BBC58EC0F51}", + "{7922C8BE-76C5-4AC6-8BF7-885C0F93B782}", + "{E245D370-308B-4A49-BFC1-1E527827975F}", + "{F6FA957B-66FC-4ED7-B260-E59BBE4FE813}", + "{E6055070-0198-431A-BC49-8DB6CEE770AE}", + "{54159234-C3EB-43DA-906B-CE5DA5C74654}", + "{594CFC35-0B60-46F6-B8EF-9983ACC1187D}", + "{D93FCAB7-1F01-48D2-B832-F761B83231A5}", + "{DBA5E6AC-E7BE-42D3-8703-4E787141526E}", + "{6171953F-DD26-44C7-A3BE-CC45F86FC11F}", + "{9E19DDBE-F5E4-4A26-A2FE-0616E04879B8}", + "{AE81A615-99E3-4885-9CE0-D9CAA193E867}", + "{FBF4067E-1855-4F6C-8BCD-4D62E801A04D}", + "{17007948-6593-4AEB-8106-F7884B4F2C19}", + "{199D4C8D-8639-4DA6-82EF-08668C35DEE0}", + "{E085E50E-C140-4CF3-BE4B-094B14F0DDD6}", + "{00785268-A9CC-4E40-AC29-BAC0019159CE}", + "{4C06F56A-DCDB-46A6-B67C-02339935CF12}", + "{3A62D3FD-519E-4EC9-8171-D2C1BFEA022F}", + "{3A62D3FD-519E-4EC9-8171-D2C1BFEA022F}", + "{9392EB58-D7BA-410B-B1F0-B2FAA6BC89A7}", + "{2ACAB2D5-E0CE-4027-BCA0-D78B2D7A6C66}", + "{86E216C3-43CE-481A-BCB2-BE5E62850635}", + "{FB631291-7923-4B91-9A57-7B18FDBB7A42}", + "{0A176EC9-E934-45B8-B87F-16C7F4C80039}", + "{DF55CA80-46E8-4C53-B65B-4990A23DD444}", + "{3A0F9895-55D2-4710-BE5E-AD7498B5BF44}", + "{294BDC5A-F448-48B6-8110-DD0A81820F8C}", + "{4B9F66E9-FAC9-47AB-B1EF-C16756FBFD06}", + "{72EA49C6-2806-48BD-B81B-D4905102E19C}", + "{5728EB7E-8929-486C-8CD5-3238D060E768}" +); + +sub generate { + my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; + my @libs = @{$build_structure{"LIBS"}}; + foreach (@libs) { + createLibProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure); + } + + my @apps = @{$build_structure{"APPS"}}; + foreach (@apps) { + createAppProject($_, $git_dir, $out_dir, $rel_dir, \%build_structure); + } + + createGlueProject($git_dir, $out_dir, $rel_dir, %build_structure); + return 0; +} + +sub createLibProject { + my ($libname, $git_dir, $out_dir, $rel_dir, $build_structure) = @_; + print "Generate $libname vcproj lib project\n"; + $rel_dir = "..\\$rel_dir"; + $rel_dir =~ s/\//\\/g; + + my $target = $libname; + $target =~ s/\//_/g; + $target =~ s/\.a//; + + my $uuid = $GUIDS[$guid_index]; + $$build_structure{"LIBS_${target}_GUID"} = $uuid; + $guid_index += 1; + + my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"LIBS_${libname}_SOURCES"}})); + my @sources; + foreach (@srcs) { + $_ =~ s/\//\\/g; + push(@sources, $_); + } + my $defines = join(",", sort(@{$$build_structure{"LIBS_${libname}_DEFINES"}})); + my $includes= join(";", sort(map(""$rel_dir\\$_"", @{$$build_structure{"LIBS_${libname}_INCLUDES"}}))); + my $cflags = join(" ", sort(@{$$build_structure{"LIBS_${libname}_CFLAGS"}})); + $cflags =~ s/\"/"/g; + + my $cflags_debug = $cflags; + $cflags_debug =~ s/-MT/-MTd/; + $cflags_debug =~ s/-O.//; + + my $cflags_release = $cflags; + $cflags_release =~ s/-MTd/-MT/; + + my @tmp = @{$$build_structure{"LIBS_${libname}_LFLAGS"}}; + my @tmp2 = (); + foreach (@tmp) { + if (/^-LTCG/) { + } elsif (/^-L/) { + $_ =~ s/^-L/-LIBPATH:$rel_dir\//; + } + push(@tmp2, $_); + } + my $lflags = join(" ", sort(@tmp)); + + $defines =~ s/-D//g; + $defines =~ s/\"/\\"/g; + $defines =~ s/\'//g; + $includes =~ s/-I//g; + mkdir "$target" || die "Could not create the directory $target for lib project!\n"; + open F, ">$target/$target.vcproj" || die "Could not open $target/$target.pro for writing!\n"; + print F << "EOM"; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOM + foreach(@sources) { + print F << "EOM"; + +EOM + } + print F << "EOM"; + + + + + +EOM + close F; +} + +sub createAppProject { + my ($appname, $git_dir, $out_dir, $rel_dir, $build_structure) = @_; + print "Generate $appname vcproj app project\n"; + $rel_dir = "..\\$rel_dir"; + $rel_dir =~ s/\//\\/g; + + my $target = $appname; + $target =~ s/\//_/g; + $target =~ s/\.exe//; + + my $uuid = $GUIDS[$guid_index]; + $$build_structure{"APPS_${target}_GUID"} = $uuid; + $guid_index += 1; + + my @srcs = sort(map("$rel_dir\\$_", @{$$build_structure{"APPS_${appname}_SOURCES"}})); + my @sources; + foreach (@srcs) { + $_ =~ s/\//\\/g; + push(@sources, $_); + } + my $defines = join(",", sort(@{$$build_structure{"APPS_${appname}_DEFINES"}})); + my $includes= join(";", sort(map(""$rel_dir\\$_"", @{$$build_structure{"APPS_${appname}_INCLUDES"}}))); + my $cflags = join(" ", sort(@{$$build_structure{"APPS_${appname}_CFLAGS"}})); + $cflags =~ s/\"/"/g; + + my $cflags_debug = $cflags; + $cflags_debug =~ s/-MT/-MTd/; + $cflags_debug =~ s/-O.//; + + my $cflags_release = $cflags; + $cflags_release =~ s/-MTd/-MT/; + + my $libs; + foreach (sort(@{$$build_structure{"APPS_${appname}_LIBS"}})) { + $_ =~ s/\//_/g; + $libs .= " $_"; + } + my @tmp = @{$$build_structure{"APPS_${appname}_LFLAGS"}}; + my @tmp2 = (); + foreach (@tmp) { + if (/^-LTCG/) { + } elsif (/^-L/) { + $_ =~ s/^-L/-LIBPATH:$rel_dir\//; + } + push(@tmp2, $_); + } + my $lflags = join(" ", sort(@tmp)) . " -LIBPATH:$rel_dir"; + + $defines =~ s/-D//g; + $defines =~ s/\"/\\"/g; + $defines =~ s/\'//g; + $defines =~ s/\\\\/\\/g; + $includes =~ s/-I//g; + mkdir "$target" || die "Could not create the directory $target for lib project!\n"; + open F, ">$target/$target.vcproj" || die "Could not open $target/$target.pro for writing!\n"; + print F << "EOM"; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOM + foreach(@sources) { + print F << "EOM"; + +EOM + } + print F << "EOM"; + + + + + +EOM + close F; +} + +sub createGlueProject { + my ($git_dir, $out_dir, $rel_dir, %build_structure) = @_; + print "Generate solutions file\n"; + $rel_dir = "..\\$rel_dir"; + $rel_dir =~ s/\//\\/g; + my $SLN_HEAD = "Microsoft Visual Studio Solution File, Format Version 10.00\n"; + my $SLN_PRE = "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = "; + my $SLN_POST = "\nEndProject\n"; + + my @libs = @{$build_structure{"LIBS"}}; + my @tmp; + foreach (@libs) { + $_ =~ s/\//_/g; + $_ =~ s/\.a//; + push(@tmp, $_); + } + @libs = @tmp; + + my @apps = @{$build_structure{"APPS"}}; + @tmp = (); + foreach (@apps) { + $_ =~ s/\//_/g; + $_ =~ s/\.exe//; + push(@tmp, $_); + } + @apps = @tmp; + + open F, ">git.sln" || die "Could not open git.sln for writing!\n"; + print F "$SLN_HEAD"; + foreach (@libs) { + my $libname = $_; + my $uuid = $build_structure{"LIBS_${libname}_GUID"}; + print F "$SLN_PRE"; + print F "\"${libname}\", \"${libname}\\${libname}.vcproj\", \"${uuid}\""; + print F "$SLN_POST"; + } + foreach (@apps) { + my $appname = $_; + my $uuid = $build_structure{"APPS_${appname}_GUID"}; + print F "$SLN_PRE"; + print F "\"${appname}\", \"${appname}\\${appname}.vcproj\", \"${uuid}\""; + print F "$SLN_POST"; + } + + print F << "EOM"; +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = Debug|Win32 + ConfigName.1 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution +EOM + foreach (@{$build_structure{"APPS"}}) { + my $appname = $_; + my $appname_clean = $_; + $appname_clean =~ s/\//_/g; + $appname_clean =~ s/\.exe//; + + my $uuid = $build_structure{"APPS_${appname_clean}_GUID"}; + my $dep_index = 0; + foreach(@{$build_structure{"APPS_${appname}_LIBS"}}) { + my $libname = $_; + $libname =~ s/\//_/g; + $libname =~ s/\.(a|lib)//; + my $libuuid = $build_structure{"LIBS_${libname}_GUID"}; + if (defined $libuuid) { + print F "\t\t${uuid}.${dep_index} = ${libuuid}\n"; + $dep_index += 1; + } + } + } + + print F << "EOM"; + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution +EOM + foreach (@libs) { + my $libname = $_; + my $uuid = $build_structure{"LIBS_${libname}_GUID"}; + print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n"; + print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n"; + print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n"; + print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n"; + } + foreach (@apps) { + my $appname = $_; + my $uuid = $build_structure{"APPS_${appname}_GUID"}; + print F "\t\t${uuid}.Debug|Win32.ActiveCfg = Debug|Win32\n"; + print F "\t\t${uuid}.Debug|Win32.Build.0 = Debug|Win32\n"; + print F "\t\t${uuid}.Release|Win32.ActiveCfg = Release|Win32\n"; + print F "\t\t${uuid}.Release|Win32.Build.0 = Release|Win32\n"; + } + + print F << "EOM"; + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal +EOM + close F; +} + +1; diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl new file mode 100644 index 0000000000..20bd061b3e --- /dev/null +++ b/contrib/buildsystems/engine.pl @@ -0,0 +1,353 @@ +#!/usr/bin/perl -w +###################################################################### +# Do not call this script directly! +# +# The generate script ensures that @INC is correct before the engine +# is executed. +# +# Copyright (C) 2009 Marius Storm-Olsen +###################################################################### +use strict; +use File::Basename; +use File::Spec; +use Cwd; +use Generators; + +my (%build_structure, %compile_options, @makedry); +my $out_dir = getcwd(); +my $git_dir = $out_dir; +$git_dir =~ s=\\=/=g; +$git_dir = dirname($git_dir) while (!-e "$git_dir/git.c" && "$git_dir" ne ""); +die "Couldn't find Git repo" if ("$git_dir" eq ""); + +my @gens = Generators::available(); +my $gen = "Vcproj"; + +sub showUsage +{ + my $genlist = join(', ', @gens); + print << "EOM"; +generate usage: + -g --gen Specify the buildsystem generator (default: $gen) + Available: $genlist + -o --out Specify output directory generation (default: .) + -i --in Specify input file, instead of running GNU Make + -h,-? --help This help +EOM + exit 0; +} + +# Parse command-line options +while (@ARGV) { + my $arg = shift @ARGV; + if ("$arg" eq "-h" || "$arg" eq "--help" || "$arg" eq "-?") { + showUsage(); + exit(0); + } elsif("$arg" eq "--out" || "$arg" eq "-o") { + $out_dir = shift @ARGV; + } elsif("$arg" eq "--gen" || "$arg" eq "-g") { + $gen = shift @ARGV; + } elsif("$arg" eq "--in" || "$arg" eq "-i") { + my $infile = shift @ARGV; + open(F, "<$infile") || die "Couldn't open file $infile"; + @makedry = ; + close(F); + } +} + +# NOT using File::Spec->rel2abs($path, $base) here, as +# it fails badly for me in the msysgit environment +$git_dir = File::Spec->rel2abs($git_dir); +$out_dir = File::Spec->rel2abs($out_dir); +my $rel_dir = makeOutRel2Git($git_dir, $out_dir); + +# Print some information so the user feels informed +print << "EOM"; +----- +Generator: $gen +Git dir: $git_dir +Out dir: $out_dir +----- +Running GNU Make to figure out build structure... +EOM + +# Pipe a make --dry-run into a variable, if not already loaded from file +@makedry = `cd $git_dir && make -n MSVC=1 V=1 2>/dev/null` if !@makedry; + +# Parse the make output into usable info +parseMakeOutput(); + +# Finally, ask the generator to start generating.. +Generators::generate($gen, $git_dir, $out_dir, $rel_dir, %build_structure); + +# main flow ends here +# ------------------------------------------------------------------------------------------------- + + +# 1) path: /foo/bar/baz 2) path: /foo/bar/baz 3) path: /foo/bar/baz +# base: /foo/bar/baz/temp base: /foo/bar base: /tmp +# rel: .. rel: baz rel: ../foo/bar/baz +sub makeOutRel2Git +{ + my ($path, $base) = @_; + my $rel; + if ("$path" eq "$base") { + return "."; + } elsif ($base =~ /^$path/) { + # case 1 + my $tmp = $base; + $tmp =~ s/^$path//; + foreach (split('/', $tmp)) { + $rel .= "../" if ("$_" ne ""); + } + } elsif ($path =~ /^$base/) { + # case 2 + $rel = $path; + $rel =~ s/^$base//; + $rel = "./$rel"; + } else { + my $tmp = $base; + foreach (split('/', $tmp)) { + $rel .= "../" if ("$_" ne ""); + } + $rel .= $path; + } + $rel =~ s/\/\//\//g; # simplify + $rel =~ s/\/$//; # don't end with / + return $rel; +} + +sub parseMakeOutput +{ + print "Parsing GNU Make output to figure out build structure...\n"; + my $line = 0; + while (my $text = shift @makedry) { + my $ate_next; + do { + $ate_next = 0; + $line++; + chomp $text; + chop $text if ($text =~ /\r$/); + if ($text =~ /\\$/) { + $text =~ s/\\$//; + $text .= shift @makedry; + $ate_next = 1; + } + } while($ate_next); + + if($text =~ / -c /) { + # compilation + handleCompileLine($text, $line); + + } elsif ($text =~ / -o /) { + # linking executable + handleLinkLine($text, $line); + + } elsif ($text =~ /\.o / && $text =~ /\.a /) { + # libifying + handleLibLine($text, $line); +# +# } elsif ($text =~ /^cp /) { +# # copy file around +# +# } elsif ($text =~ /^rm -f /) { +# # shell command +# +# } elsif ($text =~ /^make[ \[]/) { +# # make output +# +# } elsif ($text =~ /^echo /) { +# # echo to file +# +# } elsif ($text =~ /^if /) { +# # shell conditional +# +# } elsif ($text =~ /^tclsh /) { +# # translation stuff +# +# } elsif ($text =~ /^umask /) { +# # handling boilerplates +# +# } elsif ($text =~ /\$\(\:\)/) { +# # ignore +# +# } elsif ($text =~ /^FLAGS=/) { +# # flags check for dependencies +# +# } elsif ($text =~ /^'\/usr\/bin\/perl' -MError -e/) { +# # perl commands for copying files +# +# } elsif ($text =~ /generate-cmdlist\.sh/) { +# # command for generating list of commands +# +# } elsif ($text =~ /^test / && $text =~ /|| rm -f /) { +# # commands removing executables, if they exist +# +# } elsif ($text =~ /new locations or Tcl/) { +# # command for detecting Tcl/Tk changes +# +# } elsif ($text =~ /mkdir -p/) { +# # command creating path +# +# } elsif ($text =~ /: no custom templates yet/) { +# # whatever +# +# } else { +# print "Unhandled (line: $line): $text\n"; + } + } + +# use Data::Dumper; +# print "Parsed build structure:\n"; +# print Dumper(%build_structure); +} + +# variables for the compilation part of each step +my (@defines, @incpaths, @cflags, @sources); + +sub clearCompileStep +{ + @defines = (); + @incpaths = (); + @cflags = (); + @sources = (); +} + +sub removeDuplicates +{ + my (%dupHash, $entry); + %dupHash = map { $_, 1 } @defines; + @defines = keys %dupHash; + + %dupHash = map { $_, 1 } @incpaths; + @incpaths = keys %dupHash; + + %dupHash = map { $_, 1 } @cflags; + @cflags = keys %dupHash; +} + +sub handleCompileLine +{ + my ($line, $lineno) = @_; + my @parts = split(' ', $line); + my $sourcefile; + shift(@parts); # ignore cmd + while (my $part = shift @parts) { + if ("$part" eq "-o") { + # ignore object file + shift @parts; + } elsif ("$part" eq "-c") { + # ignore compile flag + } elsif ("$part" eq "-c") { + } elsif ($part =~ /^.?-I/) { + push(@incpaths, $part); + } elsif ($part =~ /^.?-D/) { + push(@defines, $part); + } elsif ($part =~ /^-/) { + push(@cflags, $part); + } elsif ($part =~ /\.(c|cc|cpp)$/) { + $sourcefile = $part; + } else { + die "Unhandled compiler option @ line $lineno: $part"; + } + } + @{$compile_options{"${sourcefile}_CFLAGS"}} = @cflags; + @{$compile_options{"${sourcefile}_DEFINES"}} = @defines; + @{$compile_options{"${sourcefile}_INCPATHS"}} = @incpaths; + clearCompileStep(); +} + +sub handleLibLine +{ + my ($line, $lineno) = @_; + my (@objfiles, @lflags, $libout, $part); + # kill cmd and rm 'prefix' + $line =~ s/^rm -f .* && .* rcs //; + my @parts = split(' ', $line); + while ($part = shift @parts) { + if ($part =~ /^-/) { + push(@lflags, $part); + } elsif ($part =~ /\.(o|obj)$/) { + push(@objfiles, $part); + } elsif ($part =~ /\.(a|lib)$/) { + $libout = $part; + $libout =~ s/\.a$//; + } else { + die "Unhandled lib option @ line $lineno: $part"; + } + } +# print "LibOut: '$libout'\nLFlags: @lflags\nOfiles: @objfiles\n"; +# exit(1); + foreach (@objfiles) { + my $sourcefile = $_; + $sourcefile =~ s/\.o/.c/; + push(@sources, $sourcefile); + push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}}); + push(@defines, @{$compile_options{"${sourcefile}_DEFINES"}}); + push(@incpaths, @{$compile_options{"${sourcefile}_INCPATHS"}}); + } + removeDuplicates(); + + push(@{$build_structure{"LIBS"}}, $libout); + @{$build_structure{"LIBS_${libout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_SOURCES", + "_OBJECTS"); + @{$build_structure{"LIBS_${libout}_DEFINES"}} = @defines; + @{$build_structure{"LIBS_${libout}_INCLUDES"}} = @incpaths; + @{$build_structure{"LIBS_${libout}_CFLAGS"}} = @cflags; + @{$build_structure{"LIBS_${libout}_LFLAGS"}} = @lflags; + @{$build_structure{"LIBS_${libout}_SOURCES"}} = @sources; + @{$build_structure{"LIBS_${libout}_OBJECTS"}} = @objfiles; + clearCompileStep(); +} + +sub handleLinkLine +{ + my ($line, $lineno) = @_; + my (@objfiles, @lflags, @libs, $appout, $part); + my @parts = split(' ', $line); + shift(@parts); # ignore cmd + while ($part = shift @parts) { + if ($part =~ /^-IGNORE/) { + push(@lflags, $part); + } elsif ($part =~ /^-[GRIMDO]/) { + # eat compiler flags + } elsif ("$part" eq "-o") { + $appout = shift @parts; + } elsif ("$part" eq "-lz") { + push(@libs, "zlib.lib"); + } elsif ($part =~ /^-/) { + push(@lflags, $part); + } elsif ($part =~ /\.(a|lib)$/) { + $part =~ s/\.a$/.lib/; + push(@libs, $part); + } elsif ($part =~ /\.(o|obj)$/) { + push(@objfiles, $part); + } else { + die "Unhandled lib option @ line $lineno: $part"; + } + } +# print "AppOut: '$appout'\nLFlags: @lflags\nLibs : @libs\nOfiles: @objfiles\n"; +# exit(1); + foreach (@objfiles) { + my $sourcefile = $_; + $sourcefile =~ s/\.o/.c/; + push(@sources, $sourcefile); + push(@cflags, @{$compile_options{"${sourcefile}_CFLAGS"}}); + push(@defines, @{$compile_options{"${sourcefile}_DEFINES"}}); + push(@incpaths, @{$compile_options{"${sourcefile}_INCPATHS"}}); + } + removeDuplicates(); + + removeDuplicates(); + push(@{$build_structure{"APPS"}}, $appout); + @{$build_structure{"APPS_${appout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_LFLAGS", + "_SOURCES", "_OBJECTS", "_LIBS"); + @{$build_structure{"APPS_${appout}_DEFINES"}} = @defines; + @{$build_structure{"APPS_${appout}_INCLUDES"}} = @incpaths; + @{$build_structure{"APPS_${appout}_CFLAGS"}} = @cflags; + @{$build_structure{"APPS_${appout}_LFLAGS"}} = @lflags; + @{$build_structure{"APPS_${appout}_SOURCES"}} = @sources; + @{$build_structure{"APPS_${appout}_OBJECTS"}} = @objfiles; + @{$build_structure{"APPS_${appout}_LIBS"}} = @libs; + clearCompileStep(); +} diff --git a/contrib/buildsystems/generate b/contrib/buildsystems/generate new file mode 100644 index 0000000000..bc10f25ff2 --- /dev/null +++ b/contrib/buildsystems/generate @@ -0,0 +1,29 @@ +#!/usr/bin/perl -w +###################################################################### +# Generate buildsystem files +# +# This script generate buildsystem files based on the output of a +# GNU Make --dry-run, enabling Windows users to develop Git with their +# trusted IDE with native projects. +# +# Note: +# It is not meant as *the* way of building Git with MSVC, but merely a +# convenience. The correct way of building Git with MSVC is to use the +# GNU Make tool to build with the maintained Makefile in the root of +# the project. If you have the msysgit environment installed and +# available in your current console, together with the Visual Studio +# environment you wish to build for, all you have to do is run the +# command: +# make MSVC=1 +# +# Copyright (C) 2009 Marius Storm-Olsen +###################################################################### +use strict; +use File::Basename; +use Cwd; + +my $git_dir = getcwd(); +$git_dir =~ s=\\=/=g; +$git_dir = dirname($git_dir) while (!-e "$git_dir/git.c" && "$git_dir" ne ""); +die "Couldn't find Git repo" if ("$git_dir" eq ""); +exec join(" ", ("PERL5LIB=${git_dir}/contrib/buildsystems ${git_dir}/contrib/buildsystems/engine.pl", @ARGV)); diff --git a/contrib/buildsystems/parse.pl b/contrib/buildsystems/parse.pl new file mode 100644 index 0000000000..c9656ece99 --- /dev/null +++ b/contrib/buildsystems/parse.pl @@ -0,0 +1,228 @@ +#!/usr/bin/perl -w +###################################################################### +# Do not call this script directly! +# +# The generate script ensures that @INC is correct before the engine +# is executed. +# +# Copyright (C) 2009 Marius Storm-Olsen +###################################################################### +use strict; +use File::Basename; +use Cwd; + +my $file = $ARGV[0]; +die "No file provided!" if !defined $file; + +my ($cflags, $target, $type, $line); + +open(F, "<$file") || die "Couldn't open file $file"; +my @data = ; +close(F); + +while (my $text = shift @data) { + my $ate_next; + do { + $ate_next = 0; + $line++; + chomp $text; + chop $text if ($text =~ /\r$/); + if ($text =~ /\\$/) { + $text =~ s/\\$//; + $text .= shift @data; + $ate_next = 1; + } + } while($ate_next); + + if($text =~ / -c /) { + # compilation + handleCompileLine($text, $line); + + } elsif ($text =~ / -o /) { + # linking executable + handleLinkLine($text, $line); + + } elsif ($text =~ /\.o / && $text =~ /\.a /) { + # libifying + handleLibLine($text, $line); + +# } elsif ($text =~ /^cp /) { +# # copy file around +# +# } elsif ($text =~ /^rm -f /) { +# # shell command +# +# } elsif ($text =~ /^make[ \[]/) { +# # make output +# +# } elsif ($text =~ /^echo /) { +# # echo to file +# +# } elsif ($text =~ /^if /) { +# # shell conditional +# +# } elsif ($text =~ /^tclsh /) { +# # translation stuff +# +# } elsif ($text =~ /^umask /) { +# # handling boilerplates +# +# } elsif ($text =~ /\$\(\:\)/) { +# # ignore +# +# } elsif ($text =~ /^FLAGS=/) { +# # flags check for dependencies +# +# } elsif ($text =~ /^'\/usr\/bin\/perl' -MError -e/) { +# # perl commands for copying files +# +# } elsif ($text =~ /generate-cmdlist\.sh/) { +# # command for generating list of commands +# +# } elsif ($text =~ /^test / && $text =~ /|| rm -f /) { +# # commands removing executables, if they exist +# +# } elsif ($text =~ /new locations or Tcl/) { +# # command for detecting Tcl/Tk changes +# +# } elsif ($text =~ /mkdir -p/) { +# # command creating path +# +# } elsif ($text =~ /: no custom templates yet/) { +# # whatever + + } else { +# print "Unhandled (line: $line): $text\n"; + } +} +close(F); + +# use Data::Dumper; +# print "Parsed build structure:\n"; +# print Dumper(%build_structure); + +# ------------------------------------------------------------------- +# Functions under here +# ------------------------------------------------------------------- +my (%build_structure, @defines, @incpaths, @cflags, @sources); + +sub clearCompileStep +{ + @defines = (); + @incpaths = (); + @cflags = (); + @sources = (); +} + +sub removeDuplicates +{ + my (%dupHash, $entry); + %dupHash = map { $_, 1 } @defines; + @defines = keys %dupHash; + + %dupHash = map { $_, 1 } @incpaths; + @incpaths = keys %dupHash; + + %dupHash = map { $_, 1 } @cflags; + @cflags = keys %dupHash; + + %dupHash = map { $_, 1 } @sources; + @sources = keys %dupHash; +} + +sub handleCompileLine +{ + my ($line, $lineno) = @_; + my @parts = split(' ', $line); + shift(@parts); # ignore cmd + while (my $part = shift @parts) { + if ("$part" eq "-o") { + # ignore object file + shift @parts; + } elsif ("$part" eq "-c") { + # ignore compile flag + } elsif ("$part" eq "-c") { + } elsif ($part =~ /^.?-I/) { + push(@incpaths, $part); + } elsif ($part =~ /^.?-D/) { + push(@defines, $part); + } elsif ($part =~ /^-/) { + push(@cflags, $part); + } elsif ($part =~ /\.(c|cc|cpp)$/) { + push(@sources, $part); + } else { + die "Unhandled compiler option @ line $lineno: $part"; + } + } + #print "Sources: @sources\nCFlags: @cflags\nDefine: @defines\nIncpat: @incpaths\n"; + #exit(1); +} + +sub handleLibLine +{ + my ($line, $lineno) = @_; + my (@objfiles, @lflags, $libout, $part); + # kill cmd and rm 'prefix' + $line =~ s/^rm -f .* && .* rcs //; + my @parts = split(' ', $line); + while ($part = shift @parts) { + if ($part =~ /^-/) { + push(@lflags, $part); + } elsif ($part =~ /\.(o|obj)$/) { + push(@objfiles, $part); + } elsif ($part =~ /\.(a|lib)$/) { + $libout = $part; + } else { + die "Unhandled lib option @ line $lineno: $part"; + } + } + #print "LibOut: '$libout'\nLFlags: @lflags\nOfiles: @objfiles\n"; + #exit(1); + removeDuplicates(); + push(@{$build_structure{"LIBS"}}, $libout); + @{$build_structure{"LIBS_${libout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_SOURCES", + "_OBJECTS"); + @{$build_structure{"LIBS_${libout}_DEFINES"}} = @defines; + @{$build_structure{"LIBS_${libout}_INCLUDES"}} = @incpaths; + @{$build_structure{"LIBS_${libout}_CFLAGS"}} = @cflags; + @{$build_structure{"LIBS_${libout}_SOURCES"}} = @sources; + @{$build_structure{"LIBS_${libout}_OBJECTS"}} = @objfiles; + clearCompileStep(); +} + +sub handleLinkLine +{ + my ($line, $lineno) = @_; + my (@objfiles, @lflags, @libs, $appout, $part); + my @parts = split(' ', $line); + shift(@parts); # ignore cmd + while ($part = shift @parts) { + if ($part =~ /^-[GRIDO]/) { + # eat compiler flags + } elsif ("$part" eq "-o") { + $appout = shift @parts; + } elsif ($part =~ /^-/) { + push(@lflags, $part); + } elsif ($part =~ /\.(a|lib)$/) { + push(@libs, $part); + } elsif ($part =~ /\.(o|obj)$/) { + push(@objfiles, $part); + } else { + die "Unhandled lib option @ line $lineno: $part"; + } + } + #print "AppOut: '$appout'\nLFlags: @lflags\nLibs : @libs\nOfiles: @objfiles\n"; + #exit(1); + removeDuplicates(); + push(@{$build_structure{"APPS"}}, $appout); + @{$build_structure{"APPS_${appout}"}} = ("_DEFINES", "_INCLUDES", "_CFLAGS", "_LFLAGS", + "_SOURCES", "_OBJECTS", "_LIBS"); + @{$build_structure{"APPS_${appout}_DEFINES"}} = @defines; + @{$build_structure{"APPS_${appout}_INCLUDES"}} = @incpaths; + @{$build_structure{"APPS_${appout}_CFLAGS"}} = @cflags; + @{$build_structure{"APPS_${appout}_LFLAGS"}} = @lflags; + @{$build_structure{"APPS_${appout}_SOURCES"}} = @sources; + @{$build_structure{"APPS_${appout}_OBJECTS"}} = @objfiles; + @{$build_structure{"APPS_${appout}_LIBS"}} = @libs; + clearCompileStep(); +} diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index 98592040d1..2d2d5794ad 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -318,13 +318,9 @@ __git_remotes () echo ${i#$d/remotes/} done [ "$ngoff" ] && shopt -u nullglob - for i in $(git --git-dir="$d" config --list); do - case "$i" in - remote.*.url=*) - i="${i#remote.}" - echo "${i/.url=*/}" - ;; - esac + for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do + i="${i#remote.}" + echo "${i/.url*/}" done } @@ -605,13 +601,9 @@ __git_porcelain_commandlist="$(__git_porcelain_commands 2>/dev/null)" __git_aliases () { local i IFS=$'\n' - for i in $(git --git-dir="$(__gitdir)" config --list); do - case "$i" in - alias.*) - i="${i#alias.}" - echo "${i/=*/}" - ;; - esac + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "alias\..*" 2>/dev/null); do + i="${i#alias.}" + echo "${i/ */}" done } @@ -1769,13 +1761,9 @@ _git_remote () ;; update) local i c='' IFS=$'\n' - for i in $(git --git-dir="$(__gitdir)" config --list); do - case "$i" in - remotes.*) - i="${i#remotes.}" - c="$c ${i/=*/}" - ;; - esac + for i in $(git --git-dir="$(__gitdir)" config --get-regexp "remotes\..*" 2>/dev/null); do + i="${i#remotes.}" + c="$c ${i/ */}" done __gitcomp "$c" ;; diff --git a/diff-delta.c b/diff-delta.c index a4e28df714..464ac3ffc0 100644 --- a/diff-delta.c +++ b/diff-delta.c @@ -4,7 +4,7 @@ * This code was greatly inspired by parts of LibXDiff from Davide Libenzi * http://www.xmailserver.org/xdiff-lib.html * - * Rewritten for GIT by Nicolas Pitre , (C) 2005-2007 + * Rewritten for GIT by Nicolas Pitre , (C) 2005-2007 * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/git-compat-util.h b/git-compat-util.h index e5e9f39c56..8d6e29cdea 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -65,6 +65,12 @@ #define _NETBSD_SOURCE 1 #define _SGI_SOURCE 1 +#ifdef WIN32 /* Both MinGW and MSVC */ +#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */ +#include +#include +#endif + #include #include #include @@ -113,6 +119,9 @@ /* pull in Windows compatibility stuff */ #include "compat/mingw.h" #endif /* __MINGW32__ */ +#ifdef _MSC_VER +#include "compat/msvc.h" +#endif #ifndef NO_LIBGEN_H #include diff --git a/git-cvsimport.perl b/git-cvsimport.perl index d7411151dd..1ad20ac964 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -253,6 +253,7 @@ sub conn { } } }; + $pass = "A" unless $pass; } my ($s, $rep); diff --git a/git-web--browse.sh b/git-web--browse.sh index 4f5c740df5..a578c3a732 100755 --- a/git-web--browse.sh +++ b/git-web--browse.sh @@ -111,7 +111,8 @@ if test -z "$browser" ; then browser_candidates="w3m links lynx" fi # SECURITYSESSIONID indicates an OS X GUI login session - if test -n "$SECURITYSESSIONID"; then + if test -n "$SECURITYSESSIONID" \ + -o "$TERM_PROGRAM" = "Apple_Terminal" ; then browser_candidates="open $browser_candidates" fi # /bin/start indicates MinGW diff --git a/git.spec.in b/git.spec.in index 4be0834f0b..ab224f7eae 100644 --- a/git.spec.in +++ b/git.spec.in @@ -233,7 +233,7 @@ rm -rf $RPM_BUILD_ROOT * Tue Mar 27 2007 Eygene Ryabinkin - Added the git-p4 package: Perforce import stuff. -* Mon Feb 13 2007 Nicolas Pitre +* Mon Feb 13 2007 Nicolas Pitre - Update core package description (Git isn't as stupid as it used to be) * Mon Feb 12 2007 Junio C Hamano diff --git a/help.c b/help.c index 294337e71c..e8db31f60f 100644 --- a/help.c +++ b/help.c @@ -126,8 +126,8 @@ static int is_executable(const char *name) !S_ISREG(st.st_mode)) return 0; -#ifdef __MINGW32__ - /* cannot trust the executable bit, peek into the file instead */ +#ifdef WIN32 +{ /* cannot trust the executable bit, peek into the file instead */ char buf[3] = { 0 }; int n; int fd = open(name, O_RDONLY); @@ -140,6 +140,7 @@ static int is_executable(const char *name) st.st_mode |= S_IXUSR; close(fd); } +} #endif return st.st_mode & S_IXUSR; } diff --git a/http.c b/http.c index 84def9ff24..23b2a1932c 100644 --- a/http.c +++ b/http.c @@ -866,7 +866,7 @@ static int fetch_pack_index(unsigned char *sha1, const char *base_url) int ret = 0; char *hex = xstrdup(sha1_to_hex(sha1)); char *filename; - char *url; + char *url = NULL; struct strbuf buf = STRBUF_INIT; if (has_pack_index(sha1)) { diff --git a/pager.c b/pager.c index f416d38ac2..86facec7b4 100644 --- a/pager.c +++ b/pager.c @@ -9,7 +9,7 @@ static int spawned_pager; -#ifndef __MINGW32__ +#ifndef WIN32 static void pager_preexec(void) { /* @@ -72,7 +72,7 @@ void setup_pager(void) static const char *env[] = { "LESS=FRSX", NULL }; pager_process.env = env; } -#ifndef __MINGW32__ +#ifndef WIN32 pager_process.preexec_cb = pager_preexec; #endif if (start_command(&pager_process)) diff --git a/patch-delta.c b/patch-delta.c index ef748ce96d..e02e13bd4e 100644 --- a/patch-delta.c +++ b/patch-delta.c @@ -2,7 +2,7 @@ * patch-delta.c: * recreate a buffer from a source and the delta produced by diff-delta.c * - * (C) 2005 Nicolas Pitre + * (C) 2005 Nicolas Pitre * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/progress.c b/progress.c index 621c34edc2..132ed95a3d 100644 --- a/progress.c +++ b/progress.c @@ -1,7 +1,7 @@ /* * Simple text-based progress display module for GIT * - * Copyright (c) 2007 by Nicolas Pitre + * Copyright (c) 2007 by Nicolas Pitre * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/run-command.c b/run-command.c index ac314a5a8d..cf2d8f7fae 100644 --- a/run-command.c +++ b/run-command.c @@ -75,7 +75,7 @@ fail_pipe: trace_argv_printf(cmd->argv, "trace: run_command:"); -#ifndef __MINGW32__ +#ifndef WIN32 fflush(NULL); cmd->pid = fork(); if (!cmd->pid) { @@ -134,6 +134,7 @@ fail_pipe: error("cannot fork() for %s: %s", cmd->argv[0], strerror(failed_errno = errno)); #else +{ int s0 = -1, s1 = -1, s2 = -1; /* backups of stdin, stdout, stderr */ const char **sargv = cmd->argv; char **env = environ; @@ -197,6 +198,7 @@ fail_pipe: dup2(s1, 1), close(s1); if (s2 >= 0) dup2(s2, 2), close(s2); +} #endif if (cmd->pid < 0) { @@ -313,8 +315,8 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const return run_command(&cmd); } -#ifdef __MINGW32__ -static __stdcall unsigned run_thread(void *data) +#ifdef WIN32 +static unsigned __stdcall run_thread(void *data) { struct async *async = data; return async->proc(async->fd_for_proc, async->data); @@ -329,7 +331,7 @@ int start_async(struct async *async) return error("cannot create pipe: %s", strerror(errno)); async->out = pipe_out[0]; -#ifndef __MINGW32__ +#ifndef WIN32 /* Flush stdio before fork() to avoid cloning buffers */ fflush(NULL); @@ -358,7 +360,7 @@ int start_async(struct async *async) int finish_async(struct async *async) { -#ifndef __MINGW32__ +#ifndef WIN32 int ret = wait_or_whine(async->pid, "child process", 0); #else DWORD ret = 0; diff --git a/run-command.h b/run-command.h index 0c00b25ff2..fb342090e3 100644 --- a/run-command.h +++ b/run-command.h @@ -70,7 +70,7 @@ struct async { int (*proc)(int fd, void *data); void *data; int out; /* caller reads from here and closes it */ -#ifndef __MINGW32__ +#ifndef WIN32 pid_t pid; #else HANDLE tid; diff --git a/setup.c b/setup.c index e3781b656d..029371e584 100644 --- a/setup.c +++ b/setup.c @@ -41,7 +41,7 @@ const char *prefix_path(const char *prefix, int len, const char *path) const char *prefix_filename(const char *pfx, int pfx_len, const char *arg) { static char path[PATH_MAX]; -#ifndef __MINGW32__ +#ifndef WIN32 if (!pfx || !*pfx || is_absolute_path(arg)) return arg; memcpy(path, pfx, pfx_len); diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh index 55ed7c7935..3c6687abec 100755 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -6,6 +6,17 @@ test_description='prune' . ./test-lib.sh +day=$((60*60*24)) +week=$(($day*7)) + +add_blob() { + before=$(git count-objects | sed "s/ .*//") && + BLOB=$(echo aleph_0 | git hash-object -w --stdin) && + BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && + test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && + test -f $BLOB_FILE +} + test_expect_success setup ' : > file && @@ -31,11 +42,7 @@ test_expect_success 'prune stale packs' ' test_expect_success 'prune --expire' ' - before=$(git count-objects | sed "s/ .*//") && - BLOB=$(echo aleph | git hash-object -w --stdin) && - BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && - test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && - test -f $BLOB_FILE && + add_blob && git prune --expire=1.hour.ago && test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && test -f $BLOB_FILE && @@ -48,16 +55,12 @@ test_expect_success 'prune --expire' ' test_expect_success 'gc: implicit prune --expire' ' - before=$(git count-objects | sed "s/ .*//") && - BLOB=$(echo aleph_0 | git hash-object -w --stdin) && - BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && - test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && - test -f $BLOB_FILE && - test-chmtime =-$((86400*14-30)) $BLOB_FILE && + add_blob && + test-chmtime =-$((2*$week-30)) $BLOB_FILE && git gc && test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && test -f $BLOB_FILE && - test-chmtime =-$((86400*14+1)) $BLOB_FILE && + test-chmtime =-$((2*$week+1)) $BLOB_FILE && git gc && test $before = $(git count-objects | sed "s/ .*//") && ! test -f $BLOB_FILE @@ -114,12 +117,8 @@ test_expect_success 'prune: do not prune heads listed as an argument' ' test_expect_success 'gc --no-prune' ' - before=$(git count-objects | sed "s/ .*//") && - BLOB=$(echo aleph_0 | git hash-object -w --stdin) && - BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && - test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && - test -f $BLOB_FILE && - test-chmtime =-$((86400*5001)) $BLOB_FILE && + add_blob && + test-chmtime =-$((5001*$day)) $BLOB_FILE && git config gc.pruneExpire 2.days.ago && git gc --no-prune && test 1 = $(git count-objects | sed "s/ .*//") && @@ -140,9 +139,8 @@ test_expect_success 'gc respects gc.pruneExpire' ' test_expect_success 'gc --prune=' ' - BLOB=$(echo aleph_0 | git hash-object -w --stdin) && - BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && - test-chmtime =-$((86400*5001)) $BLOB_FILE && + add_blob && + test-chmtime =-$((5001*$day)) $BLOB_FILE && git gc --prune=5002.days.ago && test -f $BLOB_FILE && git gc --prune=5000.days.ago && @@ -150,4 +148,18 @@ test_expect_success 'gc --prune=' ' ' +test_expect_success 'gc: prune old objects after local clone' ' + add_blob && + test-chmtime =-$((2*$week+1)) $BLOB_FILE && + git clone --no-hardlinks . aclone && + ( + cd aclone && + test 1 = $(git count-objects | sed "s/ .*//") && + test -f $BLOB_FILE && + git gc --prune && + test 0 = $(git count-objects | sed "s/ .*//") && + ! test -f $BLOB_FILE + ) +' + test_done diff --git a/test-delta.c b/test-delta.c index 3d885ff37e..af40a3c49e 100644 --- a/test-delta.c +++ b/test-delta.c @@ -1,7 +1,7 @@ /* * test-delta.c: test code to exercise diff-delta.c and patch-delta.c * - * (C) 2005 Nicolas Pitre + * (C) 2005 Nicolas Pitre * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/thread-utils.c b/thread-utils.c index 55e7e2904e..4f9c829c2d 100644 --- a/thread-utils.c +++ b/thread-utils.c @@ -1,9 +1,6 @@ #include "cache.h" -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# include -#elif defined(hpux) || defined(__hpux) || defined(_hpux) +#if defined(hpux) || defined(__hpux) || defined(_hpux) # include #endif diff --git a/transport.c b/transport.c index 4cb807700a..644a30a0b2 100644 --- a/transport.c +++ b/transport.c @@ -869,8 +869,9 @@ int transport_set_option(struct transport *transport, int transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags, - int * nonfastforward) + int *nonfastforward) { + *nonfastforward = 0; verify_remote_names(refspec_nr, refspec); if (transport->push)