* Re: packs and trees
From: Linus Torvalds @ 2006-06-21 3:54 UTC (permalink / raw)
To: Martin Langhoff; +Cc: Nicolas Pitre, Jon Smirl, git
In-Reply-To: <46a038f90606201241x3dec242dicde245a24c3ab9ab@mail.gmail.com>
On Wed, 21 Jun 2006, Martin Langhoff wrote:
>
> If you are asking about the ext3 performance problems, I think Linus
> discussed that a while ago, why unpacked repos are slow (in addition
> to huge), and there were some suggestions of using hashed directory
> indexes.
Yes. I think most distros still default to nonhashed directories, but for
any large-directory case you really want to turn on hashing.
I forget the exact details, it's somethng like
tune2fs -O dir_index
or something to turn it on (if I remember correctly, that will only affect
any directories then created after that, but you can effect that by just
doing a "git repack -a -d" which will remove all old object directories,
and now subsequent directories will be done with indexing on).
Personally, I just ended up using packs extensively, so I think I'm still
running without indexing on all my machines ;)
Linus
^ permalink raw reply
* Re: [PATCH 1/3] gitweb: whitespace cleanup
From: Jakub Narebski @ 2006-06-21 8:05 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <11508760842024-git-send-email-jnareb@gmail.com>
Jakub Narebski <jnareb@gmail.com> wrote:
>
> Signed-off-by: Jakub Narebski <jnareb.com>
It should be of course
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
Somehow cover letter got lost, and patches did not appear on mailing
list archives.
If the mail will not appear in few hours, I'll resend it to mailing list only.
Probably because git-send-email should ensure LC_ALL=C for Date:
header generation...
--
Jakub Narebski
ShadeHawk on #git
^ permalink raw reply
* [PATCH 1/4] upload-pack: avoid sending an incomplete pack upon failure
From: Junio C Hamano @ 2006-06-21 8:12 UTC (permalink / raw)
To: git
When the repository on the remote side is corrupted, rev-list
spawned from upload-pack would die with error, but pack-objects
that reads from the rev-list happily created a packfile that can
be unpacked by the downloader. When this happens, the resulting
packfile is not corrupted and unpacks cleanly, but the list of
the objects contained in it is not what the protocol exchange
computed.
This update makes upload-pack to monitor its subprocesses, and
when either of them dies with error, sends an incomplete pack
data to the downloader to cause it to fail.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* This is about "upload-pack is unsafe in corrupt repository"
message I sent about 20 hours ago.
upload-pack.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 163 insertions(+), 14 deletions(-)
diff --git a/upload-pack.c b/upload-pack.c
index 979e583..a9a8f2e 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -5,6 +5,9 @@ #include "tag.h"
#include "object.h"
#include "commit.h"
#include "exec_cmd.h"
+#include <signal.h>
+#include <sys/poll.h>
+#include <sys/wait.h>
static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=nn] <dir>";
@@ -33,17 +36,20 @@ static int strip(char *line, int len)
static void create_pack_file(void)
{
- int fd[2];
- pid_t pid;
+ /* Pipes between rev-list to pack-objects and pack-objects to us. */
+ int lp_pipe[2], pu_pipe[2];
+ pid_t pid_rev_list, pid_pack_objects;
int create_full_pack = (nr_our_refs == nr_needs && !nr_has);
+ char data[8193];
+ int buffered = -1;
- if (pipe(fd) < 0)
+ if (pipe(lp_pipe) < 0)
die("git-upload-pack: unable to create pipe");
- pid = fork();
- if (pid < 0)
+ pid_rev_list = fork();
+ if (pid_rev_list < 0)
die("git-upload-pack: unable to fork git-rev-list");
- if (!pid) {
+ if (!pid_rev_list) {
int i;
int args;
const char **argv;
@@ -60,10 +66,10 @@ static void create_pack_file(void)
argv = (const char **) p;
buf = xmalloc(args * 45);
- dup2(fd[1], 1);
+ dup2(lp_pipe[1], 1);
close(0);
- close(fd[0]);
- close(fd[1]);
+ close(lp_pipe[0]);
+ close(lp_pipe[1]);
*p++ = "rev-list";
*p++ = use_thin_pack ? "--objects-edge" : "--objects";
if (create_full_pack || MAX_NEEDS <= nr_needs)
@@ -86,11 +92,154 @@ static void create_pack_file(void)
execv_git_cmd(argv);
die("git-upload-pack: unable to exec git-rev-list");
}
- dup2(fd[0], 0);
- close(fd[0]);
- close(fd[1]);
- execl_git_cmd("pack-objects", "--stdout", NULL);
- die("git-upload-pack: unable to exec git-pack-objects");
+
+ if (pipe(pu_pipe) < 0)
+ die("git-upload-pack: unable to create pipe");
+ pid_pack_objects = fork();
+ if (pid_pack_objects < 0) {
+ /* daemon sets things up to ignore TERM */
+ kill(pid_rev_list, SIGKILL);
+ die("git-upload-pack: unable to fork git-pack-objects");
+ }
+ if (!pid_pack_objects) {
+ dup2(lp_pipe[0], 0);
+ dup2(pu_pipe[1], 1);
+
+ close(lp_pipe[0]);
+ close(lp_pipe[1]);
+ close(pu_pipe[0]);
+ close(pu_pipe[1]);
+ execl_git_cmd("pack-objects", "--stdout", NULL);
+ kill(pid_rev_list, SIGKILL);
+ die("git-upload-pack: unable to exec git-pack-objects");
+ }
+
+ close(lp_pipe[0]);
+ close(lp_pipe[1]);
+
+ /* We read from pu_pipe[0] to capture the pack data.
+ */
+ close(pu_pipe[1]);
+
+ while (1) {
+ const char *who;
+ struct pollfd pfd[2];
+ pid_t pid;
+ int status;
+ ssize_t sz;
+ int pu, pollsize;
+
+ pollsize = 0;
+ pu = -1;
+
+ if (0 <= pu_pipe[0]) {
+ pfd[pollsize].fd = pu_pipe[0];
+ pfd[pollsize].events = POLLIN;
+ pu = pollsize;
+ pollsize++;
+ }
+
+ if (pollsize) {
+ if (poll(pfd, pollsize, -1) < 0) {
+ if (errno != EINTR) {
+ error("poll failed, resuming: %s",
+ strerror(errno));
+ sleep(1);
+ }
+ continue;
+ }
+ if (0 <= pu && (pfd[pu].revents & (POLLIN|POLLHUP))) {
+ /* Data ready; we keep the last byte
+ * to ourselves in case we detect
+ * broken rev-list, so that we can
+ * leave the stream corrupted. This
+ * is unfortunate -- unpack-objects
+ * would happily accept a valid pack
+ * data with trailing garbage, so
+ * appending garbage after we pass all
+ * the pack data is not good enough to
+ * signal breakage to downstream.
+ */
+ char *cp = data;
+ ssize_t outsz = 0;
+ if (0 <= buffered) {
+ *cp++ = buffered;
+ outsz++;
+ }
+ sz = read(pu_pipe[0], cp,
+ sizeof(data) - outsz);
+ if (0 < sz)
+ ;
+ else if (sz == 0) {
+ close(pu_pipe[0]);
+ pu_pipe[0] = -1;
+ }
+ else
+ goto fail;
+ sz += outsz;
+ if (1 < sz) {
+ buffered = data[sz-1] & 0xFF;
+ sz--;
+ }
+ else
+ buffered = -1;
+ sz = xwrite(1, data, sz);
+ if (sz < 0)
+ goto fail;
+ }
+ }
+
+ /* See if the children are still there */
+ if (pid_rev_list || pid_pack_objects) {
+ pid = waitpid(-1, &status, WNOHANG);
+ if (!pid)
+ continue;
+ who = ((pid == pid_rev_list) ? "git-rev-list" :
+ (pid == pid_pack_objects) ? "git-pack-objects" :
+ NULL);
+ if (!who) {
+ if (pid < 0) {
+ error("git-upload-pack: %s",
+ strerror(errno));
+ goto fail;
+ }
+ error("git-upload-pack: we weren't "
+ "waiting for %d", pid);
+ continue;
+ }
+ if (!WIFEXITED(status) || WEXITSTATUS(status) > 0) {
+ error("git-upload-pack: %s died with error.",
+ who);
+ goto fail;
+ }
+ if (pid == pid_rev_list)
+ pid_rev_list = 0;
+ if (pid == pid_pack_objects)
+ pid_pack_objects = 0;
+ if (pid_rev_list || pid_pack_objects)
+ continue;
+ }
+
+ /* both died happily */
+ if (pollsize)
+ continue;
+
+ /* flush the data */
+ if (0 <= buffered) {
+ data[0] = buffered;
+ sz = xwrite(1, data, 1);
+ if (sz < 0)
+ goto fail;
+ fprintf(stderr, "flushed.\n");
+ }
+ return;
+ }
+ fail:
+ if (pid_pack_objects)
+ kill(pid_pack_objects, SIGKILL);
+ if (pid_rev_list)
+ kill(pid_rev_list, SIGKILL);
+ die("git-upload-pack: aborting due to possible repository corruption on the remote side.");
}
static int got_sha1(char *hex, unsigned char *sha1)
--
1.4.0.gbb3f
^ permalink raw reply related
* [PATCH 2/4] upload-pack: prepare for sideband message support.
From: Junio C Hamano @ 2006-06-21 8:12 UTC (permalink / raw)
To: git
This does not implement sideband for propagating the status to
the downloader yet, but add code to capture the standard error
output from the pack-objects process in preparation for sending
it off to the client when the protocol extension allows us to do
so.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
pack-objects.c | 4 ++++
upload-pack.c | 46 +++++++++++++++++++++++++++++++++++++++-------
2 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/pack-objects.c b/pack-objects.c
index 179560f..7a8c16c 100644
--- a/pack-objects.c
+++ b/pack-objects.c
@@ -1221,6 +1221,10 @@ int main(int argc, char **argv)
local = 1;
continue;
}
+ if (!strcmp("--progress", arg)) {
+ progress = 1;
+ continue;
+ }
if (!strcmp("--incremental", arg)) {
incremental = 1;
continue;
diff --git a/upload-pack.c b/upload-pack.c
index a9a8f2e..13eaa22 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -36,11 +36,13 @@ static int strip(char *line, int len)
static void create_pack_file(void)
{
- /* Pipes between rev-list to pack-objects and pack-objects to us. */
- int lp_pipe[2], pu_pipe[2];
+ /* Pipes between rev-list to pack-objects, pack-objects to us
+ * and pack-objects error stream for progress bar.
+ */
+ int lp_pipe[2], pu_pipe[2], pe_pipe[2];
pid_t pid_rev_list, pid_pack_objects;
int create_full_pack = (nr_our_refs == nr_needs && !nr_has);
- char data[8193];
+ char data[8193], progress[128];
int buffered = -1;
if (pipe(lp_pipe) < 0)
@@ -95,6 +97,8 @@ static void create_pack_file(void)
if (pipe(pu_pipe) < 0)
die("git-upload-pack: unable to create pipe");
+ if (pipe(pe_pipe) < 0)
+ die("git-upload-pack: unable to create pipe");
pid_pack_objects = fork();
if (pid_pack_objects < 0) {
/* daemon sets things up to ignore TERM */
@@ -104,12 +108,15 @@ static void create_pack_file(void)
if (!pid_pack_objects) {
dup2(lp_pipe[0], 0);
dup2(pu_pipe[1], 1);
+ dup2(pe_pipe[1], 2);
close(lp_pipe[0]);
close(lp_pipe[1]);
close(pu_pipe[0]);
close(pu_pipe[1]);
- execl_git_cmd("pack-objects", "--stdout", NULL);
+ close(pe_pipe[0]);
+ close(pe_pipe[1]);
+ execl_git_cmd("pack-objects", "--stdout", "--progress", NULL);
kill(pid_rev_list, SIGKILL);
die("git-upload-pack: unable to exec git-pack-objects");
}
@@ -117,20 +124,23 @@ static void create_pack_file(void)
close(lp_pipe[0]);
close(lp_pipe[1]);
- /* We read from pu_pipe[0] to capture the pack data.
+ /* We read from pe_pipe[0] to capture stderr output for
+ * progress bar, and pu_pipe[0] to capture the pack data.
*/
+ close(pe_pipe[1]);
close(pu_pipe[1]);
while (1) {
const char *who;
+ char *cp;
struct pollfd pfd[2];
pid_t pid;
int status;
ssize_t sz;
- int pu, pollsize;
+ int pe, pu, pollsize;
pollsize = 0;
- pu = -1;
+ pe = pu = -1;
if (0 <= pu_pipe[0]) {
pfd[pollsize].fd = pu_pipe[0];
@@ -138,6 +148,12 @@ static void create_pack_file(void)
pu = pollsize;
pollsize++;
}
+ if (0 <= pe_pipe[0]) {
+ pfd[pollsize].fd = pe_pipe[0];
+ pfd[pollsize].events = POLLIN;
+ pe = pollsize;
+ pollsize++;
+ }
if (pollsize) {
if (poll(pfd, pollsize, -1) < 0) {
@@ -187,6 +203,22 @@ static void create_pack_file(void)
if (sz < 0)
goto fail;
}
+ if (0 <= pe && (pfd[pe].revents & (POLLIN|POLLHUP))) {
+ /* Status ready; we do not use it for now,
+ * but later we will add side-band to send it
+ * to the other side.
+ */
+ sz = read(pe_pipe[0], progress,
+ sizeof(progress));
+ if (0 < sz)
+ write(2, progress, sz);
+ else if (sz == 0) {
+ close(pe_pipe[0]);
+ pe_pipe[0] = -1;
+ }
+ else
+ goto fail;
+ }
}
/* See if the children are still there */
--
1.4.0.gbb3f
^ permalink raw reply related
* [PATCH 3/4] Retire git-clone-pack
From: Junio C Hamano @ 2006-06-21 8:14 UTC (permalink / raw)
To: git
The program is not used by git-clone since git-fetch-pack was extended
to allow its caller do what git-clone-pack alone did, and git-clone was
updated to use it.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* Logically this does not belong to the series, but retiring
clone-pack lets me get away without having to update the
callers of the function I'll be updating in the next one.
.gitignore | 1
Documentation/git-clone-pack.txt | 64 ------------
Documentation/git-clone.txt | 4 -
Documentation/git-receive-pack.txt | 3 -
Documentation/git-upload-pack.txt | 2
Documentation/git.txt | 6 -
INSTALL | 2
Makefile | 2
clone-pack.c | 186 ------------------------------------
9 files changed, 7 insertions(+), 263 deletions(-)
diff --git a/.gitignore b/.gitignore
index afd0876..65aa939 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,7 +17,6 @@ git-cherry
git-cherry-pick
git-clean
git-clone
-git-clone-pack
git-commit
git-commit-tree
git-convert-objects
diff --git a/Documentation/git-clone-pack.txt b/Documentation/git-clone-pack.txt
deleted file mode 100644
index 09f43ee..0000000
--- a/Documentation/git-clone-pack.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-git-clone-pack(1)
-=================
-
-NAME
-----
-git-clone-pack - Clones a repository by receiving packed objects
-
-
-SYNOPSIS
---------
-'git-clone-pack' [--exec=<git-upload-pack>] [<host>:]<directory> [<head>...]
-
-DESCRIPTION
------------
-Clones a repository into the current repository by invoking
-'git-upload-pack', possibly on the remote host via ssh, in
-the named repository, and stores the sent pack in the local
-repository.
-
-OPTIONS
--------
---exec=<git-upload-pack>::
- Use this to specify the path to 'git-upload-pack' on the
- remote side, if it is not found on your $PATH.
- Installations of sshd ignore the user's environment
- setup scripts for login shells (e.g. .bash_profile) and
- your privately installed git may not be found on the system
- default $PATH. Another workaround suggested is to set
- up your $PATH in ".bashrc", but this flag is for people
- who do not want to pay the overhead for non-interactive
- shells by having a lean .bashrc file (they set most of
- the things up in .bash_profile).
-
-<host>::
- A remote host that houses the repository. When this
- part is specified, 'git-upload-pack' is invoked via
- ssh.
-
-<directory>::
- The repository to sync from.
-
-<head>...::
- The heads to update. This is relative to $GIT_DIR
- (e.g. "HEAD", "refs/heads/master"). When unspecified,
- all heads are updated to match the remote repository.
-+
-Usually all the refs from existing repository are stored
-under the same name in the new repository. Giving explicit
-<head> arguments instead writes the object names and refs to
-the standard output, just like get-fetch-pack does.
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
-
-GIT
----
-Part of the gitlink:git[7] suite
-
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index a90521e..f973c64 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -62,7 +62,7 @@ OPTIONS
--quiet::
-q::
Operate quietly. This flag is passed to "rsync" and
- "git-clone-pack" commands when given.
+ "git-fetch-pack" commands when given.
-n::
No checkout of HEAD is performed after the clone is complete.
@@ -85,7 +85,7 @@ OPTIONS
--upload-pack <upload-pack>::
-u <upload-pack>::
When given, and the repository to clone from is handled
- by 'git-clone-pack', '--exec=<upload-pack>' is passed to
+ by 'git-fetch-pack', '--exec=<upload-pack>' is passed to
the command to specify non-default path for the command
run on the other end.
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index 60debca..f9457d4 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -18,8 +18,7 @@ information fed from the remote end.
This command is usually not invoked directly by the end user.
The UI for the protocol is on the 'git-send-pack' side, and the
program pair is meant to be used to push updates to remote
-repository. For pull operations, see 'git-fetch-pack' and
-'git-clone-pack'.
+repository. For pull operations, see 'git-fetch-pack'.
The command allows for creation and fast forwarding of sha1 refs
(heads/tags) on the remote end (strictly speaking, it is the
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index 4795e98..b2c9307 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -12,7 +12,7 @@ SYNOPSIS
DESCRIPTION
-----------
-Invoked by 'git-clone-pack' and/or 'git-fetch-pack', learns what
+Invoked by 'git-fetch-pack', learns what
objects the other side is missing, and sends them after packing.
This command is usually not invoked directly by the end user.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index d4472b5..51f20c6 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -192,10 +192,6 @@ the working tree.
Synching repositories
~~~~~~~~~~~~~~~~~~~~~
-gitlink:git-clone-pack[1]::
- Clones a repository into the current repository (engine
- for ssh and local transport).
-
gitlink:git-fetch-pack[1]::
Updates from a remote repository (engine for ssh and
local transport).
@@ -237,7 +233,7 @@ gitlink:git-update-server-info[1]::
clients discover references and packs on it.
gitlink:git-upload-pack[1]::
- Invoked by 'git-clone-pack' and 'git-fetch-pack' to push
+ Invoked by 'git-fetch-pack' to push
what are asked for.
gitlink:git-upload-tar[1]::
diff --git a/INSTALL b/INSTALL
index 63af8ec..f8337e2 100644
--- a/INSTALL
+++ b/INSTALL
@@ -96,7 +96,7 @@ Issues of note:
$ mkdir manual && cd manual
$ git init-db
- $ git clone-pack git://git.kernel.org/pub/scm/git/git.git man html |
+ $ git fetch-pack git://git.kernel.org/pub/scm/git/git.git man html |
while read a b
do
echo $a >.git/$b
diff --git a/Makefile b/Makefile
index 0887945..ae5e8d7 100644
--- a/Makefile
+++ b/Makefile
@@ -149,7 +149,7 @@ SIMPLE_PROGRAMS = \
# ... and all the rest that could be moved out of bindir to gitexecdir
PROGRAMS = \
- git-checkout-index$X git-clone-pack$X \
+ git-checkout-index$X \
git-convert-objects$X git-fetch-pack$X git-fsck-objects$X \
git-hash-object$X git-index-pack$X git-local-fetch$X \
git-mailinfo$X git-merge-base$X \
diff --git a/clone-pack.c b/clone-pack.c
deleted file mode 100644
index a4370f5..0000000
--- a/clone-pack.c
+++ /dev/null
@@ -1,186 +0,0 @@
-#include "cache.h"
-#include "refs.h"
-#include "pkt-line.h"
-
-static const char clone_pack_usage[] =
-"git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
-static const char *exec = "git-upload-pack";
-
-static int quiet = 0;
-
-static void clone_handshake(int fd[2], struct ref *ref)
-{
- unsigned char sha1[20];
-
- while (ref) {
- packet_write(fd[1], "want %s\n", sha1_to_hex(ref->old_sha1));
- ref = ref->next;
- }
- packet_flush(fd[1]);
-
- /* We don't have nuttin' */
- packet_write(fd[1], "done\n");
- if (get_ack(fd[0], sha1))
- error("Huh! git-clone-pack got positive ack for %s", sha1_to_hex(sha1));
-}
-
-static int is_master(struct ref *ref)
-{
- return !strcmp(ref->name, "refs/heads/master");
-}
-
-static void write_one_ref(struct ref *ref)
-{
- char *path = git_path("%s", ref->name);
- int fd;
- char *hex;
-
- if (!strncmp(ref->name, "refs/", 5) &&
- check_ref_format(ref->name + 5)) {
- error("refusing to create funny ref '%s' locally", ref->name);
- return;
- }
-
- if (safe_create_leading_directories(path))
- die("unable to create leading directory for %s", ref->name);
- fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0666);
- if (fd < 0)
- die("unable to create ref %s", ref->name);
- hex = sha1_to_hex(ref->old_sha1);
- hex[40] = '\n';
- if (write(fd, hex, 41) != 41)
- die("unable to write ref %s", ref->name);
- close(fd);
-}
-
-static void write_refs(struct ref *ref)
-{
- struct ref *head = NULL, *head_ptr, *master_ref;
- char *head_path;
-
- /* Upload-pack must report HEAD first */
- if (!strcmp(ref->name, "HEAD")) {
- head = ref;
- ref = ref->next;
- }
- head_ptr = NULL;
- master_ref = NULL;
- while (ref) {
- if (is_master(ref))
- master_ref = ref;
- if (head &&
- !memcmp(ref->old_sha1, head->old_sha1, 20) &&
- !strncmp(ref->name, "refs/heads/",11) &&
- (!head_ptr || ref == master_ref))
- head_ptr = ref;
-
- write_one_ref(ref);
- ref = ref->next;
- }
- if (!head) {
- fprintf(stderr, "No HEAD in remote.\n");
- return;
- }
-
- head_path = strdup(git_path("HEAD"));
- if (!head_ptr) {
- /*
- * If we had a master ref, and it wasn't HEAD, we need to undo the
- * symlink, and write a standalone HEAD. Give a warning, because that's
- * really really wrong.
- */
- if (master_ref) {
- error("HEAD doesn't point to any refs! Making standalone HEAD");
- unlink(head_path);
- }
- write_one_ref(head);
- free(head_path);
- return;
- }
-
- /* We reset to the master branch if it's available */
- if (master_ref)
- return;
-
- fprintf(stderr, "Setting HEAD to %s\n", head_ptr->name);
-
- /*
- * Uhhuh. Other end didn't have master. We start HEAD off with
- * the first branch with the same value.
- */
- if (create_symref(head_path, head_ptr->name) < 0)
- die("unable to link HEAD to %s", head_ptr->name);
- free(head_path);
-}
-
-static int clone_pack(int fd[2], int nr_match, char **match)
-{
- struct ref *refs;
- int status;
-
- get_remote_heads(fd[0], &refs, nr_match, match, 1);
- if (!refs) {
- packet_flush(fd[1]);
- die("no matching remote head");
- }
- clone_handshake(fd, refs);
-
- status = receive_keep_pack(fd, "git-clone-pack", quiet);
- if (!quiet)
- fprintf(stderr, "\n");
-
- if (!status) {
- if (nr_match == 0)
- write_refs(refs);
- else
- while (refs) {
- printf("%s %s\n",
- sha1_to_hex(refs->old_sha1),
- refs->name);
- refs = refs->next;
- }
- }
- return status;
-}
-
-int main(int argc, char **argv)
-{
- int i, ret, nr_heads;
- char *dest = NULL, **heads;
- int fd[2];
- pid_t pid;
-
- setup_git_directory();
-
- nr_heads = 0;
- heads = NULL;
- for (i = 1; i < argc; i++) {
- char *arg = argv[i];
-
- if (*arg == '-') {
- if (!strcmp("-q", arg)) {
- quiet = 1;
- continue;
- }
- if (!strncmp("--exec=", arg, 7)) {
- exec = arg + 7;
- continue;
- }
- usage(clone_pack_usage);
- }
- dest = arg;
- heads = argv + i + 1;
- nr_heads = argc - i - 1;
- break;
- }
- if (!dest)
- usage(clone_pack_usage);
- pid = git_connect(fd, dest, exec);
- if (pid < 0)
- return 1;
- ret = clone_pack(fd, nr_heads, heads);
- close(fd[0]);
- close(fd[1]);
- finish_connect(pid);
- return ret;
-}
--
1.4.0.gbb3f
^ permalink raw reply related
* Re: [RFC] gitweb wishlist and TODO list
From: Josef Weidendorfer @ 2006-06-21 8:56 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Michael Gernoth
In-Reply-To: <20060620215331.GB25183@cip.informatik.uni-erlangen.de>
On Tuesday 20 June 2006 23:53, you wrote:
> he didn't do so far. So I use this opportunity. Maybe something else
> would be much more handier: Use gitweb to request the log and shortlog
> of a directory tree, like git-whatchanged arch/i386 does for example.
> Maybe it is already possible and I missed it?
There aren't any links, but:
On the bottom of a commit, you can click on "history" for blobs.
Changing the URL afterwards (the f= arg) can give you the history of
a directory.
I just tried, and in fact it works. But "Diff to current" does not
work for directories.
It would be nice to have a list of the files in the directory
touched by the given commits.
Josef
^ permalink raw reply
* [PATCH] Fix possible out-of-bounds array access
From: Uwe Zeisberger @ 2006-06-21 9:04 UTC (permalink / raw)
To: git
In-Reply-To: <20060620160836.GA20153@informatik.uni-freiburg.de>
If match is "", match[-1] is accessed. Let pathspec_matches return 1 in that
case indicating that "" matches everything.
Incidently this fixes git-grep'ing in ".".
Signed-off-by: Uwe Zeisberger <Uwe_Zeisberger@digi.com>
---
builtin-grep.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/builtin-grep.c b/builtin-grep.c
index 9806499..f7767bb 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -29,10 +29,11 @@ static int pathspec_matches(const char *
int matchlen = strlen(match);
const char *cp, *meta;
- if ((matchlen <= namelen) &&
- !strncmp(name, match, matchlen) &&
- (match[matchlen-1] == '/' ||
- name[matchlen] == '\0' || name[matchlen] == '/'))
+ if (!matchlen ||
+ ((matchlen <= namelen) &&
+ !strncmp(name, match, matchlen) &&
+ (match[matchlen-1] == '/' ||
+ name[matchlen] == '\0' || name[matchlen] == '/')))
return 1;
if (!fnmatch(match, name, 0))
return 1;
--
1.4.0
--
Uwe Zeisberger
http://www.google.com/search?q=12+mol+in+dozen
^ permalink raw reply related
* Re: [PATCH 0/3] Minor gitweb modifications and cleanups
From: Junio C Hamano @ 2006-06-21 9:04 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <11508760843417-git-send-email-jnareb@gmail.com>
Jakub Narebski <jnareb@gmail.com> writes:
> This series of patches is based on git.git 'next' branch
> 69d830d1a3a1236036bd0f84dd9794d7c8d34b3f
>
> My future gitweb-related batches will be based on this series.
>
> ---
>
> gitweb/gitweb.cgi | 53 +++++++++++++++++++++++++++++++----------------------
> gitweb/gitweb.css | 4 ++--
> 2 files changed, 33 insertions(+), 24 deletions(-)
>
> --
> Jakub Narebski
> Poland
All three applied cleanly (finally!), but with hand munging of
Date: field.
I think git-send-email should internally do LC_ALL=C or stop
using strftime() or both.
^ permalink raw reply
* [PATCH] send-email: Use setlocale in addition to $ENV{LC_ALL} to set locale
From: Jakub Narebski @ 2006-06-21 9:12 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
In-Reply-To: <7v3bdy5178.fsf@assigned-by-dhcp.cox.net>
$ENV{LC_ALL} = 'C'; does not change locale used by strftime.
Use setlocale( LC_ALL, 'C' ); instead.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
git-send-email.perl | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
7c796152570e28d3f95c17e93864c6abc8edef24
diff --git a/git-send-email.perl b/git-send-email.perl
index 7b1cca7..56949dd 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -24,7 +24,8 @@ use Data::Dumper;
# most mail servers generate the Date: header, but not all...
$ENV{LC_ALL} = 'C';
-use POSIX qw/strftime/;
+use POSIX qw/strftime setlocale LC_ALL/;
+setlocale( &LC_ALL, 'C' );
my $have_email_valid = eval { require Email::Valid; 1 };
my $smtp;
--
1.3.0
^ permalink raw reply related
* Re: [RFC] gitweb wishlist and TODO list
From: Jakub Narebski @ 2006-06-21 9:15 UTC (permalink / raw)
To: git
In-Reply-To: <200606211056.10889.Josef.Weidendorfer@gmx.de>
Josef Weidendorfer wrote:
> It would be nice to have a list of the files in the directory
> touched by the given commits.
'commit' view gives at the bottom list of all files affected by given
commit. Is that what you wanted, or did you want 'blame' for directories
(trees)?
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* [PATCH 3/3] Move $gitbin earlier in gitweb.cgi
From: Jakub Narebski @ 2006-06-21 9:25 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
In-Reply-To: <1150881955505-git-send-email-jnareb@gmail.com>
(cherry picked from 9dca843086356b964f27d8fabe1e3c48074a9f02 commit)
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Cherry picked commit is from feature branch in my repository:
http://front.fuw.edu.pl/cgi-bin/jnareb/gitweb.cgi?p=git.git;a=summary
http://front.fuw.edu.pl/jnareb/scm/git.git/
gitweb/gitweb.cgi | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
f8bd1032e0d6ec88f540a820b4f5b4789562ee05
diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi
index 87ec565..ef7fcbd 100755
--- a/gitweb/gitweb.cgi
+++ b/gitweb/gitweb.cgi
@@ -22,13 +22,13 @@ my $my_url = $cgi->url();
my $my_uri = $cgi->url(-absolute => 1);
my $rss_link = "";
+# location of the git-core binaries
+my $gitbin = "/usr/bin";
+
# absolute fs-path which will be prepended to the project path
#my $projectroot = "/pub/scm";
my $projectroot = "/home/kay/public_html/pub/scm";
-# location of the git-core binaries
-my $gitbin = "/usr/bin";
-
# version of the git-core binaries
my $git_version = qx($gitbin/git --version);
if ($git_version =~ m/git version (.*)$/) {
--
1.3.0
^ permalink raw reply related
* [PATCH 0/3] Minor gitweb modifications and cleanups
From: Jakub Narebski @ 2006-06-21 9:25 UTC (permalink / raw)
To: git
This series of patches is based on git.git 'next' branch
69d830d1a3a1236036bd0f84dd9794d7c8d34b3f
My future gitweb-related batches will be based on this series.
---
gitweb/gitweb.cgi | 53 +++++++++++++++++++++++++++++++----------------------
gitweb/gitweb.css | 4 ++--
2 files changed, 33 insertions(+), 24 deletions(-)
--
Jakub Narebski
ShadeHawk on #git
(git-send-email 1.4.0 with setlocale patch)
^ permalink raw reply
* [PATCH 1/3] gitweb: whitespace cleanup
From: Jakub Narebski @ 2006-06-21 9:25 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
In-Reply-To: <1150881954924-git-send-email-jnareb@gmail.com>
Do not use tabs to align variable initialization (actually use
tabs only at the beginning of line, for code indent). Remove trailing
whitespace. Make whitespace usage more consistent.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
gitweb/gitweb.cgi | 38 +++++++++++++++++++-------------------
gitweb/gitweb.css | 4 ++--
2 files changed, 21 insertions(+), 21 deletions(-)
691405ab79e0dacbe3b96a404740faf3f10bffd7
diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi
index 44896bb..89224e6 100755
--- a/gitweb/gitweb.cgi
+++ b/gitweb/gitweb.cgi
@@ -17,33 +17,33 @@ use Fcntl ':mode';
binmode STDOUT, ':utf8';
my $cgi = new CGI;
-my $version = "267";
-my $my_url = $cgi->url();
-my $my_uri = $cgi->url(-absolute => 1);
-my $rss_link = "";
+my $version = "267";
+my $my_url = $cgi->url();
+my $my_uri = $cgi->url(-absolute => 1);
+my $rss_link = "";
# absolute fs-path which will be prepended to the project path
-#my $projectroot = "/pub/scm";
-my $projectroot = "/home/kay/public_html/pub/scm";
+#my $projectroot = "/pub/scm";
+my $projectroot = "/home/kay/public_html/pub/scm";
# location of the git-core binaries
-my $gitbin = "/usr/bin";
+my $gitbin = "/usr/bin";
# location for temporary files needed for diffs
-my $git_temp = "/tmp/gitweb";
+my $git_temp = "/tmp/gitweb";
# target of the home link on top of all pages
-my $home_link = $my_uri;
+my $home_link = $my_uri;
# html text to include at home page
-my $home_text = "indextext.html";
+my $home_text = "indextext.html";
# URI of default stylesheet
-my $stylesheet = "gitweb.css";
+my $stylesheet = "gitweb.css";
# source of projects list
-#my $projects_list = $projectroot;
-my $projects_list = "index/index.aux";
+#my $projects_list = $projectroot;
+my $projects_list = "index/index.aux";
# default blob_plain mimetype and default charset for text/plain blob
my $default_blob_plain_mimetype = 'text/plain';
@@ -51,7 +51,7 @@ my $default_text_plain_charset = undef;
# file to use for guessing MIME types before trying /etc/mime.types
# (relative to the current git repository)
-my $mimetypes_file = undef;
+my $mimetypes_file = undef;
# input validation and dispatch
@@ -349,7 +349,7 @@ sub git_footer_html {
sub die_error {
my $status = shift || "403 Forbidden";
- my $error = shift || "Malformed query, file missing or permission denied";
+ my $error = shift || "Malformed query, file missing or permission denied";
git_header_html($status);
print "<div class=\"page_body\">\n" .
@@ -1066,7 +1066,7 @@ sub git_summary {
"<td>";
if (length($co{'title_short'}) < length($co{'title'})) {
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list", -title => "$co{'title'}"},
- "<b>" . esc_html($co{'title_short'}) . "$ref</b>");
+ "<b>" . esc_html($co{'title_short'}) . "$ref</b>");
} else {
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit"), -class => "list"},
"<b>" . esc_html($co{'title'}) . "$ref</b>");
@@ -1124,7 +1124,7 @@ sub git_summary {
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'reftype'};h=$tag{'refid'}")}, $tag{'reftype'});
if ($tag{'reftype'} eq "commit") {
print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}")}, "shortlog") .
- " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log");
+ " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log");
}
print "</td>\n" .
"</tr>";
@@ -1362,7 +1362,7 @@ sub git_tags {
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=$tag{'reftype'};h=$tag{'refid'}")}, $tag{'reftype'});
if ($tag{'reftype'} eq "commit") {
print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog;h=$tag{'name'}")}, "shortlog") .
- " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log");
+ " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log;h=$tag{'refid'}")}, "log");
}
print "</td>\n" .
"</tr>";
@@ -1942,7 +1942,7 @@ sub git_commit {
"</td>" .
"</tr>\n";
}
- print "</table>".
+ print "</table>".
"</div>\n";
print "<div class=\"page_body\">\n";
my $comment = $co{'comment'};
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index ac6a3c7..98410f5 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -1,7 +1,7 @@
body {
font-family: sans-serif;
font-size: 12px;
- border:solid #d9d8d1;
+ border: solid #d9d8d1;
border-width: 1px;
margin: 10px;
background-color: #ffffff;
@@ -33,7 +33,7 @@ div.page_header a:hover {
}
div.page_nav {
- padding:8px;
+ padding: 8px;
}
div.page_nav a:visited {
--
1.3.0
^ permalink raw reply related
* [PATCH 2/3] Add git version to gitweb output
From: Jakub Narebski @ 2006-06-21 9:25 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
In-Reply-To: <115088195576-git-send-email-jnareb@gmail.com>
Add git-core binaries used version as the comment at the beginning of HTML
output, just below the comment with version of git web interface version.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
gitweb/gitweb.cgi | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
4434b02e9a56cf5d1939021b950bbe54240a413d
diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi
index 89224e6..87ec565 100755
--- a/gitweb/gitweb.cgi
+++ b/gitweb/gitweb.cgi
@@ -29,6 +29,14 @@ my $projectroot = "/home/kay/public_html
# location of the git-core binaries
my $gitbin = "/usr/bin";
+# version of the git-core binaries
+my $git_version = qx($gitbin/git --version);
+if ($git_version =~ m/git version (.*)$/) {
+ $git_version = $1;
+} else {
+ $git_version = "unknown";
+}
+
# location for temporary files needed for diffs
my $git_temp = "/tmp/gitweb";
@@ -288,11 +296,12 @@ sub git_header_html {
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
<!-- git web interface v$version, (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
+<!-- git core binaries version $git_version -->
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="robots" content="index, nofollow"/>
-<link rel="stylesheet" type="text/css" href="$stylesheet"/>
<title>$title</title>
+<link rel="stylesheet" type="text/css" href="$stylesheet"/>
$rss_link
</head>
<body>
@@ -816,7 +825,7 @@ sub git_get_project_config {
$key =~ s/^gitweb\.//;
return if ($key =~ m/\W/);
- my $val = qx(git-repo-config --get gitweb.$key);
+ my $val = qx($gitbin/git-repo-config --get gitweb.$key);
return ($val);
}
--
1.3.0
^ permalink raw reply related
* Re: [RFC] gitweb wishlist and TODO list
From: Josef Weidendorfer @ 2006-06-21 9:57 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <e7b2n4$hd8$1@sea.gmane.org>
On Wednesday 21 June 2006 11:15, you wrote:
> Josef Weidendorfer wrote:
>
> > It would be nice to have a list of the files in the directory
> > touched by the given commits.
>
> 'commit' view gives at the bottom list of all files affected by given
> commit.
Yup, but when you are interested in the history of changes to files in
a given directory, you also want to see the name of the changed files on
the same page, and not have to click on every commit to get the file names.
Besides, the "commit" view shows all changed files, and not only the ones
which are in the directory.
> Is that what you wanted, or did you want 'blame' for directories
> (trees)?
Could be interesting; but everytime I look at such a page in ViewCVS,
I want to have it sorted by time...
Josef
^ permalink raw reply
* Re: [PATCH] rebase: Allow merge strategies to be used when rebasing
From: Eric Wong @ 2006-06-21 10:01 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbqso95f3.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
>
> > Junio C Hamano <junkio@cox.net> wrote:
> >
> >> - You kept the original "format-patch piped to am" workflow
> >> optionally working.
> >
> > I left it as the default, too. I figured that it's best not
> > to change the default (and most likely faster) behavior of
> > something people rely on.
>
> I should have said: "You kept ... working, which is good".
>
> >> I think the three-way merge you would want here is not between B
> >> and G using E as the pivot, but between B and G using A as the
> >> pivot. That's how cherry-pick and revert works. I would
> >> leverage the interface that is one level lower for this -- the
> >> strategy modules themselves.
> >>
> >> git-merge-$strategy $cmt^ -- HEAD $cmt
> >
> > Changing the 'git-merge $strategy_args "rebase-merge: $cmt" HEAD "$cmt"'
> > line in call_merge() to this seems to have broken more tests.
>
> Oh, that is to be expected if you changed git-merge -s recursive
> with git-merge-recursive without other changes. The former
> makes a commit (which your original patch later used to create a
> separate commit chain and discarded); the latter does not make a
> commit but expects the caller to create a commit out of the
> resulting index file.
Oops, *smacks head*
> > I'm not an expert at merging strategies by any measure, I've just
> > trusted merge-recursive to Do The Right Thing(TM) more often than not,
> > and use rerere to avoid repeating work.
>
> I was originally hoping that rebasing would just be a matter of
> listing sequence of commits to be ported onto a new base and
> running "git-cherry-pick" on each of them in sequence. Now
> cherry-pick does not use merge machinery (hence does not use
> git-merge-recursive), but if we change that then updating rebase
> would be pretty much straightforward. It just needs a UI layer
> to guide the user through recovery process when the merge does
> not resolve cleanly in the middle, no?
Sounds workable right to me. But then again, a cherry-pick is also a
case of rebase on a single commit, so we could be using rebase (and its
recovery code) in cherry-pick, too, right?
--
Eric Wong
^ permalink raw reply
* [PATCH (fixed)] rebase: Allow merge strategies to be used when rebasing
From: Eric Wong @ 2006-06-21 10:04 UTC (permalink / raw)
To: Junio C Hamano, git; +Cc: Eric Wong
In-Reply-To: <20060621100138.GA15748@localdomain>
1 - is fixed for --onto usage.
2 - in the series is the test from Junio, so I'm not resending it:
Subject: [PATCH] Add renaming-rebase test.
3 - keeps the NO_PYTHON people happy
--
Eric Wong
^ permalink raw reply
* [PATCH 3/3] rebase: error out for NO_PYTHON if they use recursive merge
From: Eric Wong @ 2006-06-21 10:04 UTC (permalink / raw)
To: Junio C Hamano, git; +Cc: Eric Wong
In-Reply-To: <11508842842125-git-send-email-normalperson@yhbt.net>
recursive merge relies on Python, and we can't perform
rename-aware merges without the recursive merge. So bail out
before trying it.
The test won't work w/o recursive merge, either, so skip that,
too.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
git-rebase.sh | 9 +++++++++
t/t3402-rebase-merge.sh | 6 ++++++
2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/git-rebase.sh b/git-rebase.sh
index bce7bf8..b9ce112 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -300,6 +300,15 @@ then
exit $?
fi
+if test "@@NO_PYTHON@@" && test "$strategy" = "recursive"
+then
+ die 'The recursive merge strategy currently relies on Python,
+which this installation of git was not configured with. Please consider
+a different merge strategy (e.g. octopus, resolve, stupid, ours)
+or install Python and git with Python support.'
+
+fi
+
# start doing a rebase with git-merge
# this is rename-aware if the recursive (default) strategy is used
diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh
index 8c7a519..f1c1f35 100755
--- a/t/t3402-rebase-merge.sh
+++ b/t/t3402-rebase-merge.sh
@@ -7,6 +7,12 @@ test_description='git rebase --merge tes
. ./test-lib.sh
+if test "$no_python"; then
+ echo "Skipping: no python => no recursive merge"
+ test_done
+ exit 0
+fi
+
T="A quick brown fox
jumps over the lazy dog."
for i in 1 2 3 4 5 6 7 8 9 10
--
1.4.0.g65f3
^ permalink raw reply related
* [PATCH 1/3] rebase: Allow merge strategies to be used when rebasing
From: Eric Wong @ 2006-06-21 10:04 UTC (permalink / raw)
To: Junio C Hamano, git; +Cc: Eric Wong
In-Reply-To: <11508842824018-git-send-email-normalperson@yhbt.net>
This solves the problem of rebasing local commits against an
upstream that has renamed files.
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
Documentation/git-rebase.txt | 20 ++++
git-rebase.sh | 192 ++++++++++++++++++++++++++++++++++++++++--
2 files changed, 202 insertions(+), 10 deletions(-)
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 08ee4aa..c339c45 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -7,7 +7,7 @@ git-rebase - Rebase local commits to a n
SYNOPSIS
--------
-'git-rebase' [--onto <newbase>] <upstream> [<branch>]
+'git-rebase' [--merge] [--onto <newbase>] <upstream> [<branch>]
'git-rebase' --continue | --skip | --abort
@@ -106,6 +106,24 @@ OPTIONS
--abort::
Restore the original branch and abort the rebase operation.
+--skip::
+ Restart the rebasing process by skipping the current patch.
+ This does not work with the --merge option.
+
+--merge::
+ Use merging strategies to rebase. When the recursive (default) merge
+ strategy is used, this allows rebase to be aware of renames on the
+ upstream side.
+
+-s <strategy>, \--strategy=<strategy>::
+ Use the given merge strategy; can be supplied more than
+ once to specify them in the order they should be tried.
+ If there is no `-s` option, a built-in list of strategies
+ is used instead (`git-merge-recursive` when merging a single
+ head, `git-merge-octopus` otherwise). This implies --merge.
+
+include::merge-strategies.txt[]
+
NOTES
-----
When you rebase a branch, you are changing its history in a way that
diff --git a/git-rebase.sh b/git-rebase.sh
index e6b57b8..bce7bf8 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -34,7 +34,96 @@ When you have resolved this problem run
If you would prefer to skip this patch, instead run \"git rebase --skip\".
To restore the original branch and stop rebasing run \"git rebase --abort\".
"
+
+MRESOLVEMSG="
+When you have resolved this problem run \"git rebase --continue\".
+To restore the original branch and stop rebasing run \"git rebase --abort\".
+"
unset newbase
+strategy=recursive
+do_merge=
+dotest=$GIT_DIR/.dotest-merge
+prec=4
+
+continue_merge () {
+ test -n "$prev_head" || die "prev_head must be defined"
+ test -d "$dotest" || die "$dotest directory does not exist"
+
+ unmerged=$(git-ls-files -u)
+ if test -n "$unmerged"
+ then
+ echo "You still have unmerged paths in your index"
+ echo "did you forget update-index?"
+ die "$MRESOLVEMSG"
+ fi
+
+ if test -n "`git-diff-index HEAD`"
+ then
+ git-commit -C "`cat $dotest/current`"
+ else
+ echo "Previous merge succeeded automatically"
+ fi
+
+ prev_head=`git-rev-parse HEAD^0`
+
+ # save the resulting commit so we can read-tree on it later
+ echo "$prev_head" > "$dotest/`printf %0${prec}d $msgnum`.result"
+ echo "$prev_head" > "$dotest/prev_head"
+
+ # onto the next patch:
+ msgnum=$(($msgnum + 1))
+ printf "%0${prec}d" "$msgnum" > "$dotest/msgnum"
+}
+
+call_merge () {
+ cmt="$(cat $dotest/`printf %0${prec}d $1`)"
+ echo "$cmt" > "$dotest/current"
+ git-merge-$strategy "$cmt^" -- HEAD "$cmt"
+ rv=$?
+ case "$rv" in
+ 0)
+ git-commit -C "$cmt" || die "commit failed: $MRESOLVEMSG"
+ ;;
+ 1)
+ test -d "$GIT_DIR/rr-cache" && git-rerere
+ die "$MRESOLVEMSG"
+ ;;
+ 2)
+ echo "Strategy: $rv $strategy failed, try another" 1>&2
+ die "$MRESOLVEMSG"
+ ;;
+ *)
+ die "Unknown exit code ($rv) from command:" \
+ "git-merge-$strategy $cmt^ -- HEAD $cmt"
+ ;;
+ esac
+}
+
+finish_rb_merge () {
+ set -e
+
+ msgnum=1
+ echo "Finalizing rebased commits..."
+ git-reset --hard "`cat $dotest/onto`"
+ end="`cat $dotest/end`"
+ while test "$msgnum" -le "$end"
+ do
+ msgnum=`printf "%0${prec}d" "$msgnum"`
+ printf "%0${prec}d" "$msgnum" > "$dotest/msgnum"
+
+ git-read-tree `cat "$dotest/$msgnum.result"`
+ git-checkout-index -q -f -u -a
+ git-commit -C "`cat $dotest/$msgnum`"
+
+ echo "Committed $msgnum"
+ echo ' '`git-rev-list --pretty=oneline -1 HEAD | \
+ sed 's/^[a-f0-9]\+ //'`
+ msgnum=$(($msgnum + 1))
+ done
+ rm -r "$dotest"
+ echo "All done."
+}
+
while case "$#" in 0) break ;; esac
do
case "$1" in
@@ -46,17 +135,43 @@ do
exit 1
;;
esac
+ if test -d "$dotest"
+ then
+ prev_head="`cat $dotest/prev_head`"
+ end="`cat $dotest/end`"
+ msgnum="`cat $dotest/msgnum`"
+ onto="`cat $dotest/onto`"
+ continue_merge
+ while test "$msgnum" -le "$end"
+ do
+ call_merge "$msgnum"
+ continue_merge
+ done
+ finish_rb_merge
+ exit
+ fi
git am --resolved --3way --resolvemsg="$RESOLVEMSG"
exit
;;
--skip)
+ if test -d "$dotest"
+ then
+ die "--skip is not supported when using --merge"
+ fi
git am -3 --skip --resolvemsg="$RESOLVEMSG"
exit
;;
--abort)
- [ -d .dotest ] || die "No rebase in progress?"
+ if test -d "$dotest"
+ then
+ rm -r "$dotest"
+ elif test -d .dotest
+ then
+ rm -r .dotest
+ else
+ die "No rebase in progress?"
+ fi
git reset --hard ORIG_HEAD
- rm -r .dotest
exit
;;
--onto)
@@ -64,6 +179,23 @@ do
newbase="$2"
shift
;;
+ -M|-m|--m|--me|--mer|--merg|--merge)
+ do_merge=t
+ ;;
+ -s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
+ --strateg=*|--strategy=*|\
+ -s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
+ case "$#,$1" in
+ *,*=*)
+ strategy=`expr "$1" : '-[^=]*=\(.*\)'` ;;
+ 1,*)
+ usage ;;
+ *)
+ strategy="$2"
+ shift ;;
+ esac
+ do_merge=t
+ ;;
-*)
usage
;;
@@ -75,16 +207,25 @@ do
done
# Make sure we do not have .dotest
-if mkdir .dotest
+if test -z "$do_merge"
then
- rmdir .dotest
-else
- echo >&2 '
+ if mkdir .dotest
+ then
+ rmdir .dotest
+ else
+ echo >&2 '
It seems that I cannot create a .dotest directory, and I wonder if you
are in the middle of patch application or another rebase. If that is not
the case, please rm -fr .dotest and run me again. I am stopping in case
you still have something valuable there.'
- exit 1
+ exit 1
+ fi
+else
+ if test -d "$dotest"
+ then
+ die "previous dotest directory $dotest still exists." \
+ 'try git-rebase < --continue | --abort >'
+ fi
fi
# The tree must be really really clean.
@@ -152,6 +293,39 @@ then
exit 0
fi
-git-format-patch -k --stdout --full-index "$upstream"..ORIG_HEAD |
-git am --binary -3 -k --resolvemsg="$RESOLVEMSG"
+if test -z "$do_merge"
+then
+ git-format-patch -k --stdout --full-index "$upstream"..ORIG_HEAD |
+ git am --binary -3 -k --resolvemsg="$RESOLVEMSG"
+ exit $?
+fi
+
+# start doing a rebase with git-merge
+# this is rename-aware if the recursive (default) strategy is used
+
+mkdir -p "$dotest"
+echo "$onto" > "$dotest/onto"
+prev_head=`git-rev-parse HEAD^0`
+echo "$prev_head" > "$dotest/prev_head"
+
+msgnum=0
+for cmt in `git-rev-list --no-merges "$upstream"..ORIG_HEAD \
+ | perl -e 'print reverse <>'`
+do
+ msgnum=$(($msgnum + 1))
+ echo "$cmt" > "$dotest/`printf "%0${prec}d" $msgnum`"
+done
+
+printf "%0${prec}d" 1 > "$dotest/msgnum"
+printf "%0${prec}d" "$msgnum" > "$dotest/end"
+
+end=$msgnum
+msgnum=1
+
+while test "$msgnum" -le "$end"
+do
+ call_merge "$msgnum"
+ continue_merge
+done
+finish_rb_merge
--
1.4.0.g65f3
^ permalink raw reply related
* Re: [PATCH] send-email: Use setlocale in addition to $ENV{LC_ALL} to set locale
From: Jakub Narebski @ 2006-06-21 10:33 UTC (permalink / raw)
To: git
In-Reply-To: <11508811631669-git-send-email-jnareb@gmail.com>
Jakub Narebski wrote:
> $ENV{LC_ALL} = 'C'; does not change locale used by strftime.
> Use setlocale( LC_ALL, 'C' ); instead.
> # most mail servers generate the Date: header, but not all...
> $ENV{LC_ALL} = 'C';
> -use POSIX qw/strftime/;
> +use POSIX qw/strftime setlocale LC_ALL/;
> +setlocale( &LC_ALL, 'C' );
Perhaps instead of
setlocale( &LC_ALL, 'C' );
we should use
setlocale( &LC_ALL, '' );
(i.e. set the LC_ALL behaviour according to the locale environment
variables). I'm not that versed in locale, POSIX and Perl.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH] send-email: Use setlocale in addition to $ENV{LC_ALL} to set locale
From: Eric Wong @ 2006-06-21 10:49 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <e7b796$lj$1@sea.gmane.org>
Jakub Narebski <jnareb@gmail.com> wrote:
> Jakub Narebski wrote:
>
> > $ENV{LC_ALL} = 'C'; does not change locale used by strftime.
> > Use setlocale( LC_ALL, 'C' ); instead.
>
> > # most mail servers generate the Date: header, but not all...
> > $ENV{LC_ALL} = 'C';
> > -use POSIX qw/strftime/;
> > +use POSIX qw/strftime setlocale LC_ALL/;
> > +setlocale( &LC_ALL, 'C' );
>
> Perhaps instead of
> setlocale( &LC_ALL, 'C' );
> we should use
> setlocale( &LC_ALL, '' );
> (i.e. set the LC_ALL behaviour according to the locale environment
> variables). I'm not that versed in locale, POSIX and Perl.
I'm responsible for the $ENV{LC_ALL} = 'C' setting but I never actually
tested how things would work with a non-English locale (not being
well-versed in these things myself, either).
I've always wondered about why /usr/bin/822-date existed without
strftime on my Debian systems but never bothered asking, I guess this
could be a good reason why...
For reference, here's the /usr/bin/822-date script
(trailing whitespace fixed):
------- 8< -------
#!/usr/bin/perl --
# I hereby place this in the public domain - Ian Jackson, 1995.
# Changes by Klee Dienes also placed in public domain (1997).
# time structure:
# [ sec min hour mday mon year wday yday isdst ]
@ARGV && die "usage: 822-date\n";
$curtime = time;
@localtm = localtime ($curtime);
$localtms = localtime ($curtime);
@gmttm = gmtime ($curtime);
$gmttms = gmtime ($curtime);
if ($localtm[0] != $gmttm[0]) {
die (sprintf ("local timezone differs from GMT by a non-minute interval\n"
. "local time: %s\n"
. "GMT time: %s\n", $localtms, $gmttms));
}
$localmin = $localtm[1] + $localtm[2] * 60;
$gmtmin = $gmttm[1] + $gmttm[2] * 60;
if ((($gmttm[6] + 1) % 7) == $localtm[6]) {
$localmin += 1440;
} elsif ((($gmttm[6] - 1) % 7) == $localtm[6]) {
$localmin -= 1440;
} elsif ($gmttm[6] == $localtm[6]) {
1;
} else {
die ("822-date: local time offset greater than or equal to 24 hours\n");
}
$offset = $localmin - $gmtmin;
$offhour = $offset / 60;
$offmin = abs ($offset % 60);
if (abs ($offhour) >= 24) {
die ("822-date: local time offset greater than or equal to 24 hours\n");
}
printf
(
"%s, %2d %s %d %02d:%02d:%02d %s%02d%02d\n",
(Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$localtm[6]], # day of week
$localtm[3], # day of month
(Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$localtm[4]], # month
$localtm[5]+1900, # year
$localtm[2], # hour
$localtm[1], # minute
$localtm[0], # sec
($offset >= 0) ? '+' : '-',# TZ offset direction
abs ($offhour), # TZ offset hour
$offmin, # TZ offset minute
) || die "822-date: output error: $!\n";
------- 8< -------
--
Eric Wong
^ permalink raw reply
* Re: [PATCH] Fix possible out-of-bounds array access
From: Junio C Hamano @ 2006-06-21 11:01 UTC (permalink / raw)
To: Uwe Zeisberger; +Cc: git
In-Reply-To: <20060621090412.GA9267@informatik.uni-freiburg.de>
Thanks.
^ permalink raw reply
* Re: [PATCH] rebase: Allow merge strategies to be used when rebasing
From: Junio C Hamano @ 2006-06-21 11:01 UTC (permalink / raw)
To: Eric Wong; +Cc: git
In-Reply-To: <20060621100138.GA15748@localdomain>
Eric Wong <normalperson@yhbt.net> writes:
> Junio C Hamano <junkio@cox.net> wrote:
>>
>> >> git-merge-$strategy $cmt^ -- HEAD $cmt
>> >
>> > Changing the 'git-merge $strategy_args "rebase-merge: $cmt" HEAD "$cmt"'
>> > line in call_merge() to this seems to have broken more tests.
>>
>> Oh, that is to be expected if you changed git-merge -s recursive
>> with git-merge-recursive without other changes. The former
>> makes a commit (which your original patch later used to create a
>> separate commit chain and discarded); the latter does not make a
>> commit but expects the caller to create a commit out of the
>> resulting index file.
>
> Oops, *smacks head*
Well, but you used it to do the right thing after all ;-).
The patch looks quite good.
>> I was originally hoping that rebasing would just be a matter of
>> listing sequence of commits to be ported onto a new base and
>> running "git-cherry-pick" on each of them in sequence. Now
>> cherry-pick does not use merge machinery (hence does not use
>> git-merge-recursive), but if we change that then updating rebase
>> would be pretty much straightforward. It just needs a UI layer
>> to guide the user through recovery process when the merge does
>> not resolve cleanly in the middle, no?
>
> Sounds workable right to me. But then again, a cherry-pick is also a
> case of rebase on a single commit, so we could be using rebase (and its
> recovery code) in cherry-pick, too, right?
Revert and cherry-pick are quite similar operation (the only
difference is that you swap his and pivot when doing revert), so
when you implement cherry-pick as an atomic operation you can
have revert almost for free. If you have a rebase like you did,
it would be a bit more involved to make it do revert as well.
^ permalink raw reply
* Re: [PATCH (fixed)] rebase: Allow merge strategies to be used when rebasing
From: Junio C Hamano @ 2006-06-21 11:01 UTC (permalink / raw)
To: Eric Wong; +Cc: git
In-Reply-To: <11508842824018-git-send-email-normalperson@yhbt.net>
Eric Wong <normalperson@yhbt.net> writes:
> 1 - is fixed for --onto usage.
More importantly, it used to rebase "side edits further" commit
incorrectly in the test sequence -- the commit should only touch
"newfile", but it touched "renamed" as well. Your updated patch
fixes this problem.
^ permalink raw reply
* Re: Odd behavior with git and cairo-devel repo
From: Junio C Hamano @ 2006-06-21 11:01 UTC (permalink / raw)
To: Andre Noll; +Cc: git, Art Haas
In-Reply-To: <20060621024605.GO11245@skl-net.de>
Andre Noll <maan@systemlinux.org> writes:
> On 20:00, Art Haas wrote:
>
>> $ git clone git://git.cairographics.org/git/cairo cairo
>> [ ... git clones the repo without problem ... ]
>> $ cd cairo
>> $ git fsck-objects
>> Floating point exception
>
> This is due to refs_hash_size being zero in mark_reachable().
> Both "git fsck-objects --full" and "git repack -a -d" seem to work
> fine with the patch below (tested by cloning your repo).
Good catch. Thanks both!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox