git-reflog
git-relink
git-remote
+git-remote-curl
git-repack
git-replace
git-repo-config
--- /dev/null
+GIT v1.6.4.3 Release Notes
+==========================
+
+Fixes since v1.6.4.2
+--------------------
+
+* "git clone" from an empty repository gave unnecessary error message,
+ even though it did everything else correctly.
+
+* "git cvsserver" invoked git commands via "git-foo" style, which has long
+ been deprecated.
+
+* "git fetch" and "git clone" had an extra sanity check to verify the
+ presense of the corresponding *.pack file before downloading *.idx
+ file by issuing a HEAD request. Github server however sometimes
+ gave 500 (Internal server error) response to HEAD even if a GET
+ request for *.pack file to the same URL would have succeeded, and broke
+ clone over HTTP from some of their repositories. As a workaround, this
+ verification has been removed (as it is not absolutely necessary).
+
+* "git grep" did not like relative pathname to refer outside the current
+ directory when run from a subdirectory.
+
+* an error message from "git push" was formatted in a very ugly way.
+
+* "git svn" did not quote the subversion user name correctly when
+ running its author-prog helper program.
+
+Other minor documentation updates are included.
[--3way] [--interactive] [--committer-date-is-author-date]
[--ignore-date] [--ignore-space-change | --ignore-whitespace]
[--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
- [--reject] [-q | --quiet] [--scissors]
+ [--reject] [-q | --quiet] [--scissors | --no-scissors]
[<mbox> | <Maildir>...]
'git am' (--skip | --resolved | --abort)
Remove everything in body before a scissors line (see
linkgit:git-mailinfo[1]).
+---no-scissors::
+ Ignore scissors lines (see linkgit:git-mailinfo[1]).
+
-q::
--quiet::
Be quiet. Only print error messages.
with comments and suggestions on the message you are responding to, and to
conclude it with a patch submission, separating the discussion and the
beginning of the proposed commit log message with a scissors line.
++
+This can enabled by default with the configuration option mailinfo.scissors.
+
+--no-scissors::
+ Ignore scissors lines. Useful for overriding mailinfo.scissors settings.
<msg>::
The commit log message extracted from e-mail, usually
SYNOPSIS
--------
[verse]
-'git quiltimport' [--dry-run] [--author <author>] [--patches <dir>]
+'git quiltimport' [--dry-run | -n] [--author <author>] [--patches <dir>]
DESCRIPTION
--- /dev/null
+git-remote-helpers(1)
+=====================
+
+NAME
+----
+git-remote-helpers - Helper programs for interoperation with remote git
+
+SYNOPSIS
+--------
+'git remote-<transport>' <remote>
+
+DESCRIPTION
+-----------
+
+These programs are normally not used directly by end users, but are
+invoked by various git programs that interact with remote repositories
+when the repository they would operate on will be accessed using
+transport code not linked into the main git binary. Various particular
+helper programs will behave as documented here.
+
+COMMANDS
+--------
+
+Commands are given by the caller on the helper's standard input, one per line.
+
+'capabilities'::
+ Lists the capabilities of the helper, one per line, ending
+ with a blank line.
+
+'list'::
+ Lists the refs, one per line, in the format "<value> <name>
+ [<attr> ...]". The value may be a hex sha1 hash, "@<dest>" for
+ a symref, or "?" to indicate that the helper could not get the
+ value of the ref. A space-separated list of attributes follows
+ the name; unrecognized attributes are ignored. After the
+ complete list, outputs a blank line.
+
+'fetch' <sha1> <name>::
+ Fetches the given object, writing the necessary objects to the
+ database. Outputs a blank line when the fetch is
+ complete. Only objects which were reported in the ref list
+ with a sha1 may be fetched this way.
++
+Supported if the helper has the "fetch" capability.
+
+If a fatal error occurs, the program writes the error message to
+stderr and exits. The caller should expect that a suitable error
+message has been printed if the child closes the connection without
+completing a valid response for the current command.
+
+Additional commands may be supported, as may be determined from
+capabilities reported by the helper.
+
+CAPABILITIES
+------------
+
+'fetch'::
+ This helper supports the 'fetch' command.
+
+REF LIST ATTRIBUTES
+-------------------
+
+None are defined yet, but the caller must accept any which are supplied.
+
+Documentation
+-------------
+Documentation by Daniel Barkalow.
+
+GIT
+---
+Part of the linkgit:git[1] suite
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.6.4.2/git.html[documentation for release 1.6.4.2]
+* link:v1.6.4.3/git.html[documentation for release 1.6.4.3]
* release notes for
+ 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],
link:RelNotes-1.6.4.txt[1.6.4].
which are derived from $prefix, so "make all; make prefix=/usr
install" would not work.
+The beginning of the Makefile documents many variables that affect the way
+git is built. You can override them either from the command line, or in a
+config.mak file.
+
Alternatively you can use autoconf generated ./configure script to
set up install paths (via config.mak.autogen), so you can write instead
export GIT_EXEC_PATH PATH GITPERLLIB
- Git is reasonably self-sufficient, but does depend on a few external
- programs and libraries:
+ programs and libraries. Git can be used without most of them by adding
+ the approriate "NO_<LIBRARY>=YesPlease" to the make command line or
+ config.mak file.
- "zlib", the compression library. Git won't build without it.
- - "openssl". Unless you specify otherwise, you'll get the SHA1
- library from here.
+ - "ssh" is used to push and pull over the net.
- If you don't have openssl, you can use one of the SHA1 libraries
- that come with git (git includes the one from Mozilla, and has
- its own PowerPC and ARM optimized ones too - see the Makefile).
+ - A POSIX-compliant shell is required to run many scripts needed
+ for everyday use (e.g. "bisect", "pull").
- - libcurl library; git-http-fetch and git-fetch use them. You
- might also want the "curl" executable for debugging purposes.
- If you do not use http transfer, you are probably OK if you
- do not have them.
+ - "Perl" is needed to use some of the features (e.g. preparing a
+ partial commit using "git add -i/-p", interacting with svn
+ repositories with "git svn"). If you can live without these, use
+ NO_PERL.
- - expat library; git-http-push uses it for remote lock
- management over DAV. Similar to "curl" above, this is optional.
+ - "openssl" library is used by git-imap-send to use IMAP over SSL.
+ If you don't need it, use NO_OPENSSL.
- - "wish", the Tcl/Tk windowing shell is used in gitk to show the
- history graphically, and in git-gui.
+ By default, git uses OpenSSL for SHA1 but it will use it's own
+ library (inspired by Mozilla's) with either NO_OPENSSL or
+ BLK_SHA1. Also included is a version optimized for PowerPC
+ (PPC_SHA1).
+
+ - "libcurl" library is used by git-http-fetch and git-fetch. You
+ might also want the "curl" executable for debugging purposes.
+ If you do not use http:// or https:// repositories, you do not
+ have to have them (use NO_CURL).
- - "ssh" is used to push and pull over the net
+ - "expat" library; git-http-push uses it for remote lock
+ management over DAV. Similar to "curl" above, this is optional
+ (with NO_EXPAT).
- - "perl" and POSIX-compliant shells are needed to use most of
- the bare-bones Porcelainish scripts.
+ - "wish", the Tcl/Tk windowing shell is used in gitk to show the
+ history graphically, and in git-gui. If you don't want gitk or
+ git-gui, you can use NO_TCLTK.
- Some platform specific issues are dealt with Makefile rules,
but depending on your specific installation, you may not
# Define PPC_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for PowerPC.
#
-# Define NEEDS_SSL_WITH_CRYPTO if you need -lcrypto with -lssl (Darwin).
+# Define NEEDS_CRYPTO_WITH_SSL if you need -lcrypto when using -lssl (Darwin).
+#
+# Define NEEDS_SSL_WITH_CRYPTO if you need -lssl when using -lcrypto (Darwin).
#
# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
#
BUILT_INS += git-status$X
BUILT_INS += git-whatchanged$X
-# what 'all' will build and 'install' will install, in gitexecdir
+# what 'all' will build and 'install' will install in gitexecdir,
+# excluding programs for built-in commands
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
# what 'all' will build but not install in gitexecdir
LIB_OBJS += tag.o
LIB_OBJS += trace.o
LIB_OBJS += transport.o
+LIB_OBJS += transport-helper.o
LIB_OBJS += tree-diff.o
LIB_OBJS += tree.o
LIB_OBJS += tree-walk.o
TAR = gtar
endif
ifeq ($(uname_S),Darwin)
+ NEEDS_CRYPTO_WITH_SSL = YesPlease
NEEDS_SSL_WITH_CRYPTO = YesPlease
NEEDS_LIBICONV = YesPlease
ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
else
CURL_LIBCURL = -lcurl
endif
- BUILTIN_OBJS += builtin-http-fetch.o
- EXTLIBS += $(CURL_LIBCURL)
- LIB_OBJS += http.o http-walker.o
+ PROGRAMS += git-remote-curl$X git-http-fetch$X
curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p)
ifeq "$(curl_check)" "070908"
ifndef NO_EXPAT
else
OPENSSL_LINK =
endif
+ ifdef NEEDS_CRYPTO_WITH_SSL
+ OPENSSL_LINK += -lcrypto
+ endif
else
BASIC_CFLAGS += -DNO_OPENSSL
BLK_SHA1 = 1
QUIET_LINK = @echo ' ' LINK $@;
QUIET_BUILT_IN = @echo ' ' BUILTIN $@;
QUIET_GEN = @echo ' ' GEN $@;
+ QUIET_LNCP = @echo ' ' LN/CP $@;
QUIET_SUBDIR0 = +@subdir=
QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
$(MAKE) $(PRINT_DIR) -C $$subdir
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL)
-http.o http-walker.o http-push.o transport.o: http.h
+http.o http-walker.o http-push.o: http.h
+http.o http-walker.o: $(LIB_H)
+
+git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS)
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+ $(LIBS) $(CURL_LIBCURL)
git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
+git-remote-curl$X: remote-curl.o http.o http-walker.o $(GITLIBS)
+ $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
+ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
+
$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
$(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)
builtin-revert.o wt-status.o: wt-status.h
out = open(file, O_CREAT | O_WRONLY, 0644);
if (out < 0)
die ("Could not open '%s' for writing.", file);
- rev.diffopt.file = fdopen(out, "w");
+ rev.diffopt.file = xfdopen(out, "w");
rev.diffopt.close_file = 1;
if (run_diff_files(&rev, 0))
die ("Could not write patch");
die_errno("failed to create link '%s'", dest->buf);
option_no_hardlinks = 1;
}
- if (copy_file(dest->buf, src->buf, 0666))
+ if (copy_file_with_time(dest->buf, src->buf, 0666))
die_errno("failed to copy file to '%s'", dest->buf);
}
closedir(dir);
for (ref = ref_map; ref; ref = ref->next) {
if (write_in_full(revlist.in, sha1_to_hex(ref->old_sha1), 40) < 0 ||
- write_in_full(revlist.in, "\n", 1) < 0) {
+ write_str_in_full(revlist.in, "\n") < 0) {
if (errno != EPIPE && errno != EINVAL)
error("failed write to rev-list: %s", strerror(errno));
err = -1;
#include "parse-options.h"
#include "userdiff.h"
#include "grep.h"
+#include "quote.h"
#ifndef NO_EXTERNAL_GREP
#ifdef __unix__
unsigned long size;
char *data;
enum object_type type;
- char *to_free = NULL;
int hit;
+ struct strbuf pathbuf = STRBUF_INIT;
data = read_sha1_file(sha1, &type, &size);
if (!data) {
return 0;
}
if (opt->relative && opt->prefix_length) {
- static char name_buf[PATH_MAX];
- char *cp;
- int name_len = strlen(name) - opt->prefix_length + 1;
-
- if (!tree_name_len)
- name += opt->prefix_length;
- else {
- if (ARRAY_SIZE(name_buf) <= name_len)
- cp = to_free = xmalloc(name_len);
- else
- cp = name_buf;
- memcpy(cp, name, tree_name_len);
- strcpy(cp + tree_name_len,
- name + tree_name_len + opt->prefix_length);
- name = cp;
- }
+ quote_path_relative(name + tree_name_len, -1, &pathbuf, opt->prefix);
+ strbuf_insert(&pathbuf, 0, name, tree_name_len);
+ name = pathbuf.buf;
}
hit = grep_buffer(opt, name, data, size);
+ strbuf_release(&pathbuf);
free(data);
- free(to_free);
return hit;
}
int i;
char *data;
size_t sz;
+ struct strbuf buf = STRBUF_INIT;
if (lstat(filename, &st) < 0) {
err_ret:
}
close(i);
if (opt->relative && opt->prefix_length)
- filename += opt->prefix_length;
+ filename = quote_path_relative(filename, -1, &buf, opt->prefix);
i = grep_buffer(opt, filename, data, sz);
+ strbuf_release(&buf);
free(data);
return i;
}
hit = external_grep(opt, paths, cached);
if (hit >= 0)
return hit;
+ hit = 0;
}
#endif
};
memset(&opt, 0, sizeof(opt));
+ opt.prefix = prefix;
opt.prefix_length = (prefix && *prefix) ? strlen(prefix) : 0;
opt.relative = 1;
opt.pathname = 1;
verify_filename(prefix, argv[j]);
}
- if (i < argc) {
+ if (i < argc)
paths = get_pathspec(prefix, argv + i);
- if (opt.prefix_length && opt.relative) {
- /* Make sure we do not get outside of paths */
- for (i = 0; paths[i]; i++)
- if (strncmp(prefix, paths[i], opt.prefix_length))
- die("git grep: cannot generate relative filenames containing '..'");
- }
- }
else if (prefix) {
paths = xcalloc(2, sizeof(const char *));
paths[0] = prefix;
+++ /dev/null
-#include "cache.h"
-#include "walker.h"
-
-int cmd_http_fetch(int argc, const char **argv, const char *prefix)
-{
- struct walker *walker;
- int commits_on_stdin = 0;
- int commits;
- const char **write_ref = NULL;
- char **commit_id;
- const char *url;
- char *rewritten_url = NULL;
- int arg = 1;
- int rc = 0;
- int get_tree = 0;
- int get_history = 0;
- int get_all = 0;
- int get_verbosely = 0;
- int get_recover = 0;
-
- git_config(git_default_config, NULL);
-
- while (arg < argc && argv[arg][0] == '-') {
- if (argv[arg][1] == 't') {
- get_tree = 1;
- } else if (argv[arg][1] == 'c') {
- get_history = 1;
- } else if (argv[arg][1] == 'a') {
- get_all = 1;
- get_tree = 1;
- get_history = 1;
- } else if (argv[arg][1] == 'v') {
- get_verbosely = 1;
- } else if (argv[arg][1] == 'w') {
- write_ref = &argv[arg + 1];
- arg++;
- } else if (!strcmp(argv[arg], "--recover")) {
- get_recover = 1;
- } else if (!strcmp(argv[arg], "--stdin")) {
- commits_on_stdin = 1;
- }
- arg++;
- }
- if (argc < arg + 2 - commits_on_stdin) {
- usage("git http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url");
- return 1;
- }
- if (commits_on_stdin) {
- commits = walker_targets_stdin(&commit_id, &write_ref);
- } else {
- commit_id = (char **) &argv[arg++];
- commits = 1;
- }
- url = argv[arg];
- if (url && url[strlen(url)-1] != '/') {
- rewritten_url = xmalloc(strlen(url)+2);
- strcpy(rewritten_url, url);
- strcat(rewritten_url, "/");
- url = rewritten_url;
- }
-
- walker = get_http_walker(url, NULL);
- walker->get_tree = get_tree;
- walker->get_history = get_history;
- walker->get_all = get_all;
- walker->get_verbosely = get_verbosely;
- walker->get_recover = get_recover;
-
- rc = walker_fetch(walker, commits, commit_id, write_ref, url);
-
- if (commits_on_stdin)
- walker_targets_free(commits, commit_id, write_ref);
-
- if (walker->corrupt_object_found) {
- fprintf(stderr,
-"Some loose object were found to be corrupt, but they might be just\n"
-"a false '404 Not Found' error message sent with incorrect HTTP\n"
-"status code. Suggest running 'git fsck'.\n");
- }
-
- walker_free(walker);
-
- free(rewritten_url);
-
- return rc;
-}
}
static const char mailinfo_usage[] =
- "git mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
+ "git mailinfo [-k] [-u | --encoding=<encoding> | -n] [--scissors | --no-scissors] msg patch < mail >info";
int cmd_mailinfo(int argc, const char **argv, const char *prefix)
{
fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd < 0)
die_errno("cannot open output file '%s'", name);
- output = fdopen(fd, "w");
+ output = xfdopen(fd, "w");
/* Copy it out, while searching for a line that begins with
* "From " and having something that looks like a date format.
} else if (cmd->updateref &&
(write_in_full(lock->lock_fd,
sha1_to_hex(cb.last_kept_sha1), 40) != 40 ||
- write_in_full(lock->lock_fd, "\n", 1) != 1 ||
+ write_str_in_full(lock->lock_fd, "\n") != 1 ||
close_ref(lock) < 0)) {
status |= error("Couldn't write %s",
lock->lk->filename);
rls.git_cmd = 1;
if (start_command(&rls))
return -1;
- rls_fout = fdopen(rls.out, "r");
+ rls_fout = xfdopen(rls.out, "r");
while (fgets(buffer, sizeof(buffer), rls_fout)) {
unsigned char sha1[20];
if (buffer[0] == '-') {
extern void maybe_flush_or_die(FILE *, const char *);
extern int copy_fd(int ifd, int ofd);
extern int copy_file(const char *dst, const char *src, int mode);
-extern ssize_t read_in_full(int fd, void *buf, size_t count);
-extern ssize_t write_in_full(int fd, const void *buf, size_t count);
+extern int copy_file_with_time(const char *dst, const char *src, int mode);
extern void write_or_die(int fd, const void *buf, size_t count);
extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg);
extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg);
extern void fsync_or_die(int fd, const char *);
+extern ssize_t read_in_full(int fd, void *buf, size_t count);
+extern ssize_t write_in_full(int fd, const void *buf, size_t count);
+static inline ssize_t write_str_in_full(int fd, const char *str)
+{
+ return write_in_full(fd, str, strlen(str));
+}
+
/* pager.c */
extern void setup_pager(void);
extern const char *pager_program;
else {
if (write_in_full(fd, hex, 40) != 40)
break;
- if (write_in_full(fd, "\n", 1) != 1)
+ if (write_str_in_full(fd, "\n") != 1)
break;
}
}
free_path_split(path);
}
-char **copy_environ()
+static char **copy_environ(void)
{
char **env;
int i = 0;
/*
* If name contains '=', then sets the variable, otherwise it unsets it
*/
-char **env_setenv(char **env, const char *name)
+static char **env_setenv(char **env, const char *name)
{
char *eq = strchrnul(name, '=');
int i = lookup_env(env, name, eq-name);
return env;
}
+/*
+ * Copies global environ and adjusts variables as specified by vars.
+ */
+char **make_augmented_environ(const char *const *vars)
+{
+ char **env = copy_environ();
+
+ while (*vars)
+ env = env_setenv(env, *vars++);
+ return env;
+}
+
/* this is the first function to call into WS_32; initialize it */
#undef gethostbyname
struct hostent *mingw_gethostbyname(const char *host)
* helpers
*/
-char **copy_environ(void);
+char **make_augmented_environ(const char *const *vars);
void free_environ(char **env);
-char **env_setenv(char **env, const char *name);
/*
* A replacement of main() that ensures that argv[0] has a path
copy_end - copy_begin)
goto write_err_out;
if (new_line &&
- write_in_full(fd, "\n", 1) != 1)
+ write_str_in_full(fd, "\n") != 1)
goto write_err_out;
}
copy_begin = store.offset[i];
(defun git-add-file ()
"Add marked file(s) to the index cache."
(interactive)
- (let ((files (git-get-filenames (git-marked-files-state 'unknown 'ignored))))
+ (let ((files (git-get-filenames (git-marked-files-state 'unknown 'ignored 'unmerged))))
;; FIXME: add support for directories
(unless files
(push (file-relative-name (read-file-name "File to add: " nil nil t)) files))
(when buffer (with-current-buffer buffer (revert-buffer t t t)))))
(git-success-message "Reverted" names))))))
-(defun git-resolve-file ()
- "Resolve conflicts in marked file(s)."
- (interactive)
- (let ((files (git-get-filenames (git-marked-files-state 'unmerged))))
- (when files
- (when (apply 'git-call-process-display-error "update-index" "--" files)
- (git-update-status-files files)
- (git-success-message "Resolved" files)))))
-
(defun git-remove-handled ()
"Remove handled files from the status list."
(interactive)
(define-key map "P" 'git-prev-unmerged-file)
(define-key map "q" 'git-status-quit)
(define-key map "r" 'git-remove-file)
- (define-key map "R" 'git-resolve-file)
(define-key map "t" toggle-map)
(define-key map "T" 'git-toggle-all-marks)
(define-key map "u" 'git-unmark-file)
("Merge"
["Next Unmerged File" git-next-unmerged-file t]
["Prev Unmerged File" git-prev-unmerged-file t]
- ["Mark as Resolved" git-resolve-file t]
["Interactive Merge File" git-find-file-imerge t]
["Diff Against Common Base File" git-diff-file-base t]
["Diff Combined" git-diff-file-combined t]
# License: MIT <http://www.opensource.org/licenses/mit-license.php>
#
-import optparse, sys, os, marshal, popen2, subprocess, shelve
-import tempfile, getopt, sha, os.path, time, platform
+import optparse, sys, os, marshal, subprocess, shelve
+import tempfile, getopt, os.path, time, platform
import re
-from sets import Set;
-
verbose = False
self.usage += " //depot/path[@revRange]"
self.silent = False
- self.createdBranches = Set()
- self.committedChanges = Set()
+ self.createdBranches = set()
+ self.committedChanges = set()
self.branch = ""
self.detectBranches = False
self.detectLabels = False
if len(self.changesFile) > 0:
output = open(self.changesFile).readlines()
- changeSet = Set()
+ changeSet = set()
for line in output:
changeSet.add(int(line))
return 0;
}
+static int copy_times(const char *dst, const char *src)
+{
+ struct stat st;
+ struct utimbuf times;
+ if (stat(src, &st) < 0)
+ return -1;
+ times.actime = st.st_atime;
+ times.modtime = st.st_mtime;
+ if (utime(dst, ×) < 0)
+ return -1;
+ return 0;
+}
+
int copy_file(const char *dst, const char *src, int mode)
{
int fdi, fdo, status;
return status;
}
+
+int copy_file_with_time(const char *dst, const char *src, int mode)
+{
+ int status = copy_file(dst, src, mode);
+ if (!status)
+ return copy_times(dst, src);
+ return status;
+}
# The tree must be really really clean.
if ! git update-index --ignore-submodules --refresh > /dev/null; then
echo >&2 "cannot rebase: you have unstaged changes"
- git diff --name-status -r --ignore-submodules -- >&2
+ git diff-files --name-status -r --ignore-submodules -- >&2
exit 1
fi
diff=$(git diff-index --cached --name-status -r --ignore-submodules HEAD --)
sub call_authors_prog {
my ($orig_author) = @_;
+ $orig_author = command_oneline('rev-parse', '--sq-quote', $orig_author);
my $author = `$::_authors_prog $orig_author`;
if ($? != 0) {
die "$::_authors_prog failed with exit code $?\n"
#include "run-command.h"
const char git_usage_string[] =
- "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
+ "git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]\n"
+ " [-p|--paginate|--no-pager]\n"
+ " [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n"
+ " [--help] COMMAND [ARGS]";
const char git_more_info_string[] =
"See 'git help COMMAND' for more information on a specific command.";
{ "get-tar-commit-id", cmd_get_tar_commit_id },
{ "grep", cmd_grep, RUN_SETUP | USE_PAGER },
{ "help", cmd_help },
-#ifndef NO_CURL
- { "http-fetch", cmd_http_fetch, RUN_SETUP },
-#endif
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
{ "log", cmd_log, RUN_SETUP | USE_PAGER },
struct grep_pat *pattern_list;
struct grep_pat **pattern_tail;
struct grep_expr *pattern_expression;
+ const char *prefix;
int prefix_length;
regex_t regexp;
int linenum;
--- /dev/null
+#include "cache.h"
+#include "walker.h"
+
+int main(int argc, const char **argv)
+{
+ const char *prefix;
+ struct walker *walker;
+ int commits_on_stdin = 0;
+ int commits;
+ const char **write_ref = NULL;
+ char **commit_id;
+ const char *url;
+ char *rewritten_url = NULL;
+ int arg = 1;
+ int rc = 0;
+ int get_tree = 0;
+ int get_history = 0;
+ int get_all = 0;
+ int get_verbosely = 0;
+ int get_recover = 0;
+
+ prefix = setup_git_directory();
+
+ git_config(git_default_config, NULL);
+
+ while (arg < argc && argv[arg][0] == '-') {
+ if (argv[arg][1] == 't') {
+ get_tree = 1;
+ } else if (argv[arg][1] == 'c') {
+ get_history = 1;
+ } else if (argv[arg][1] == 'a') {
+ get_all = 1;
+ get_tree = 1;
+ get_history = 1;
+ } else if (argv[arg][1] == 'v') {
+ get_verbosely = 1;
+ } else if (argv[arg][1] == 'w') {
+ write_ref = &argv[arg + 1];
+ arg++;
+ } else if (!strcmp(argv[arg], "--recover")) {
+ get_recover = 1;
+ } else if (!strcmp(argv[arg], "--stdin")) {
+ commits_on_stdin = 1;
+ }
+ arg++;
+ }
+ if (argc < arg + 2 - commits_on_stdin) {
+ usage("git http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url");
+ return 1;
+ }
+ if (commits_on_stdin) {
+ commits = walker_targets_stdin(&commit_id, &write_ref);
+ } else {
+ commit_id = (char **) &argv[arg++];
+ commits = 1;
+ }
+ url = argv[arg];
+ if (url && url[strlen(url)-1] != '/') {
+ rewritten_url = xmalloc(strlen(url)+2);
+ strcpy(rewritten_url, url);
+ strcat(rewritten_url, "/");
+ url = rewritten_url;
+ }
+
+ walker = get_http_walker(url, NULL);
+ walker->get_tree = get_tree;
+ walker->get_history = get_history;
+ walker->get_all = get_all;
+ walker->get_verbosely = get_verbosely;
+ walker->get_recover = get_recover;
+
+ rc = walker_fetch(walker, commits, commit_id, write_ref, url);
+
+ if (commits_on_stdin)
+ walker_targets_free(commits, commit_id, write_ref);
+
+ if (walker->corrupt_object_found) {
+ fprintf(stderr,
+"Some loose object were found to be corrupt, but they might be just\n"
+"a false '404 Not Found' error message sent with incorrect HTTP\n"
+"status code. Suggest running 'git fsck'.\n");
+ }
+
+ walker_free(walker);
+
+ free(rewritten_url);
+
+ return rc;
+}
char *url;
struct strbuf buf = STRBUF_INIT;
- /* Don't use the index if the pack isn't there */
- end_url_with_slash(&buf, base_url);
- strbuf_addf(&buf, "objects/pack/pack-%s.pack", hex);
- url = strbuf_detach(&buf, 0);
-
- if (http_get_strbuf(url, NULL, 0)) {
- ret = error("Unable to verify pack %s is available",
- hex);
- goto cleanup;
- }
-
if (has_pack_index(sha1)) {
ret = 0;
goto cleanup;
FD_ZERO(&in);
FD_SET(0, &in);
select(1, &in, NULL, &in, NULL);
-
- setenv("LESS", "FRSX", 0);
}
#endif
pager_argv[2] = pager;
pager_process.argv = pager_argv;
pager_process.in = -1;
+ if (!getenv("LESS")) {
+ static const char *env[] = { "LESS=FRSX", NULL };
+ pager_process.env = env;
+ }
#ifndef __MINGW32__
pager_process.preexec_cb = pager_preexec;
#endif
--- /dev/null
+#include "cache.h"
+#include "remote.h"
+#include "strbuf.h"
+#include "walker.h"
+#include "http.h"
+
+static struct ref *get_refs(struct walker *walker, const char *url)
+{
+ struct strbuf buffer = STRBUF_INIT;
+ char *data, *start, *mid;
+ char *ref_name;
+ char *refs_url;
+ int i = 0;
+ int http_ret;
+
+ struct ref *refs = NULL;
+ struct ref *ref = NULL;
+ struct ref *last_ref = NULL;
+
+ refs_url = xmalloc(strlen(url) + 11);
+ sprintf(refs_url, "%s/info/refs", url);
+
+ http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
+ switch (http_ret) {
+ case HTTP_OK:
+ break;
+ case HTTP_MISSING_TARGET:
+ die("%s not found: did you run git update-server-info on the"
+ " server?", refs_url);
+ default:
+ http_error(refs_url, http_ret);
+ die("HTTP request failed");
+ }
+
+ data = buffer.buf;
+ start = NULL;
+ mid = data;
+ while (i < buffer.len) {
+ if (!start) {
+ start = &data[i];
+ }
+ if (data[i] == '\t')
+ mid = &data[i];
+ if (data[i] == '\n') {
+ data[i] = 0;
+ ref_name = mid + 1;
+ ref = xmalloc(sizeof(struct ref) +
+ strlen(ref_name) + 1);
+ memset(ref, 0, sizeof(struct ref));
+ strcpy(ref->name, ref_name);
+ get_sha1_hex(start, ref->old_sha1);
+ if (!refs)
+ refs = ref;
+ if (last_ref)
+ last_ref->next = ref;
+ last_ref = ref;
+ start = NULL;
+ }
+ i++;
+ }
+
+ strbuf_release(&buffer);
+
+ ref = alloc_ref("HEAD");
+ if (!walker->fetch_ref(walker, ref) &&
+ !resolve_remote_symref(ref, refs)) {
+ ref->next = refs;
+ refs = ref;
+ } else {
+ free(ref);
+ }
+
+ strbuf_release(&buffer);
+ free(refs_url);
+ return refs;
+}
+
+int main(int argc, const char **argv)
+{
+ struct remote *remote;
+ struct strbuf buf = STRBUF_INIT;
+ const char *url;
+ struct walker *walker = NULL;
+
+ setup_git_directory();
+ if (argc < 2) {
+ fprintf(stderr, "Remote needed\n");
+ return 1;
+ }
+
+ remote = remote_get(argv[1]);
+
+ if (argc > 2) {
+ url = argv[2];
+ } else {
+ url = remote->url[0];
+ }
+
+ do {
+ if (strbuf_getline(&buf, stdin, '\n') == EOF)
+ break;
+ if (!prefixcmp(buf.buf, "fetch ")) {
+ char *obj = buf.buf + strlen("fetch ");
+ if (!walker)
+ walker = get_http_walker(url, remote);
+ walker->get_all = 1;
+ walker->get_tree = 1;
+ walker->get_history = 1;
+ walker->get_verbosely = 0;
+ walker->get_recover = 0;
+ if (walker_fetch(walker, 1, &obj, NULL, NULL))
+ die("Fetch failed.");
+ printf("\n");
+ fflush(stdout);
+ } else if (!strcmp(buf.buf, "list")) {
+ struct ref *refs;
+ struct ref *posn;
+ if (!walker)
+ walker = get_http_walker(url, remote);
+ refs = get_refs(walker, url);
+ for (posn = refs; posn; posn = posn->next) {
+ if (posn->symref)
+ printf("@%s %s\n", posn->symref, posn->name);
+ else
+ printf("%s %s\n", sha1_to_hex(posn->old_sha1), posn->name);
+ }
+ printf("\n");
+ fflush(stdout);
+ } else if (!strcmp(buf.buf, "capabilities")) {
+ printf("fetch\n");
+ printf("\n");
+ fflush(stdout);
+ } else {
+ return 1;
+ }
+ strbuf_reset(&buf);
+ } while (1);
+ return 0;
+}
path = rr->items[i].string;
length = strlen(path) + 1;
if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
- write_in_full(out_fd, "\t", 1) != 1 ||
+ write_str_in_full(out_fd, "\t") != 1 ||
write_in_full(out_fd, path, length) != length)
die("unable to write rerere record");
}
if (cmd->dir)
die("chdir in start_command() not implemented");
- if (cmd->env) {
- env = copy_environ();
- for (; *cmd->env; cmd->env++)
- env = env_setenv(env, *cmd->env);
- }
+ if (cmd->env)
+ env = make_augmented_environ(cmd->env);
if (cmd->git_cmd) {
cmd->argv = prepare_git_cmd(cmd->argv);
test_cmp expected actual
'
+test_expect_success 'grep from a subdirectory to search wider area (1)' '
+ mkdir -p s &&
+ (
+ cd s && git grep "x x x" ..
+ )
+'
+
+test_expect_success 'grep from a subdirectory to search wider area (2)' '
+ mkdir -p s &&
+ (
+ cd s || exit 1
+ ( git grep xxyyzz .. >out ; echo $? >status )
+ ! test -s out &&
+ test 1 = $(cat status)
+ )
+'
+
test_done
)
'
+git --git-dir=x/.git config --unset svn.authorsfile
+git --git-dir=x/.git config --unset svn.authorsprog
+
+test_expect_success 'authors-prog handled special characters in username' '
+ svn mkdir -m bad --username "xyz; touch evil" "$svnrepo"/bad &&
+ (
+ cd x &&
+ git svn --authors-prog=../svn-authors-prog fetch &&
+ git rev-list -1 --pretty=raw refs/remotes/git-svn |
+ grep "^author xyz; touch evil <xyz; touch evil@example\.com> " &&
+ ! test -f evil
+ )
+'
+
test_done
--- /dev/null
+#include "cache.h"
+#include "transport.h"
+
+#include "run-command.h"
+#include "commit.h"
+#include "diff.h"
+#include "revision.h"
+
+struct helper_data
+{
+ const char *name;
+ struct child_process *helper;
+ unsigned fetch : 1;
+};
+
+static struct child_process *get_helper(struct transport *transport)
+{
+ struct helper_data *data = transport->data;
+ struct strbuf buf = STRBUF_INIT;
+ struct child_process *helper;
+ FILE *file;
+
+ if (data->helper)
+ return data->helper;
+
+ helper = xcalloc(1, sizeof(*helper));
+ helper->in = -1;
+ helper->out = -1;
+ helper->err = 0;
+ helper->argv = xcalloc(4, sizeof(*helper->argv));
+ strbuf_addf(&buf, "remote-%s", data->name);
+ helper->argv[0] = strbuf_detach(&buf, NULL);
+ helper->argv[1] = transport->remote->name;
+ helper->argv[2] = transport->url;
+ helper->git_cmd = 1;
+ if (start_command(helper))
+ die("Unable to run helper: git %s", helper->argv[0]);
+ data->helper = helper;
+
+ write_str_in_full(helper->in, "capabilities\n");
+
+ file = xfdopen(helper->out, "r");
+ while (1) {
+ if (strbuf_getline(&buf, file, '\n') == EOF)
+ exit(128); /* child died, message supplied already */
+
+ if (!*buf.buf)
+ break;
+ if (!strcmp(buf.buf, "fetch"))
+ data->fetch = 1;
+ }
+ return data->helper;
+}
+
+static int disconnect_helper(struct transport *transport)
+{
+ struct helper_data *data = transport->data;
+ if (data->helper) {
+ write_str_in_full(data->helper->in, "\n");
+ close(data->helper->in);
+ finish_command(data->helper);
+ free((char *)data->helper->argv[0]);
+ free(data->helper->argv);
+ free(data->helper);
+ data->helper = NULL;
+ }
+ return 0;
+}
+
+static int fetch_with_fetch(struct transport *transport,
+ int nr_heads, const struct ref **to_fetch)
+{
+ struct child_process *helper = get_helper(transport);
+ FILE *file = xfdopen(helper->out, "r");
+ int i;
+ struct strbuf buf = STRBUF_INIT;
+
+ for (i = 0; i < nr_heads; i++) {
+ const struct ref *posn = to_fetch[i];
+ if (posn->status & REF_STATUS_UPTODATE)
+ continue;
+
+ strbuf_addf(&buf, "fetch %s %s\n",
+ sha1_to_hex(posn->old_sha1), posn->name);
+ write_in_full(helper->in, buf.buf, buf.len);
+ strbuf_reset(&buf);
+
+ if (strbuf_getline(&buf, file, '\n') == EOF)
+ exit(128); /* child died, message supplied already */
+ }
+ return 0;
+}
+
+static int fetch(struct transport *transport,
+ int nr_heads, const struct ref **to_fetch)
+{
+ struct helper_data *data = transport->data;
+ int i, count;
+
+ count = 0;
+ for (i = 0; i < nr_heads; i++)
+ if (!(to_fetch[i]->status & REF_STATUS_UPTODATE))
+ count++;
+
+ if (!count)
+ return 0;
+
+ if (data->fetch)
+ return fetch_with_fetch(transport, nr_heads, to_fetch);
+
+ return -1;
+}
+
+static struct ref *get_refs_list(struct transport *transport, int for_push)
+{
+ struct child_process *helper;
+ struct ref *ret = NULL;
+ struct ref **tail = &ret;
+ struct ref *posn;
+ struct strbuf buf = STRBUF_INIT;
+ FILE *file;
+
+ helper = get_helper(transport);
+
+ write_str_in_full(helper->in, "list\n");
+
+ file = xfdopen(helper->out, "r");
+ while (1) {
+ char *eov, *eon;
+ if (strbuf_getline(&buf, file, '\n') == EOF)
+ exit(128); /* child died, message supplied already */
+
+ if (!*buf.buf)
+ break;
+
+ eov = strchr(buf.buf, ' ');
+ if (!eov)
+ die("Malformed response in ref list: %s", buf.buf);
+ eon = strchr(eov + 1, ' ');
+ *eov = '\0';
+ if (eon)
+ *eon = '\0';
+ *tail = alloc_ref(eov + 1);
+ if (buf.buf[0] == '@')
+ (*tail)->symref = xstrdup(buf.buf + 1);
+ else if (buf.buf[0] != '?')
+ get_sha1_hex(buf.buf, (*tail)->old_sha1);
+ tail = &((*tail)->next);
+ }
+ strbuf_release(&buf);
+
+ for (posn = ret; posn; posn = posn->next)
+ resolve_remote_symref(posn, ret);
+
+ return ret;
+}
+
+int transport_helper_init(struct transport *transport, const char *name)
+{
+ struct helper_data *data = xcalloc(sizeof(*data), 1);
+ data->name = name;
+
+ transport->data = data;
+ transport->get_refs_list = get_refs_list;
+ transport->fetch = fetch;
+ transport->disconnect = disconnect_helper;
+ return 0;
+}
#include "cache.h"
#include "transport.h"
#include "run-command.h"
-#ifndef NO_CURL
-#include "http.h"
-#endif
#include "pkt-line.h"
#include "fetch-pack.h"
#include "send-pack.h"
return result;
}
-/* Generic functions for using commit walkers */
-
-#ifndef NO_CURL /* http fetch is the only user */
-static int fetch_objs_via_walker(struct transport *transport,
- int nr_objs, const struct ref **to_fetch)
-{
- char *dest = xstrdup(transport->url);
- struct walker *walker = transport->data;
- char **objs = xmalloc(nr_objs * sizeof(*objs));
- int i;
-
- walker->get_all = 1;
- walker->get_tree = 1;
- walker->get_history = 1;
- walker->get_verbosely = transport->verbose >= 0;
- walker->get_recover = 0;
-
- for (i = 0; i < nr_objs; i++)
- objs[i] = xstrdup(sha1_to_hex(to_fetch[i]->old_sha1));
-
- if (walker_fetch(walker, nr_objs, objs, NULL, NULL))
- die("Fetch failed.");
-
- for (i = 0; i < nr_objs; i++)
- free(objs[i]);
- free(objs);
- free(dest);
- return 0;
-}
-#endif /* NO_CURL */
-
-static int disconnect_walker(struct transport *transport)
-{
- struct walker *walker = transport->data;
- if (walker)
- walker_free(walker);
- return 0;
-}
-
#ifndef NO_CURL
static int curl_transport_push(struct transport *transport, int refspec_nr, const char **refspec, int flags)
{
return !!run_command_v_opt(argv, RUN_GIT_CMD);
}
-static struct ref *get_refs_via_curl(struct transport *transport, int for_push)
-{
- struct strbuf buffer = STRBUF_INIT;
- char *data, *start, *mid;
- char *ref_name;
- char *refs_url;
- int i = 0;
- int http_ret;
-
- struct ref *refs = NULL;
- struct ref *ref = NULL;
- struct ref *last_ref = NULL;
-
- struct walker *walker;
-
- if (for_push)
- return NULL;
-
- if (!transport->data)
- transport->data = get_http_walker(transport->url,
- transport->remote);
-
- walker = transport->data;
-
- refs_url = xmalloc(strlen(transport->url) + 11);
- sprintf(refs_url, "%s/info/refs", transport->url);
-
- http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
- switch (http_ret) {
- case HTTP_OK:
- break;
- case HTTP_MISSING_TARGET:
- die("%s not found: did you run git update-server-info on the"
- " server?", refs_url);
- default:
- http_error(refs_url, http_ret);
- die("HTTP request failed");
- }
-
- data = buffer.buf;
- start = NULL;
- mid = data;
- while (i < buffer.len) {
- if (!start)
- start = &data[i];
- if (data[i] == '\t')
- mid = &data[i];
- if (data[i] == '\n') {
- data[i] = 0;
- ref_name = mid + 1;
- ref = xmalloc(sizeof(struct ref) +
- strlen(ref_name) + 1);
- memset(ref, 0, sizeof(struct ref));
- strcpy(ref->name, ref_name);
- get_sha1_hex(start, ref->old_sha1);
- if (!refs)
- refs = ref;
- if (last_ref)
- last_ref->next = ref;
- last_ref = ref;
- start = NULL;
- }
- i++;
- }
-
- strbuf_release(&buffer);
-
- ref = alloc_ref("HEAD");
- if (!walker->fetch_ref(walker, ref) &&
- !resolve_remote_symref(ref, refs)) {
- ref->next = refs;
- refs = ref;
- } else {
- free(ref);
- }
-
- strbuf_release(&buffer);
- free(refs_url);
- return refs;
-}
-
-static int fetch_objs_via_curl(struct transport *transport,
- int nr_objs, const struct ref **to_fetch)
-{
- if (!transport->data)
- transport->data = get_http_walker(transport->url,
- transport->remote);
- return fetch_objs_via_walker(transport, nr_objs, to_fetch);
-}
-
#endif
struct bundle_transport_data {
} else if (!prefixcmp(url, "http://")
|| !prefixcmp(url, "https://")
|| !prefixcmp(url, "ftp://")) {
+ transport_helper_init(ret, "curl");
#ifdef NO_CURL
error("git was compiled without libcurl support.");
#else
- ret->get_refs_list = get_refs_via_curl;
- ret->fetch = fetch_objs_via_curl;
ret->push = curl_transport_push;
#endif
- ret->disconnect = disconnect_walker;
} else if (is_local(url) && is_file(url)) {
struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
int transport_disconnect(struct transport *transport);
char *transport_anonymize_url(const char *url);
+/* Transport methods defined outside transport.c */
+int transport_helper_init(struct transport *transport, const char *name);
+
#endif
int i;
struct rev_info revs;
- pack_pipe = fdopen(fd, "w");
+ pack_pipe = xfdopen(fd, "w");
init_revisions(&revs, NULL);
revs.tag_objects = 1;
revs.tree_objects = 1;
/* pass on revisions we (don't) want */
if (!shallow_nr) {
- FILE *pipe_fd = fdopen(pack_objects.in, "w");
+ FILE *pipe_fd = xfdopen(pack_objects.in, "w");
if (!create_full_pack) {
int i;
for (i = 0; i < want_obj.nr; i++)
shallow_nr = 0;
if (debug_fd)
- write_in_full(debug_fd, "#S\n", 3);
+ write_str_in_full(debug_fd, "#S\n");
for (;;) {
struct object *o;
unsigned char sha1_buf[20];
}
}
if (debug_fd)
- write_in_full(debug_fd, "#E\n", 3);
+ write_str_in_full(debug_fd, "#E\n");
if (!use_sideband && daemon_mode)
no_progress = 1;