summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-cvsserver.txt24
-rw-r--r--Documentation/git-svnimport.txt13
-rw-r--r--Makefile12
-rw-r--r--combine-diff.c14
-rw-r--r--contrib/git-svn/git-svn.txt11
-rwxr-xr-xcontrib/gitview/gitview91
-rw-r--r--diff-delta.c253
-rw-r--r--diffcore-break.c4
-rwxr-xr-xgit-cvsserver.perl44
-rwxr-xr-xgit-format-patch.sh7
-rwxr-xr-xgit-mv.perl33
-rwxr-xr-xgit-svnimport.perl23
12 files changed, 308 insertions, 221 deletions
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 88f07ff15d..19c9c51cff 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -54,6 +54,30 @@ INSTALLATION
of branches in git).
$ cvs co -d mylocaldir master
+Eclipse CVS Client Notes
+------------------------
+
+To get a checkout with the Eclipse CVS client:
+
+1. Create a new project from CVS checkout, giving it repository and module
+2. Context Menu->Team->Share Project...
+3. Enter the repository and module information again and click Finish
+4. The Synchronize view appears. Untick "launch commit wizard" to avoid
+committing the .project file, and select HEAD as the tag to synchronize to.
+Update all incoming changes.
+
+Note that most versions of Eclipse ignore CVS_SERVER (which you can set in
+the Preferences->Team->CVS->ExtConnection pane), so you may have to
+rename, alias or symlink git-cvsserver to 'cvs' on the server.
+
+Clients known to work
+---------------------
+
+CVS 1.12.9 on Debian
+CVS 1.11.17 on MacOSX (from Fink package)
+Eclipse 3.0, 3.1.2 on MacOSX (see Eclipse CVS Client Notes)
+TortoiseCVS
+
Operations supported
--------------------
diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt
index c95ff84f6a..912a80865e 100644
--- a/Documentation/git-svnimport.txt
+++ b/Documentation/git-svnimport.txt
@@ -13,7 +13,8 @@ SYNOPSIS
[ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev]
[ -b branch_subdir ] [ -T trunk_subdir ] [ -t tag_subdir ]
[ -s start_chg ] [ -m ] [ -r ] [ -M regex ]
- [ -I <ignorefile_name> ] <SVN_repository_URL> [ <path> ]
+ [ -I <ignorefile_name> ] [ -A <author_file> ]
+ <SVN_repository_URL> [ <path> ]
DESCRIPTION
@@ -71,6 +72,16 @@ When importing incrementally, you might need to edit the .git/svn2git file.
syntaxes are similar enough that using the Subversion patterns
directly with "-I .gitignore" will almost always just work.)
+-A <author_file>::
+ Read a file with lines on the form
+
+ username = User's Full Name <email@addr.es>
+
+ and use "User's Full Name <email@addr.es>" as the GIT
+ author and committer for Subversion commits made by
+ "username". If encountering a commit made by a user not in the
+ list, abort.
+
-m::
Attempt to detect merges based on the commit message. This option
will enable default regexes that try to capture the name source
diff --git a/Makefile b/Makefile
index 6c59cee414..19578fc93a 100644
--- a/Makefile
+++ b/Makefile
@@ -223,11 +223,15 @@ ifeq ($(uname_S),Darwin)
NEEDS_SSL_WITH_CRYPTO = YesPlease
NEEDS_LIBICONV = YesPlease
## fink
- ALL_CFLAGS += -I/sw/include
- ALL_LDFLAGS += -L/sw/lib
+ ifeq ($(shell test -d /sw/lib && echo y),y)
+ ALL_CFLAGS += -I/sw/include
+ ALL_LDFLAGS += -L/sw/lib
+ endif
## darwinports
- ALL_CFLAGS += -I/opt/local/include
- ALL_LDFLAGS += -L/opt/local/lib
+ ifeq ($(shell test -d /opt/local/lib && echo y),y)
+ ALL_CFLAGS += -I/opt/local/include
+ ALL_LDFLAGS += -L/opt/local/lib
+ endif
endif
ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease
diff --git a/combine-diff.c b/combine-diff.c
index d812600d11..a23894d869 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -621,7 +621,8 @@ static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
}
static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
- int dense, const char *header)
+ int dense, const char *header,
+ struct diff_options *opt)
{
unsigned long size, cnt, lno;
char *result, *cp, *ep;
@@ -631,6 +632,7 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
char ourtmp_buf[TMPPATHLEN];
char *ourtmp = ourtmp_buf;
int working_tree_file = !memcmp(elem->sha1, null_sha1, 20);
+ int abbrev = opt->full_index ? 40 : DEFAULT_ABBREV;
/* Read the result of merge first */
if (!working_tree_file) {
@@ -724,7 +726,7 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
if (header) {
shown_header++;
- puts(header);
+ printf("%s%c", header, opt->line_termination);
}
printf("diff --%s ", dense ? "cc" : "combined");
if (quote_c_style(elem->path, NULL, NULL, 0))
@@ -735,10 +737,10 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
printf("index ");
for (i = 0; i < num_parent; i++) {
abb = find_unique_abbrev(elem->parent[i].sha1,
- DEFAULT_ABBREV);
+ abbrev);
printf("%s%s", i ? "," : "", abb);
}
- abb = find_unique_abbrev(elem->sha1, DEFAULT_ABBREV);
+ abb = find_unique_abbrev(elem->sha1, abbrev);
printf("..%s\n", abb);
if (mode_differs) {
@@ -797,7 +799,7 @@ static void show_raw_diff(struct combine_diff_path *p, int num_parent, const cha
inter_name_termination = 0;
if (header)
- puts(header);
+ printf("%s%c", header, line_termination);
for (i = 0; i < num_parent; i++) {
if (p->parent[i].mode)
@@ -862,7 +864,7 @@ int show_combined_diff(struct combine_diff_path *p,
default:
case DIFF_FORMAT_PATCH:
- return show_patch_diff(p, num_parent, dense, header);
+ return show_patch_diff(p, num_parent, dense, header, opt);
}
}
diff --git a/contrib/git-svn/git-svn.txt b/contrib/git-svn/git-svn.txt
index b4b7789dee..b29073997c 100644
--- a/contrib/git-svn/git-svn.txt
+++ b/contrib/git-svn/git-svn.txt
@@ -43,6 +43,11 @@ fetch::
Fetch unfetched revisions from the SVN_URL we are tracking.
refs/heads/git-svn-HEAD will be updated to the latest revision.
+ Note: You should never attempt to modify the git-svn-HEAD branch
+ outside of git-svn. Instead, create a branch from git-svn-HEAD
+ and work on that branch. Use the 'commit' command (see below)
+ to write git commits back to git-svn-HEAD.
+
commit::
Commit specified commit or tree objects to SVN. This relies on
your imported fetch data being up-to-date. This makes
@@ -154,7 +159,7 @@ Tracking and contributing to an Subversion managed-project:
# Commit only the git commits you want to SVN::
git-svn commit <tree-ish> [<tree-ish_2> ...]
# Commit all the git commits from my-branch that don't exist in SVN::
- git commit git-svn-HEAD..my-branch
+ git-svn commit git-svn-HEAD..my-branch
# Something is committed to SVN, pull the latest into your branch::
git-svn fetch && git pull . git-svn-HEAD
# Append svn:ignore settings to the default git exclude file:
@@ -179,7 +184,9 @@ SVN repositories via one git repository. Simply set the GIT_SVN_ID
environment variable to a name other other than "git-svn" (the default)
and git-svn will ignore the contents of the $GIT_DIR/git-svn directory
and instead do all of its work in $GIT_DIR/$GIT_SVN_ID for that
-invocation.
+invocation. The interface branch will be $GIT_SVN_ID-HEAD, instead of
+git-svn-HEAD. Any $GIT_SVN_ID-HEAD branch should never be modified
+by the user outside of git-svn commands.
ADDITIONAL FETCH ARGUMENTS
--------------------------
diff --git a/contrib/gitview/gitview b/contrib/gitview/gitview
index 4e3847d8bf..ea05cd4240 100755
--- a/contrib/gitview/gitview
+++ b/contrib/gitview/gitview
@@ -162,7 +162,7 @@ class CellRendererGraph(gtk.GenericCellRenderer):
for item in names:
names_len += len(item)
- width = box_size * (cols + 1 ) + names_len
+ width = box_size * (cols + 1 ) + names_len
height = box_size
# FIXME I have no idea how to use cell_area properly
@@ -239,20 +239,23 @@ class CellRendererGraph(gtk.GenericCellRenderer):
box_size / 4, 0, 2 * math.pi)
+ self.set_colour(ctx, colour, 0.0, 0.5)
+ ctx.stroke_preserve()
+
+ self.set_colour(ctx, colour, 0.5, 1.0)
+ ctx.fill_preserve()
+
if (len(names) != 0):
name = " "
for item in names:
name = name + item + " "
- ctx.select_font_face("Monospace")
ctx.set_font_size(13)
- ctx.text_path(name)
-
- self.set_colour(ctx, colour, 0.0, 0.5)
- ctx.stroke_preserve()
-
- self.set_colour(ctx, colour, 0.5, 1.0)
- ctx.fill()
+ if (flags & 1):
+ self.set_colour(ctx, colour, 0.5, 1.0)
+ else:
+ self.set_colour(ctx, colour, 0.0, 0.5)
+ ctx.show_text(name)
class Commit:
""" This represent a commit object obtained after parsing the git-rev-list
@@ -261,11 +264,11 @@ class Commit:
children_sha1 = {}
def __init__(self, commit_lines):
- self.message = ""
+ self.message = ""
self.author = ""
- self.date = ""
- self.committer = ""
- self.commit_date = ""
+ self.date = ""
+ self.committer = ""
+ self.commit_date = ""
self.commit_sha1 = ""
self.parent_sha1 = [ ]
self.parse_commit(commit_lines)
@@ -365,7 +368,7 @@ class DiffWindow:
save_menu.connect("activate", self.save_menu_response, "save")
save_menu.show()
menu_bar.append(save_menu)
- vbox.pack_start(menu_bar, False, False, 2)
+ vbox.pack_start(menu_bar, expand=False, fill=True)
menu_bar.show()
scrollwin = gtk.ScrolledWindow()
@@ -391,7 +394,7 @@ class DiffWindow:
sourceview.show()
- def set_diff(self, commit_sha1, parent_sha1):
+ def set_diff(self, commit_sha1, parent_sha1, encoding):
"""Set the differences showed by this window.
Compares the two trees and populates the window with the
differences.
@@ -401,7 +404,7 @@ class DiffWindow:
return
fp = os.popen("git diff-tree -p " + parent_sha1 + " " + commit_sha1)
- self.buffer.set_text(fp.read())
+ self.buffer.set_text(unicode(fp.read(), encoding).encode('utf-8'))
fp.close()
self.window.show()
@@ -426,10 +429,11 @@ class GitView:
def __init__(self, with_diff=0):
self.with_diff = with_diff
- self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.set_border_width(0)
self.window.set_title("Git repository browser")
+ self.get_encoding()
self.get_bt_sha1()
# Use three-quarters of the screen by default
@@ -468,22 +472,20 @@ class GitView:
self.bt_sha1[sha1].append(name)
fp.close()
+ def get_encoding(self):
+ fp = os.popen("git repo-config --get i18n.commitencoding")
+ self.encoding=string.strip(fp.readline())
+ fp.close()
+ if (self.encoding == ""):
+ self.encoding = "utf-8"
+
def construct(self):
"""Construct the window contents."""
+ vbox = gtk.VBox()
paned = gtk.VPaned()
paned.pack1(self.construct_top(), resize=False, shrink=True)
paned.pack2(self.construct_bottom(), resize=False, shrink=True)
- self.window.add(paned)
- paned.show()
-
-
- def construct_top(self):
- """Construct the top-half of the window."""
- vbox = gtk.VBox(spacing=6)
- vbox.set_border_width(12)
- vbox.show()
-
menu_bar = gtk.MenuBar()
menu_bar.set_pack_direction(gtk.PACK_DIRECTION_RTL)
help_menu = gtk.MenuItem("Help")
@@ -495,8 +497,20 @@ class GitView:
help_menu.set_submenu(menu)
help_menu.show()
menu_bar.append(help_menu)
- vbox.pack_start(menu_bar, False, False, 2)
menu_bar.show()
+ vbox.pack_start(menu_bar, expand=False, fill=True)
+ vbox.pack_start(paned, expand=True, fill=True)
+ self.window.add(vbox)
+ paned.show()
+ vbox.show()
+
+
+ def construct_top(self):
+ """Construct the top-half of the window."""
+ vbox = gtk.VBox(spacing=6)
+ vbox.set_border_width(12)
+ vbox.show()
+
scrollwin = gtk.ScrolledWindow()
scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
@@ -512,6 +526,9 @@ class GitView:
self.treeview.show()
cell = CellRendererGraph()
+ # Set the default width to 265
+ # This make sure that we have nice display with large tag names
+ cell.set_property("width", 265)
column = gtk.TreeViewColumn()
column.set_resizable(True)
column.pack_start(cell, expand=True)
@@ -683,7 +700,7 @@ class GitView:
self.revid_label.set_text(revid_label)
self.committer_label.set_text(committer)
self.timestamp_label.set_text(timestamp)
- self.message_buffer.set_text(message)
+ self.message_buffer.set_text(unicode(message, self.encoding).encode('utf-8'))
for widget in self.parents_widgets:
self.table.remove(widget)
@@ -728,7 +745,7 @@ class GitView:
button.set_relief(gtk.RELIEF_NONE)
button.set_sensitive(True)
button.connect("clicked", self._show_clicked_cb,
- commit.commit_sha1, parent_id)
+ commit.commit_sha1, parent_id, self.encoding)
hbox.pack_start(button, expand=False, fill=True)
button.show()
@@ -870,15 +887,15 @@ class GitView:
# Reset nodepostion
if (last_nodepos > 5):
- last_nodepos = -1
+ last_nodepos = -1
# Add the incomplete lines of the last cell in this
try:
colour = self.colours[commit.commit_sha1]
except KeyError:
self.colours[commit.commit_sha1] = last_colour+1
- last_colour = self.colours[commit.commit_sha1]
- colour = self.colours[commit.commit_sha1]
+ last_colour = self.colours[commit.commit_sha1]
+ colour = self.colours[commit.commit_sha1]
try:
node_pos = self.nodepos[commit.commit_sha1]
@@ -910,7 +927,7 @@ class GitView:
self.colours[parent_id] = last_colour+1
last_colour = self.colours[parent_id]
self.nodepos[parent_id] = last_nodepos+1
- last_nodepos = self.nodepos[parent_id]
+ last_nodepos = self.nodepos[parent_id]
in_line.append((node_pos, self.nodepos[parent_id],
self.colours[parent_id]))
@@ -946,7 +963,7 @@ class GitView:
try:
next_commit = self.commits[index+1]
if (next_commit.commit_sha1 == sha1 and pos != int(pos)):
- # join the line back to the node point
+ # join the line back to the node point
# This need to be done only if we modified it
in_line.append((pos, pos-0.5, self.colours[sha1]))
continue;
@@ -967,10 +984,10 @@ class GitView:
self.treeview.grab_focus()
- def _show_clicked_cb(self, widget, commit_sha1, parent_sha1):
+ def _show_clicked_cb(self, widget, commit_sha1, parent_sha1, encoding):
"""Callback for when the show button for a parent is clicked."""
window = DiffWindow()
- window.set_diff(commit_sha1, parent_sha1)
+ window.set_diff(commit_sha1, parent_sha1, encoding)
self.treeview.grab_focus()
if __name__ == "__main__":
diff --git a/diff-delta.c b/diff-delta.c
index c2f656ae39..2ed5984b1c 100644
--- a/diff-delta.c
+++ b/diff-delta.c
@@ -19,8 +19,9 @@
*/
#include <stdlib.h>
+#include <string.h>
+#include <zlib.h>
#include "delta.h"
-#include "zlib.h"
/* block size: min = 16, max = 64k, power of 2 */
@@ -29,149 +30,87 @@
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define GR_PRIME 0x9e370001
-#define HASH(v, b) (((unsigned int)(v) * GR_PRIME) >> (32 - (b)))
-
-static unsigned int hashbits(unsigned int size)
-{
- unsigned int val = 1, bits = 0;
- while (val < size && bits < 32) {
- val <<= 1;
- bits++;
- }
- return bits ? bits: 1;
-}
-
-typedef struct s_chanode {
- struct s_chanode *next;
- int icurr;
-} chanode_t;
-
-typedef struct s_chastore {
- int isize, nsize;
- chanode_t *ancur;
-} chastore_t;
-
-static void cha_init(chastore_t *cha, int isize, int icount)
-{
- cha->isize = isize;
- cha->nsize = icount * isize;
- cha->ancur = NULL;
-}
-
-static void *cha_alloc(chastore_t *cha)
-{
- chanode_t *ancur;
- void *data;
+#define HASH(v, shift) (((unsigned int)(v) * GR_PRIME) >> (shift))
- ancur = cha->ancur;
- if (!ancur || ancur->icurr == cha->nsize) {
- ancur = malloc(sizeof(chanode_t) + cha->nsize);
- if (!ancur)
- return NULL;
- ancur->icurr = 0;
- ancur->next = cha->ancur;
- cha->ancur = ancur;
- }
-
- data = (void *)ancur + sizeof(chanode_t) + ancur->icurr;
- ancur->icurr += cha->isize;
- return data;
-}
-
-static void cha_free(chastore_t *cha)
-{
- chanode_t *cur = cha->ancur;
- while (cur) {
- chanode_t *tmp = cur;
- cur = cur->next;
- free(tmp);
- }
-}
-
-typedef struct s_bdrecord {
- struct s_bdrecord *next;
- unsigned int fp;
+struct index {
const unsigned char *ptr;
-} bdrecord_t;
-
-typedef struct s_bdfile {
- chastore_t cha;
- unsigned int fphbits;
- bdrecord_t **fphash;
-} bdfile_t;
+ unsigned int val;
+ struct index *next;
+};
-static int delta_prepare(const unsigned char *buf, int bufsize, bdfile_t *bdf)
+static struct index ** delta_index(const unsigned char *buf,
+ unsigned long bufsize,
+ unsigned int *hash_shift)
{
- unsigned int fphbits;
- int i, hsize;
- const unsigned char *data, *top;
- bdrecord_t *brec;
- bdrecord_t **fphash;
-
- fphbits = hashbits(bufsize / BLK_SIZE + 1);
- hsize = 1 << fphbits;
- fphash = malloc(hsize * sizeof(bdrecord_t *));
- if (!fphash)
- return -1;
- for (i = 0; i < hsize; i++)
- fphash[i] = NULL;
- cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1);
-
- top = buf + bufsize;
- data = buf + (bufsize / BLK_SIZE) * BLK_SIZE;
- if (data == top)
+ unsigned int hsize, hshift, entries, blksize, i;
+ const unsigned char *data;
+ struct index *entry, **hash;
+ void *mem;
+
+ /* determine index hash size */
+ entries = (bufsize + BLK_SIZE - 1) / BLK_SIZE;
+ hsize = entries / 4;
+ for (i = 4; (1 << i) < hsize && i < 16; i++);
+ hsize = 1 << i;
+ hshift = 32 - i;
+ *hash_shift = hshift;
+
+ /* allocate lookup index */
+ mem = malloc(hsize * sizeof(*hash) + entries * sizeof(*entry));
+ if (!mem)
+ return NULL;
+ hash = mem;
+ entry = mem + hsize * sizeof(*hash);
+ memset(hash, 0, hsize * sizeof(*hash));
+
+ /* then populate it */
+ data = buf + entries * BLK_SIZE - BLK_SIZE;
+ blksize = bufsize - (data - buf);
+ while (data >= buf) {
+ unsigned int val = adler32(0, data, blksize);
+ i = HASH(val, hshift);
+ entry->ptr = data;
+ entry->val = val;
+ entry->next = hash[i];
+ hash[i] = entry++;
+ blksize = BLK_SIZE;
data -= BLK_SIZE;
+ }
- for ( ; data >= buf; data -= BLK_SIZE) {
- brec = cha_alloc(&bdf->cha);
- if (!brec) {
- cha_free(&bdf->cha);
- free(fphash);
- return -1;
- }
- brec->fp = adler32(0, data, MIN(BLK_SIZE, top - data));
- brec->ptr = data;
- i = HASH(brec->fp, fphbits);
- brec->next = fphash[i];
- fphash[i] = brec;
- }
-
- bdf->fphbits = fphbits;
- bdf->fphash = fphash;
-
- return 0;
-}
-
-static void delta_cleanup(bdfile_t *bdf)
-{
- free(bdf->fphash);
- cha_free(&bdf->cha);
+ return hash;
}
+/* provide the size of the copy opcode given the block offset and size */
#define COPYOP_SIZE(o, s) \
(!!(o & 0xff) + !!(o & 0xff00) + !!(o & 0xff0000) + !!(o & 0xff000000) + \
!!(s & 0xff) + !!(s & 0xff00) + 1)
+/* the maximum size for any opcode */
+#define MAX_OP_SIZE COPYOP_SIZE(0xffffffff, 0xffffffff)
+
void *diff_delta(void *from_buf, unsigned long from_size,
void *to_buf, unsigned long to_size,
unsigned long *delta_size,
unsigned long max_size)
{
- int i, outpos, outsize, inscnt, csize, msize, moff;
- unsigned int fp;
- const unsigned char *ref_data, *ref_top, *data, *top, *ptr1, *ptr2;
- unsigned char *out, *orig;
- bdrecord_t *brec;
- bdfile_t bdf;
+ unsigned int i, outpos, outsize, inscnt, hash_shift;
+ const unsigned char *ref_data, *ref_top, *data, *top;
+ unsigned char *out;
+ struct index *entry, **hash;
- if (!from_size || !to_size || delta_prepare(from_buf, from_size, &bdf))
+ if (!from_size || !to_size)
+ return NULL;
+ hash = delta_index(from_buf, from_size, &hash_shift);
+ if (!hash)
return NULL;
-
+
outpos = 0;
outsize = 8192;
+ if (max_size && outsize >= max_size)
+ outsize = max_size + MAX_OP_SIZE + 1;
out = malloc(outsize);
if (!out) {
- delta_cleanup(&bdf);
+ free(hash);
return NULL;
}
@@ -199,28 +138,32 @@ void *diff_delta(void *from_buf, unsigned long from_size,
}
inscnt = 0;
- moff = 0;
- while (data < top) {
- msize = 0;
- fp = adler32(0, data, MIN(top - data, BLK_SIZE));
- i = HASH(fp, bdf.fphbits);
- for (brec = bdf.fphash[i]; brec; brec = brec->next) {
- if (brec->fp == fp) {
- csize = ref_top - brec->ptr;
- if (csize > top - data)
- csize = top - data;
- for (ptr1 = brec->ptr, ptr2 = data;
- csize && *ptr1 == *ptr2;
- csize--, ptr1++, ptr2++);
- csize = ptr1 - brec->ptr;
- if (csize > msize) {
- moff = brec->ptr - ref_data;
- msize = csize;
- if (msize >= 0x10000) {
- msize = 0x10000;
- break;
- }
+ while (data < top) {
+ unsigned int moff = 0, msize = 0;
+ unsigned int blksize = MIN(top - data, BLK_SIZE);
+ unsigned int val = adler32(0, data, blksize);
+ i = HASH(val, hash_shift);
+ for (entry = hash[i]; entry; entry = entry->next) {
+ const unsigned char *ref = entry->ptr;
+ const unsigned char *src = data;
+ unsigned int ref_size = ref_top - ref;
+ if (entry->val != val)
+ continue;
+ if (ref_size > top - src)
+ ref_size = top - src;
+ while (ref_size && *src++ == *ref) {
+ ref++;
+ ref_size--;
+ }
+ ref_size = ref - entry->ptr;
+ if (ref_size > msize) {
+ /* this is our best match so far */
+ moff = entry->ptr - ref_data;
+ msize = ref_size;
+ if (msize >= 0x10000) {
+ msize = 0x10000;
+ break;
}
}
}
@@ -235,13 +178,15 @@ void *diff_delta(void *from_buf, unsigned long from_size,
inscnt = 0;
}
} else {
+ unsigned char *op;
+
if (inscnt) {
out[outpos - inscnt - 1] = inscnt;
inscnt = 0;
}
data += msize;
- orig = out + outpos++;
+ op = out + outpos++;
i = 0x80;
if (moff & 0xff) { out[outpos++] = moff; i |= 0x01; }
@@ -256,23 +201,21 @@ void *diff_delta(void *from_buf, unsigned long from_size,
msize >>= 8;
if (msize & 0xff) { out[outpos++] = msize; i |= 0x20; }
- *orig = i;
- }
-
- if (max_size && outpos > max_size) {
- free(out);
- delta_cleanup(&bdf);
- return NULL;
+ *op = i;
}
- /* next time around the largest possible output is 1 + 4 + 3 */
- if (outpos > outsize - 8) {
+ if (outpos >= outsize - MAX_OP_SIZE) {
void *tmp = out;
outsize = outsize * 3 / 2;
- out = realloc(out, outsize);
+ if (max_size && outsize >= max_size)
+ outsize = max_size + MAX_OP_SIZE + 1;
+ if (max_size && outpos > max_size)
+ out = NULL;
+ else
+ out = realloc(out, outsize);
if (!out) {
free(tmp);
- delta_cleanup(&bdf);
+ free(hash);
return NULL;
}
}
@@ -281,7 +224,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
if (inscnt)
out[outpos - inscnt - 1] = inscnt;
- delta_cleanup(&bdf);
+ free(hash);
*delta_size = outpos;
return out;
}
diff --git a/diffcore-break.c b/diffcore-break.c
index c57513a4fa..95b5eb492e 100644
--- a/diffcore-break.c
+++ b/diffcore-break.c
@@ -58,6 +58,10 @@ static int should_break(struct diff_filespec *src,
if (!S_ISREG(src->mode) || !S_ISREG(dst->mode))
return 0; /* leave symlink rename alone */
+ if (src->sha1_valid && dst->sha1_valid &&
+ !memcmp(src->sha1, dst->sha1, 20))
+ return 0; /* they are the same */
+
if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
return 0; /* error but caught downstream */
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index d20d1a8c4b..3c588c9d64 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -53,6 +53,7 @@ my $methods = {
'Entry' => \&req_Entry,
'Modified' => \&req_Modified,
'Unchanged' => \&req_Unchanged,
+ 'Questionable' => \&req_Questionable,
'Argument' => \&req_Argument,
'Argumentx' => \&req_Argument,
'expand-modules' => \&req_expandmodules,
@@ -63,6 +64,7 @@ my $methods = {
'ci' => \&req_ci,
'diff' => \&req_diff,
'log' => \&req_log,
+ 'rlog' => \&req_log,
'tag' => \&req_CATCHALL,
'status' => \&req_status,
'admin' => \&req_CATCHALL,
@@ -459,6 +461,22 @@ sub req_Unchanged
#$log->debug("req_Unchanged : $data");
}
+# Questionable filename \n
+# Response expected: no. Additional data: no.
+# Tell the server to check whether filename should be ignored,
+# and if not, next time the server sends responses, send (in
+# a M response) `?' followed by the directory and filename.
+# filename must not contain `/'; it needs to be a file in the
+# directory named by the most recent Directory request.
+sub req_Questionable
+{
+ my ( $cmd, $data ) = @_;
+
+ $state->{entries}{$state->{directory}.$data}{questionable} = 1;
+
+ #$log->debug("req_Questionable : $data");
+}
+
# Argument text \n
# Response expected: no. Save argument for use in a subsequent command.
# Arguments accumulate until an argument-using command is given, at which
@@ -568,7 +586,7 @@ sub req_co
# print some information to the client
print "MT +updated\n";
- print "MT text U\n";
+ print "MT text U \n";
if ( defined ( $git->{dir} ) and $git->{dir} ne "./" )
{
print "MT fname $checkout_path/$git->{dir}$git->{name}\n";
@@ -579,9 +597,9 @@ sub req_co
print "MT -updated\n";
# instruct client we're sending a file to put in this path
- print "Created $checkout_path/" . ( defined ( $git->{dir} ) ? $git->{dir} . "/" : "" ) . "\n";
+ print "Created $checkout_path/" . ( defined ( $git->{dir} ) and $git->{dir} ne "./" ? $git->{dir} . "/" : "" ) . "\n";
- print $state->{CVSROOT} . "/$module/" . ( defined ( $git->{dir} ) ? $git->{dir} . "/" : "" ) . "$git->{name}\n";
+ print $state->{CVSROOT} . "/$module/" . ( defined ( $git->{dir} ) and $git->{dir} ne "./" ? $git->{dir} . "/" : "" ) . "$git->{name}\n";
# this is an "entries" line
print "/$git->{name}/1.$git->{revision}///\n";
@@ -612,6 +630,26 @@ sub req_update
argsplit("update");
+ #
+ # It may just be a client exploring the available heads/modukles
+ # in that case, list them as top level directories and leave it
+ # at that. Eclipse uses this technique to offer you a list of
+ # projects (heads in this case) to checkout.
+ #
+ if ($state->{module} eq '') {
+ print "E cvs update: Updating .\n";
+ opendir HEADS, $state->{CVSROOT} . '/refs/heads';
+ while (my $head = readdir(HEADS)) {
+ if (-f $state->{CVSROOT} . '/refs/heads/' . $head) {
+ print "E cvs update: New directory `$head'\n";
+ }
+ }
+ closedir HEADS;
+ print "ok\n";
+ return 1;
+ }
+
+
# Grab a handle to the SQLite db and do any necessary updates
my $updater = GITCVS::updater->new($state->{CVSROOT}, $state->{module}, $log);
diff --git a/git-format-patch.sh b/git-format-patch.sh
index eb75de4601..2bd26395ec 100755
--- a/git-format-patch.sh
+++ b/git-format-patch.sh
@@ -174,7 +174,7 @@ titleScript='
process_one () {
perl -w -e '
my ($keep_subject, $num, $signoff, $commsg) = @ARGV;
-my ($signoff_pattern, $done_header, $done_subject, $signoff_seen,
+my ($signoff_pattern, $done_header, $done_subject, $done_separator, $signoff_seen,
$last_was_signoff);
if ($signoff) {
@@ -228,6 +228,11 @@ while (<FH>) {
$done_subject = 1;
next;
}
+ unless ($done_separator) {
+ print "\n";
+ $done_separator = 1;
+ next if (/^$/);
+ }
$last_was_signoff = 0;
if (/Signed-off-by:/i) {
diff --git a/git-mv.perl b/git-mv.perl
index 2ea852c918..fe9c40e1b9 100755
--- a/git-mv.perl
+++ b/git-mv.perl
@@ -19,25 +19,26 @@ EOT
exit(1);
}
-my $GIT_DIR = `git rev-parse --git-dir`;
-exit 1 if $?; # rev-parse would have given "not a git dir" message.
-chomp($GIT_DIR);
-
our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v);
getopts("hnfkv") || usage;
usage() if $opt_h;
@ARGV >= 1 or usage;
+my $GIT_DIR = `git rev-parse --git-dir`;
+exit 1 if $?; # rev-parse would have given "not a git dir" message.
+chomp($GIT_DIR);
+
my (@srcArgs, @dstArgs, @srcs, @dsts);
my ($src, $dst, $base, $dstDir);
+# remove any trailing slash in arguments
+for (@ARGV) { s/\/*$//; }
+
my $argCount = scalar @ARGV;
if (-d $ARGV[$argCount-1]) {
$dstDir = $ARGV[$argCount-1];
- # remove any trailing slash
- $dstDir =~ s/\/$//;
@srcArgs = @ARGV[0..$argCount-2];
-
+
foreach $src (@srcArgs) {
$base = $src;
$base =~ s/^.*\///;
@@ -46,10 +47,14 @@ if (-d $ARGV[$argCount-1]) {
}
}
else {
- if ($argCount != 2) {
+ if ($argCount < 2) {
+ print "Error: need at least two arguments\n";
+ exit(1);
+ }
+ if ($argCount > 2) {
print "Error: moving to directory '"
. $ARGV[$argCount-1]
- . "' not possible; not exisiting\n";
+ . "' not possible; not existing\n";
exit(1);
}
@srcArgs = ($ARGV[0]);
@@ -57,6 +62,16 @@ else {
$dstDir = "";
}
+# normalize paths, needed to compare against versioned files and update-index
+# also, this is nicer to end-users by doing ".//a/./b/.//./c" ==> "a/b/c"
+for (@srcArgs, @dstArgs) {
+ s|^\./||;
+ s|/\./|/| while (m|/\./|);
+ s|//+|/|g;
+ # Also "a/b/../c" ==> "a/c"
+ 1 while (s,(^|/)[^/]+/\.\./,$1,);
+}
+
my (@allfiles,@srcfiles,@dstfiles);
my $safesrc;
my (%overwritten, %srcForDst);
diff --git a/git-svnimport.perl b/git-svnimport.perl
index 0dd9fab9fe..86837edbdd 100755
--- a/git-svnimport.perl
+++ b/git-svnimport.perl
@@ -30,7 +30,7 @@ $SIG{'PIPE'}="IGNORE";
$ENV{'TZ'}="UTC";
our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,
- $opt_b,$opt_r,$opt_I,$opt_s,$opt_l,$opt_d,$opt_D);
+ $opt_b,$opt_r,$opt_I,$opt_A,$opt_s,$opt_l,$opt_d,$opt_D);
sub usage() {
print STDERR <<END;
@@ -38,12 +38,12 @@ Usage: ${\basename $0} # fetch/update GIT from SVN
[-o branch-for-HEAD] [-h] [-v] [-l max_rev]
[-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
[-d|-D] [-i] [-u] [-r] [-I ignorefilename] [-s start_chg]
- [-m] [-M regex] [SVN_URL]
+ [-m] [-M regex] [-A author_file] [SVN_URL]
END
exit(1);
}
-getopts("b:C:dDhiI:l:mM:o:rs:t:T:uv") or usage();
+getopts("A:b:C:dDhiI:l:mM:o:rs:t:T:uv") or usage();
usage if $opt_h;
my $tag_name = $opt_t || "tags";
@@ -68,6 +68,19 @@ if ($opt_M) {
push (@mergerx, qr/$opt_M/);
}
+our %users = ();
+if ($opt_A) {
+ die "Cannot open $opt_A\n" unless -f $opt_A;
+ open(my $authors,$opt_A);
+ while(<$authors>) {
+ chomp;
+ next unless /^(\S+?)\s*=\s*(.+?)\s*<(.+)>\s*$/;
+ (my $user,my $name,my $email) = ($1,$2,$3);
+ $users{$user} = [$name,$email];
+ }
+ close($authors);
+}
+
select(STDERR); $|=1; select(STDOUT);
@@ -485,6 +498,10 @@ sub commit {
if (not defined $author) {
$author_name = $author_email = "unknown";
+ } elsif ($opt_A) {
+ die "User $author is not listed in $opt_A\n"
+ unless exists $users{$author};
+ ($author_name,$author_email) = @{$users{$author}};
} elsif ($author =~ /^(.*?)\s+<(.*)>$/) {
($author_name, $author_email) = ($1, $2);
} else {