* Re: [PATCH] Per branch properties for pull and fetch
From: Martin Waitz @ 2006-07-27 8:55 UTC (permalink / raw)
To: Santi Béjar; +Cc: Git Mailing List
In-Reply-To: <87lkqfcvm2.fsf@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 590 bytes --]
hoi :)
On Thu, Jul 27, 2006 at 10:14:45AM +0200, Santi Béjar wrote:
> It allows to specify on a per branch basis the following:
> .- default repository to fetch
> .- default branches to merge on a per repository basis
> .- default pull.{octopus,twohead}
>
> So if you have this in the config:
> [branch "my"]
> remote=yours
> merge=master
> merge=our from theirs
> merge=mine from .
could we default the to-be-merged branch to "remotes/$remote/$branch" if
that exists?. That could make life a lot easier when using
clone --use-separate-remote.
--
Martin Waitz
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH 1/2] rebase: Fix the detection of fast-forwarding of the current branch to upstream.
From: Robert Shearman @ 2006-07-27 9:32 UTC (permalink / raw)
To: Git Mailing List
[-- Attachment #1: Type: text/plain, Size: 424 bytes --]
Previously, a rebasing operation with on a branch that is just tracking
an upstream branch would output a confusing "Nothing to do" due to no
patches being given to git-am.
The test brings the behaviour back into line with that of just before
e646c9c8c0aa995eac284ea0a2117add19c4461c.
Signed-off-by: Robert Shearman <rob@codeweavers.com>
---
git-rebase.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
[-- Attachment #2: 5d77c657b6e3b8fabe8690171a10aa54ec2cf641.diff --]
[-- Type: text/x-patch, Size: 374 bytes --]
diff --git a/git-rebase.sh b/git-rebase.sh
index 29028dd..5554541 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -281,7 +281,7 @@ git-reset --hard "$onto"
# If the $onto is a proper descendant of the tip of the branch, then
# we just fast forwarded.
-if test "$mb" = "$onto"
+if test "$mb" = "$branch"
then
echo >&2 "Fast-forwarded $branch to $newbase."
exit 0
^ permalink raw reply related
* [PATCH 2/2] rebase: Make the fast-fowarding message more user-friendly by using branch names instead of SHA1 IDs.
From: Robert Shearman @ 2006-07-27 9:32 UTC (permalink / raw)
To: Git Mailing List
[-- Attachment #1: Type: text/plain, Size: 134 bytes --]
Signed-off-by: Robert Shearman <rob@codeweavers.com>
---
git-rebase.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
[-- Attachment #2: 3bd88862ba13448b574662ffda717b96ddab8e98.diff --]
[-- Type: text/x-patch, Size: 355 bytes --]
diff --git a/git-rebase.sh b/git-rebase.sh
index 5554541..1c23798 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -283,7 +283,7 @@ # If the $onto is a proper descendant of
# we just fast forwarded.
if test "$mb" = "$branch"
then
- echo >&2 "Fast-forwarded $branch to $newbase."
+ echo >&2 "Fast-forwarded $branch_name to $onto_name."
exit 0
fi
^ permalink raw reply related
* Re: [PATCH] Per branch properties for pull and fetch
From: Santi @ 2006-07-27 9:40 UTC (permalink / raw)
To: Martin Waitz; +Cc: Git Mailing List
In-Reply-To: <20060727085516.GC27593@admingilde.org>
2006/7/27, Martin Waitz <tali@admingilde.org>:
> hoi :)
>
> On Thu, Jul 27, 2006 at 10:14:45AM +0200, Santi Béjar wrote:
> > It allows to specify on a per branch basis the following:
> > .- default repository to fetch
> > .- default branches to merge on a per repository basis
> > .- default pull.{octopus,twohead}
> >
> > So if you have this in the config:
> > [branch "my"]
> > remote=yours
> > merge=master
> > merge=our from theirs
> > merge=mine from .
>
> could we default the to-be-merged branch to "remotes/$remote/$branch" if
> that exists?. That could make life a lot easier when using
> clone --use-separate-remote.
I would prefer to change git-clone and git-branch to write the full
config. And I'll do this if this or someting like this is accepted.
Santi
^ permalink raw reply
* Re: [WIP] Status update on merge-recursive in C
From: Johannes Schindelin @ 2006-07-27 9:41 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Pavel Roskin
In-Reply-To: <7vu053o2g7.fsf@assigned-by-dhcp.cox.net>
Hi,
On Thu, 27 Jul 2006, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > On Sun, 9 Jul 2006, Pavel Roskin wrote:
> >
> >> - variable declarations in the middle of the code (allowed by c99 but
> >> not by ANSI C) and incomplete function declarations (no "void"). It's
> >> not C++, let's stick to the C standards.
> >...
> >> I'm attaching a patch that fixes everything except variable
> >> declarations.
> >
> > May I ask you a favour? Can you redo the patch in, say, two weeks? Thank
> > you!
>
> Now it's about two weeks so maybe we can apply this on top to
> clean up and prod you to continue ;-)?
*grin*
Actually, we continued a little with it, but I mainly waited what would
happen to "git-read-tree --rename"...
I will send an updated patch soon. The remaining TODOs after that are:
$ grep TODO merge-recursive.c
* TODO: we should not have to copy the SHA1s around, but rather reference
* TODO: check if we can just reuse the active_cache structure: it is already
* TODO: this can be streamlined by refactoring builtin-read-tree.c
* TODO: this can be streamlined by refactoring builtin-read-tree.c
* TODO: this can be streamlined by refactoring builtin-write-tree.c
/* General TODO: no javaIfiCation: rename updateCache to update_cache */
* TODO: once we no longer call external programs, we'd probably be better off
/* General TODO: get rid of all the debug messages */
/* TODO: refactor, so that 1/2 are not needed */
So, the biggest problem I see: refactoring builtin-read-tree. I really
could use some help there -- I already tried 3 times to come up with a
nice abstraction for unpack_trees() which could be used as a library
function.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] Per branch properties for pull and fetch
From: Santi @ 2006-07-27 10:06 UTC (permalink / raw)
To: Martin Waitz; +Cc: Git Mailing List
In-Reply-To: <8aa486160607270240h412b0dcek1d57eeb2b254fb2e@mail.gmail.com>
2006/7/27, Santi <sbejar@gmail.com>:
> 2006/7/27, Martin Waitz <tali@admingilde.org>:
> > hoi :)
> >
> > On Thu, Jul 27, 2006 at 10:14:45AM +0200, Santi Béjar wrote:
> > > It allows to specify on a per branch basis the following:
> > > .- default repository to fetch
> > > .- default branches to merge on a per repository basis
> > > .- default pull.{octopus,twohead}
> > >
> > > So if you have this in the config:
> > > [branch "my"]
> > > remote=yours
> > > merge=master
> > > merge=our from theirs
> > > merge=mine from .
> >
> > could we default the to-be-merged branch to "remotes/$remote/$branch" if
> > that exists?. That could make life a lot easier when using
> > clone --use-separate-remote.
>
> I would prefer to change git-clone and git-branch to write the full
> config. And I'll do this if this or someting like this is accepted.
>
On the other hand, my patch changes the behaviour only when explicitly
configured, and your proposed default would change the behaviour even
without changes to the config.
Santi
^ permalink raw reply
* Re: print errors from git-update-ref
From: Johannes Schindelin @ 2006-07-27 11:04 UTC (permalink / raw)
To: Shawn Pearce; +Cc: Junio C Hamano, Alex Riesen, Git Mailing List
In-Reply-To: <20060727012856.GB32492@spearce.org>
Hi,
On Wed, 26 Jul 2006, Shawn Pearce wrote:
> This change adds a test for trying to create a ref within a directory
> that is actually currently a file, and adds error printing within
> the ref locking routine should the resolve operation fail.
Why not just print an error message when the resolve operation fails,
instead of special casing this obscure corner case? It is way shorter,
too. The test should stay, though.
Ciao,
Dscho
^ permalink raw reply
* [PATCH] Cumulative update of merge-recursive in C
From: Johannes Schindelin @ 2006-07-27 11:17 UTC (permalink / raw)
To: git, junkio
This contains mainly three sorts of fixes:
- get rid of small wrapper functions
- reuse the diff_filespec structure when sha1, mode & path are needed
- Junio's pedantic updates
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
Sorry for the big patch; it seemed to be tiny each
time I committed.
merge-recursive.c | 894 ++++++++++++++++++++++-------------------------------
1 files changed, 366 insertions(+), 528 deletions(-)
diff --git a/merge-recursive.c b/merge-recursive.c
index 8d30519..85bb47a 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -25,9 +25,9 @@ #include "path-list.h"
/*#define DEBUG*/
#ifdef DEBUG
-#define debug(args, ...) fprintf(stderr, args, ## __VA_ARGS__)
+#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
-#define debug(args, ...)
+#define debug(...) do { ; /* nothing */ } while (0)
#endif
#ifdef DEBUG
@@ -61,13 +61,14 @@ static void show_ce_entry(const char *ta
fputc('\n', stderr);
}
-static void ls_files() {
+static void ls_files(void) {
int i;
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
show_ce_entry("", ce);
}
fprintf(stderr, "---\n");
+ if (0) ls_files(); /* avoid "unused" warning */
}
#endif
@@ -76,41 +77,6 @@ #endif
* - (const char *)commit->util set to the name, and
* - *(int *)commit->object.sha1 set to the virtual id.
*/
-static const char *commit_title(struct commit *commit, int *len)
-{
- const char *s = "(null commit)";
- *len = strlen(s);
-
- if ( commit->util ) {
- s = commit->util;
- *len = strlen(s);
- } else {
- if ( parse_commit(commit) != 0 ) {
- s = "(bad commit)";
- *len = strlen(s);
- } else {
- s = commit->buffer;
- char prev = '\0';
- while ( *s ) {
- if ( '\n' == prev && '\n' == *s ) {
- ++s;
- break;
- }
- prev = *s++;
- }
- *len = 0;
- while ( s[*len] && '\n' != s[*len] )
- ++(*len);
- }
- }
- return s;
-}
-
-static const char *commit_hex_sha1(const struct commit *commit)
-{
- return commit->util ? "virtual" : commit ?
- sha1_to_hex(commit->object.sha1) : "undefined";
-}
static unsigned commit_list_count(const struct commit_list *l)
{
@@ -136,41 +102,11 @@ static struct commit *make_virtual_commi
*/
static int sha_eq(const unsigned char *a, const unsigned char *b)
{
- if ( !a && !b )
+ if (!a && !b)
return 2;
return a && b && memcmp(a, b, 20) == 0;
}
-static void memswp(void *p1, void *p2, unsigned n)
-{
- unsigned char *a = p1, *b = p2;
- while ( n-- ) {
- *a ^= *b;
- *b ^= *a;
- *a ^= *b;
- ++a;
- ++b;
- }
-}
-
-/*
- * TODO: we should convert the merge_result users to
- * int blabla(..., struct commit **result)
- * like everywhere else in git.
- * Same goes for merge_tree_result and merge_file_info.
- */
-struct merge_result
-{
- struct commit *commit;
- unsigned clean:1;
-};
-
-struct merge_tree_result
-{
- struct tree *tree;
- unsigned clean:1;
-};
-
/*
* TODO: check if we can just reuse the active_cache structure: it is already
* sorted (by name, stage).
@@ -195,7 +131,7 @@ static void output(const char *fmt, ...)
{
va_list args;
int i;
- for ( i = output_indent; i--; )
+ for (i = output_indent; i--;)
fputs(" ", stdout);
va_start(args, fmt);
vfprintf(stdout, fmt, args);
@@ -203,11 +139,37 @@ static void output(const char *fmt, ...)
fputc('\n', stdout);
}
+static void output_commit_title(struct commit *commit)
+{
+ int i;
+ for (i = output_indent; i--;)
+ fputs(" ", stdout);
+ if (commit->util)
+ printf("virtual %s\n", (char *)commit->util);
+ else {
+ printf("%s ", sha1_to_hex(commit->object.sha1));
+ if (parse_commit(commit) != 0)
+ printf("(bad commit)\n");
+ else {
+ const char *s;
+ int len;
+ for (s = commit->buffer; *s; s++)
+ if (*s == '\n' && s[1] == '\n') {
+ s += 2;
+ break;
+ }
+ for (len = 0; s[len] && '\n' != s[len]; len++)
+ ; /* do nothing */
+ printf("%.*s\n", len, s);
+ }
+ }
+}
+
static const char *original_index_file;
static const char *temporary_index_file;
static int cache_dirty = 0;
-static int flush_cache()
+static int flush_cache(void)
{
/* flush temporary index */
struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
@@ -290,11 +252,12 @@ #if 0
getenv("GIT_INDEX_FILE"),
sha1_to_hex(tree->object.sha1));
#endif
+ int rc;
const char *argv[] = { "git-read-tree", NULL, NULL, };
if (cache_dirty)
die("read-tree with dirty cache");
argv[1] = sha1_to_hex(tree->object.sha1);
- int rc = run_command_v(2, argv);
+ rc = run_command_v(2, argv);
return rc < 0 ? -1: rc;
}
@@ -314,6 +277,7 @@ #if 0
sha1_to_hex(head->object.sha1),
sha1_to_hex(merge->object.sha1));
#endif
+ int rc;
const char *argv[] = {
"git-read-tree", NULL, "-m", NULL, NULL, NULL,
NULL,
@@ -324,50 +288,42 @@ #endif
argv[3] = sha1_to_hex(common->object.sha1);
argv[4] = sha1_to_hex(head->object.sha1);
argv[5] = sha1_to_hex(merge->object.sha1);
- int rc = run_command_v(6, argv);
+ rc = run_command_v(6, argv);
return rc < 0 ? -1: rc;
}
/*
* TODO: this can be streamlined by refactoring builtin-write-tree.c
*/
-static struct tree *git_write_tree()
+static struct tree *git_write_tree(void)
{
#if 0
fprintf(stderr, "GIT_INDEX_FILE='%s' git-write-tree\n",
getenv("GIT_INDEX_FILE"));
#endif
- if (cache_dirty)
- flush_cache();
- FILE *fp = popen("git-write-tree 2>/dev/null", "r");
+ FILE *fp;
+ int rc;
char buf[41];
unsigned char sha1[20];
int ch;
unsigned i = 0;
- while ( (ch = fgetc(fp)) != EOF )
- if ( i < sizeof(buf)-1 && ch >= '0' && ch <= 'f' )
+ if (cache_dirty)
+ flush_cache();
+ fp = popen("git-write-tree 2>/dev/null", "r");
+ while ((ch = fgetc(fp)) != EOF)
+ if (i < sizeof(buf)-1 && ch >= '0' && ch <= 'f')
buf[i++] = ch;
else
break;
- int rc = pclose(fp);
- if ( rc == -1 || WEXITSTATUS(rc) )
+ rc = pclose(fp);
+ if (rc == -1 || WEXITSTATUS(rc))
return NULL;
buf[i] = '\0';
- if ( get_sha1(buf, sha1) != 0 )
+ if (get_sha1(buf, sha1) != 0)
return NULL;
return lookup_tree(sha1);
}
-/*
- * TODO: get rid of files_and_dirs; we do not use it except for
- * current_file_set and current_dir_set, which are global already.
- */
-static struct
-{
- struct path_list *files;
- struct path_list *dirs;
-} files_and_dirs;
-
static int save_files_dirs(const unsigned char *sha1,
const char *base, int baselen, const char *path,
unsigned int mode, int stage)
@@ -379,70 +335,36 @@ static int save_files_dirs(const unsigne
newpath[baselen + len] = '\0';
if (S_ISDIR(mode))
- path_list_insert(newpath, files_and_dirs.dirs);
+ path_list_insert(newpath, ¤tDirectorySet);
else
- path_list_insert(newpath, files_and_dirs.files);
+ path_list_insert(newpath, ¤tFileSet);
free(newpath);
return READ_TREE_RECURSIVE;
}
-static int get_files_dirs(struct tree *tree,
- struct path_list *files,
- struct path_list *dirs)
+static int get_files_dirs(struct tree *tree)
{
int n;
- files_and_dirs.files = files;
- files_and_dirs.dirs = dirs;
debug("get_files_dirs ...\n");
if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs) != 0) {
debug(" get_files_dirs done (0)\n");
return 0;
}
- n = files->nr + dirs->nr;
+ n = currentFileSet.nr + currentDirectorySet.nr;
debug(" get_files_dirs done (%d)\n", n);
return n;
}
/*
- * TODO: this wrapper is so small, we can use path_list_lookup directly.
- * Same goes for index_entry_get(), free_index_entries(), find_rename_bysrc(),
- * free_rename_entries().
- */
-static struct stage_data *index_entry_find(struct path_list *ents,
- const char *path)
-{
- struct path_list_item *item = path_list_lookup(path, ents);
- if (item)
- return item->util;
- return NULL;
-}
-
-static struct stage_data *index_entry_get(struct path_list *ents,
- const char *path)
-{
- struct path_list_item *item = path_list_lookup(path, ents);
-
- if (item == NULL) {
- item = path_list_insert(path, ents);
- item->util = xcalloc(1, sizeof(struct stage_data));
- }
- return item->util;
-}
-
-/*
- * TODO: since the result of index_entry_from_db() is tucked into a
- * path_list anyway, this helper can do that already.
- */
-/*
* Returns a index_entry instance which doesn't have to correspond to
* a real cache entry in Git's index.
*/
-static struct stage_data *index_entry_from_db(const char *path,
- struct tree *o,
- struct tree *a,
- struct tree *b)
+static struct stage_data *insert_stage_data(const char *path,
+ struct tree *o, struct tree *a, struct tree *b,
+ struct path_list *entries)
{
+ struct path_list_item *item;
struct stage_data *e = xcalloc(1, sizeof(struct stage_data));
get_tree_entry(o->object.sha1, path,
e->stages[1].sha, &e->stages[1].mode);
@@ -450,24 +372,16 @@ static struct stage_data *index_entry_fr
e->stages[2].sha, &e->stages[2].mode);
get_tree_entry(b->object.sha1, path,
e->stages[3].sha, &e->stages[3].mode);
+ item = path_list_insert(path, entries);
+ item->util = e;
return e;
}
-static void free_index_entries(struct path_list **ents)
-{
- if (!*ents)
- return;
-
- path_list_clear(*ents, 1);
- free(*ents);
- *ents = NULL;
-}
-
/*
* Create a dictionary mapping file names to CacheEntry objects. The
* dictionary contains one entry for every path with a non-zero stage entry.
*/
-static struct path_list *get_unmerged()
+static struct path_list *get_unmerged(void)
{
struct path_list *unmerged = xcalloc(1, sizeof(struct path_list));
int i;
@@ -478,16 +392,22 @@ static struct path_list *get_unmerged()
cache_dirty++;
}
for (i = 0; i < active_nr; i++) {
+ struct path_list_item *item;
+ struct stage_data *e;
struct cache_entry *ce = active_cache[i];
if (!ce_stage(ce))
continue;
- struct stage_data *e = index_entry_get(unmerged, ce->name);
+ item = path_list_lookup(ce->name, unmerged);
+ if (!item) {
+ item = path_list_insert(ce->name, unmerged);
+ item->util = xcalloc(1, sizeof(struct stage_data));
+ }
+ e = item->util;
e->stages[ce_stage(ce)].mode = ntohl(ce->ce_mode);
memcpy(e->stages[ce_stage(ce)].sha, ce->sha1, 20);
}
- debug(" get_unmerged done\n");
return unmerged;
}
@@ -499,25 +419,6 @@ struct rename
unsigned processed:1;
};
-static struct rename *find_rename_bysrc(struct path_list *e,
- const char *name)
-{
- struct path_list_item *item = path_list_lookup(name, e);
- if (item)
- return item->util;
- return NULL;
-}
-
-static void free_rename_entries(struct path_list **list)
-{
- if (!*list)
- return;
-
- path_list_clear(*list, 0);
- free(*list);
- *list = NULL;
-}
-
/*
* Get information of all renames which occured between 'oTree' and
* 'tree'. We need the three trees in the merge ('oTree', 'aTree' and
@@ -530,13 +431,16 @@ static struct path_list *get_renames(str
struct tree *bTree,
struct path_list *entries)
{
+ int i;
+ struct path_list *renames;
+ struct diff_options opts;
#ifdef DEBUG
time_t t = time(0);
+
debug("getRenames ...\n");
#endif
- int i;
- struct path_list *renames = xcalloc(1, sizeof(struct path_list));
- struct diff_options opts;
+
+ renames = xcalloc(1, sizeof(struct path_list));
diff_setup(&opts);
opts.recursive = 1;
opts.detect_rename = DIFF_DETECT_RENAME;
@@ -546,6 +450,7 @@ #endif
diff_tree_sha1(oTree->object.sha1, tree->object.sha1, "", &opts);
diffcore_std(&opts);
for (i = 0; i < diff_queued_diff.nr; ++i) {
+ struct path_list_item *item;
struct rename *re;
struct diff_filepair *pair = diff_queued_diff.queue[i];
if (pair->status != 'R') {
@@ -555,78 +460,66 @@ #endif
re = xmalloc(sizeof(*re));
re->processed = 0;
re->pair = pair;
- re->src_entry = index_entry_find(entries, re->pair->one->path);
- /* TODO: should it not be an error, if src_entry was found? */
- if ( !re->src_entry ) {
- re->src_entry = index_entry_from_db(re->pair->one->path,
- oTree, aTree, bTree);
- struct path_list_item *item =
- path_list_insert(re->pair->one->path, entries);
- item->util = re->src_entry;
- }
- re->dst_entry = index_entry_find(entries, re->pair->two->path);
- if ( !re->dst_entry ) {
- re->dst_entry = index_entry_from_db(re->pair->two->path,
- oTree, aTree, bTree);
- struct path_list_item *item =
- path_list_insert(re->pair->two->path, entries);
- item->util = re->dst_entry;
- }
- struct path_list_item *item = path_list_insert(pair->one->path, renames);
+ item = path_list_lookup(re->pair->one->path, entries);
+ if (!item)
+ re->src_entry = insert_stage_data(re->pair->one->path,
+ oTree, aTree, bTree, entries);
+ else
+ re->src_entry = item->util;
+
+ item = path_list_lookup(re->pair->two->path, entries);
+ if (!item)
+ re->dst_entry = insert_stage_data(re->pair->two->path,
+ oTree, aTree, bTree, entries);
+ else
+ re->dst_entry = item->util;
+ item = path_list_insert(pair->one->path, renames);
item->util = re;
}
opts.output_format = DIFF_FORMAT_NO_OUTPUT;
diff_queued_diff.nr = 0;
diff_flush(&opts);
+#ifdef DEBUG
debug(" getRenames done in %ld\n", time(0)-t);
+#endif
return renames;
}
-/*
- * TODO: the code would be way nicer, if we had a struct containing just sha1 and mode.
- * In this particular case, we might get away reusing stage_data, no?
- */
-int update_stages(const char *path,
- unsigned char *osha, unsigned omode,
- unsigned char *asha, unsigned amode,
- unsigned char *bsha, unsigned bmode,
- int clear /* =True */)
+int update_stages(const char *path, struct diff_filespec *o,
+ struct diff_filespec *a, struct diff_filespec *b, int clear)
{
int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE;
- if ( clear )
- if (add_cacheinfo(0, null_sha1, path, 0, 0, options))
+ if (clear)
+ if (remove_file_from_cache(path))
return -1;
- if ( omode )
- if (add_cacheinfo(omode, osha, path, 1, 0, options))
+ if (o)
+ if (add_cacheinfo(o->mode, o->sha1, path, 1, 0, options))
return -1;
- if ( amode )
- if (add_cacheinfo(omode, osha, path, 2, 0, options))
+ if (a)
+ if (add_cacheinfo(a->mode, a->sha1, path, 2, 0, options))
return -1;
- if ( bmode )
- if (add_cacheinfo(omode, osha, path, 3, 0, options))
+ if (b)
+ if (add_cacheinfo(b->mode, b->sha1, path, 3, 0, options))
return -1;
return 0;
}
-/*
- * TODO: there has to be a function in libgit doing this exact thing.
- */
static int remove_path(const char *name)
{
- int ret;
- char *slash;
+ int ret, len;
+ char *slash, *dirs;
ret = unlink(name);
- if ( ret )
+ if (ret)
return ret;
- int len = strlen(name);
- char *dirs = malloc(len+1);
+ len = strlen(name);
+ dirs = malloc(len+1);
memcpy(dirs, name, len);
dirs[len] = '\0';
- while ( (slash = strrchr(name, '/')) ) {
+ while ((slash = strrchr(name, '/'))) {
*slash = '\0';
len = slash - name;
- if ( rmdir(name) != 0 )
+ if (rmdir(name) != 0)
break;
}
free(dirs);
@@ -636,7 +529,7 @@ static int remove_path(const char *name)
/* General TODO: unC99ify the code: no declaration after code */
/* General TODO: no javaIfiCation: rename updateCache to update_cache */
/*
- * TODO: once we no longer call external programs, we'd probably be better of
+ * TODO: once we no longer call external programs, we'd probably be better off
* not setting / getting the environment variable GIT_INDEX_FILE all the time.
*/
int remove_file(int clean, const char *path)
@@ -644,17 +537,17 @@ int remove_file(int clean, const char *p
int updateCache = index_only || clean;
int updateWd = !index_only;
- if ( updateCache ) {
+ if (updateCache) {
if (!cache_dirty)
read_cache_from(getenv("GIT_INDEX_FILE"));
cache_dirty++;
if (remove_file_from_cache(path))
return -1;
}
- if ( updateWd )
+ if (updateWd)
{
unlink(path);
- if ( errno != ENOENT || errno != EISDIR )
+ if (errno != ENOENT || errno != EISDIR)
return -1;
remove_path(path);
}
@@ -664,55 +557,31 @@ int remove_file(int clean, const char *p
static char *unique_path(const char *path, const char *branch)
{
char *newpath = xmalloc(strlen(path) + 1 + strlen(branch) + 8 + 1);
+ int suffix = 0;
+ struct stat st;
+ char *p = newpath + strlen(newpath);
strcpy(newpath, path);
strcat(newpath, "~");
- char *p = newpath + strlen(newpath);
strcpy(p, branch);
- for ( ; *p; ++p )
- if ( '/' == *p )
+ for (; *p; ++p)
+ if ('/' == *p)
*p = '_';
- int suffix = 0;
- struct stat st;
- while ( path_list_has_path(¤tFileSet, newpath) ||
- path_list_has_path(¤tDirectorySet, newpath) ||
- lstat(newpath, &st) == 0 ) {
+ while (path_list_has_path(¤tFileSet, newpath) ||
+ path_list_has_path(¤tDirectorySet, newpath) ||
+ lstat(newpath, &st) == 0)
sprintf(p, "_%d", suffix++);
- }
+
path_list_insert(newpath, ¤tFileSet);
return newpath;
}
-/*
- * TODO: except for create_last, this so looks like
- * safe_create_leading_directories().
- */
-static int mkdir_p(const char *path, unsigned long mode, int create_last)
+static int mkdir_p(const char *path, unsigned long mode)
{
+ /* path points to cache entries, so strdup before messing with it */
char *buf = strdup(path);
- char *p;
-
- for ( p = buf; *p; ++p ) {
- if ( *p != '/' )
- continue;
- *p = '\0';
- if (mkdir(buf, mode)) {
- int e = errno;
- if ( e == EEXIST ) {
- struct stat st;
- if ( !stat(buf, &st) && S_ISDIR(st.st_mode) )
- goto next; /* ok */
- errno = e;
- }
- free(buf);
- return -1;
- }
- next:
- *p = '/';
- }
+ int result = safe_create_leading_directories(buf);
free(buf);
- if ( create_last && mkdir(path, mode) )
- return -1;
- return 0;
+ return result;
}
static void flush_buffer(int fd, const char *buf, unsigned long size)
@@ -732,17 +601,16 @@ static void flush_buffer(int fd, const c
}
}
-/* General TODO: reindent according to guide lines (no if ( blabla )) */
void update_file_flags(const unsigned char *sha,
- unsigned mode,
- const char *path,
- int updateCache,
- int updateWd)
+ unsigned mode,
+ const char *path,
+ int update_cache,
+ int update_wd)
{
- if ( index_only )
- updateWd = 0;
+ if (index_only)
+ update_wd = 0;
- if ( updateWd ) {
+ if (update_wd) {
char type[20];
void *buf;
unsigned long size;
@@ -750,37 +618,38 @@ void update_file_flags(const unsigned ch
buf = read_sha1_file(sha, type, &size);
if (!buf)
die("cannot read object %s '%s'", sha1_to_hex(sha), path);
- if ( strcmp(type, blob_type) != 0 )
+ if (strcmp(type, blob_type) != 0)
die("blob expected for %s '%s'", sha1_to_hex(sha), path);
- if ( S_ISREG(mode) ) {
- if ( mkdir_p(path, 0777, 0 /* don't create last element */) )
+ if (S_ISREG(mode)) {
+ int fd;
+ if (mkdir_p(path, 0777))
die("failed to create path %s: %s", path, strerror(errno));
unlink(path);
- if ( mode & 0100 )
+ if (mode & 0100)
mode = 0777;
else
mode = 0666;
- int fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
- if ( fd < 0 )
+ fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
+ if (fd < 0)
die("failed to open %s: %s", path, strerror(errno));
flush_buffer(fd, buf, size);
close(fd);
- } else if ( S_ISLNK(mode) ) {
- char *linkTarget = malloc(size + 1);
- memcpy(linkTarget, buf, size);
- linkTarget[size] = '\0';
- mkdir_p(path, 0777, 0);
- symlink(linkTarget, path);
+ } else if (S_ISLNK(mode)) {
+ char *lnk = malloc(size + 1);
+ memcpy(lnk, buf, size);
+ lnk[size] = '\0';
+ mkdir_p(path, 0777);
+ unlink(lnk);
+ symlink(lnk, path);
} else
die("do not know what to do with %06o %s '%s'",
mode, sha1_to_hex(sha), path);
}
- if ( updateCache )
- add_cacheinfo(mode, sha, path, 0, updateWd, ADD_CACHE_OK_TO_ADD);
+ if (update_cache)
+ add_cacheinfo(mode, sha, path, 0, update_wd, ADD_CACHE_OK_TO_ADD);
}
-/* TODO: is this often used? if not, do direct call */
void update_file(int clean,
const unsigned char *sha,
unsigned mode,
@@ -819,64 +688,53 @@ static char *git_unpack_file(const unsig
return path;
}
-/*
- * TODO: the signature would be much more efficient using stage_data
- */
-static struct merge_file_info merge_file(const char *oPath,
- const unsigned char *oSha,
- unsigned oMode,
- const char *aPath,
- const unsigned char *aSha,
- unsigned aMode,
- const char *bPath,
- const unsigned char *bSha,
- unsigned bMode,
- const char *branch1Name,
- const char *branch2Name)
+static struct merge_file_info merge_file(struct diff_filespec *o,
+ struct diff_filespec *a, struct diff_filespec *b,
+ const char *branch1Name, const char *branch2Name)
{
struct merge_file_info result;
result.merge = 0;
result.clean = 1;
- if ( (S_IFMT & aMode) != (S_IFMT & bMode) ) {
+ if ((S_IFMT & a->mode) != (S_IFMT & b->mode)) {
result.clean = 0;
- if ( S_ISREG(aMode) ) {
- result.mode = aMode;
- memcpy(result.sha, aSha, 20);
+ if (S_ISREG(a->mode)) {
+ result.mode = a->mode;
+ memcpy(result.sha, a->sha1, 20);
} else {
- result.mode = bMode;
- memcpy(result.sha, bSha, 20);
+ result.mode = b->mode;
+ memcpy(result.sha, b->sha1, 20);
}
} else {
- if ( memcmp(aSha, oSha, 20) != 0 && memcmp(bSha, oSha, 20) != 0 )
+ if (!sha_eq(a->sha1, o->sha1) && !sha_eq(b->sha1, o->sha1))
result.merge = 1;
- result.mode = aMode == oMode ? bMode: aMode;
-
- if ( memcmp(aSha, oSha, 20) == 0 )
- memcpy(result.sha, bSha, 20);
- else if ( memcmp(bSha, oSha, 20) == 0 )
- memcpy(result.sha, aSha, 20);
- else if ( S_ISREG(aMode) ) {
+ result.mode = a->mode == o->mode ? b->mode: a->mode;
- int code = 1;
+ if (sha_eq(a->sha1, o->sha1))
+ memcpy(result.sha, b->sha1, 20);
+ else if (sha_eq(b->sha1, o->sha1))
+ memcpy(result.sha, a->sha1, 20);
+ else if (S_ISREG(a->mode)) {
+ int code = 1, fd;
+ struct stat st;
char orig[PATH_MAX];
char src1[PATH_MAX];
char src2[PATH_MAX];
-
- git_unpack_file(oSha, orig);
- git_unpack_file(aSha, src1);
- git_unpack_file(bSha, src2);
-
const char *argv[] = {
"merge", "-L", NULL, "-L", NULL, "-L", NULL,
src1, orig, src2,
NULL
};
char *la, *lb, *lo;
- argv[2] = la = strdup(mkpath("%s/%s", branch1Name, aPath));
- argv[6] = lb = strdup(mkpath("%s/%s", branch2Name, bPath));
- argv[4] = lo = strdup(mkpath("orig/%s", oPath));
+
+ git_unpack_file(o->sha1, orig);
+ git_unpack_file(a->sha1, src1);
+ git_unpack_file(b->sha1, src2);
+
+ argv[2] = la = strdup(mkpath("%s/%s", branch1Name, a->path));
+ argv[6] = lb = strdup(mkpath("%s/%s", branch2Name, b->path));
+ argv[4] = lo = strdup(mkpath("orig/%s", o->path));
#if 0
printf("%s %s %s %s %s %s %s %s %s %s\n",
@@ -888,17 +746,15 @@ #endif
free(la);
free(lb);
free(lo);
- if ( code && code < -256 ) {
+ if (code && code < -256) {
die("Failed to execute 'merge'. merge(1) is used as the "
"file-level merge tool. Is 'merge' in your path?");
}
- struct stat st;
- int fd = open(src1, O_RDONLY);
+ fd = open(src1, O_RDONLY);
if (fd < 0 || fstat(fd, &st) < 0 ||
index_fd(result.sha, fd, &st, 1,
"blob"))
die("Unable to add %s to database", src1);
- close(fd);
unlink(orig);
unlink(src1);
@@ -906,12 +762,12 @@ #endif
result.clean = WEXITSTATUS(code) == 0;
} else {
- if ( !(S_ISLNK(aMode) || S_ISLNK(bMode)) )
+ if (!(S_ISLNK(a->mode) || S_ISLNK(b->mode)))
die("cannot merge modes?");
- memcpy(result.sha, aSha, 20);
+ memcpy(result.sha, a->sha1, 20);
- if ( memcmp(aSha, bSha, 20) != 0 )
+ if (!sha_eq(a->sha1, b->sha1))
result.clean = 0;
}
}
@@ -942,17 +798,9 @@ static void conflict_rename_rename(struc
ren2_dst, branch1, dstName2);
remove_file(0, ren2_dst);
}
- update_stages(dstName1,
- NULL, 0,
- ren1->pair->two->sha1, ren1->pair->two->mode,
- NULL, 0,
- 1 /* clear */);
- update_stages(dstName2,
- NULL, 0,
- NULL, 0,
- ren2->pair->two->sha1, ren2->pair->two->mode,
- 1 /* clear */);
- while ( delp-- )
+ update_stages(dstName1, NULL, ren1->pair->two, NULL, 1);
+ update_stages(dstName2, NULL, NULL, ren2->pair->two, 1);
+ while (delp--)
free(del[delp]);
}
@@ -989,66 +837,73 @@ static int process_renames(struct path_l
const char *branchNameA,
const char *branchNameB)
{
- int cleanMerge = 1, i;
- struct path_list srcNames = {NULL, 0, 0, 0}, byDstA = {NULL, 0, 0, 0}, byDstB = {NULL, 0, 0, 0};
+ int cleanMerge = 1, i, j;
+ struct path_list byDstA = {NULL, 0, 0, 0}, byDstB = {NULL, 0, 0, 0};
const struct rename *sre;
- /*
- * TODO: think about a saner way to do this.
- * Since both renamesA and renamesB are sorted, it should
- * be much more efficient to traverse both simultaneously,
- * only byDstA and byDstB should be needed.
- */
- debug("processRenames...\n");
for (i = 0; i < renamesA->nr; i++) {
sre = renamesA->items[i].util;
- path_list_insert(sre->pair->one->path, &srcNames);
path_list_insert(sre->pair->two->path, &byDstA)->util
= sre->dst_entry;
}
for (i = 0; i < renamesB->nr; i++) {
sre = renamesB->items[i].util;
- path_list_insert(sre->pair->one->path, &srcNames);
path_list_insert(sre->pair->two->path, &byDstB)->util
= sre->dst_entry;
}
- for (i = 0; i < srcNames.nr; i++) {
- char *src = srcNames.items[i].path;
+ for (i = 0, j = 0; i < renamesA->nr || j < renamesB->nr;) {
+ int compare;
+ char *src;
struct path_list *renames1, *renames2, *renames2Dst;
- struct rename *ren1, *ren2;
+ struct rename *ren1 = NULL, *ren2 = NULL;
const char *branchName1, *branchName2;
- ren1 = find_rename_bysrc(renamesA, src);
- ren2 = find_rename_bysrc(renamesB, src);
+ const char *ren1_src, *ren1_dst;
+
+ if (i >= renamesA->nr) {
+ compare = 1;
+ ren2 = renamesB->items[j++].util;
+ } else if (j >= renamesB->nr) {
+ compare = -1;
+ ren1 = renamesA->items[i++].util;
+ } else {
+ compare = strcmp(renamesA->items[i].path,
+ renamesB->items[j].path);
+ ren1 = renamesA->items[i++].util;
+ ren2 = renamesB->items[j++].util;
+ }
+
/* TODO: refactor, so that 1/2 are not needed */
- if ( ren1 ) {
+ if (ren1) {
renames1 = renamesA;
renames2 = renamesB;
renames2Dst = &byDstB;
branchName1 = branchNameA;
branchName2 = branchNameB;
} else {
+ struct rename *tmp;
renames1 = renamesB;
renames2 = renamesA;
renames2Dst = &byDstA;
branchName1 = branchNameB;
branchName2 = branchNameA;
- struct rename *tmp = ren2;
+ tmp = ren2;
ren2 = ren1;
ren1 = tmp;
}
+ src = ren1->pair->one->path;
ren1->dst_entry->processed = 1;
ren1->src_entry->processed = 1;
- if ( ren1->processed )
+ if (ren1->processed)
continue;
ren1->processed = 1;
- const char *ren1_src = ren1->pair->one->path;
- const char *ren1_dst = ren1->pair->two->path;
+ ren1_src = ren1->pair->one->path;
+ ren1_dst = ren1->pair->two->path;
- if ( ren2 ) {
+ if (ren2) {
const char *ren2_src = ren2->pair->one->path;
const char *ren2_dst = ren2->pair->two->path;
/* Renamed in 1 and renamed in 2 */
@@ -1067,57 +922,48 @@ static int process_renames(struct path_l
} else {
remove_file(1, ren1_src);
struct merge_file_info mfi;
- mfi = merge_file(ren1_src,
- ren1->pair->one->sha1,
- ren1->pair->one->mode,
- ren1_dst,
- ren1->pair->two->sha1,
- ren1->pair->two->mode,
- ren2_dst,
- ren2->pair->two->sha1,
- ren2->pair->two->mode,
+ mfi = merge_file(ren1->pair->one,
+ ren1->pair->two,
+ ren2->pair->two,
branchName1,
branchName2);
- if ( mfi.merge || !mfi.clean )
+ if (mfi.merge || !mfi.clean)
output("Renaming %s->%s", src, ren1_dst);
- if ( mfi.merge )
+ if (mfi.merge)
output("Auto-merging %s", ren1_dst);
- if ( !mfi.clean ) {
+ if (!mfi.clean) {
output("CONFLICT (content): merge conflict in %s",
ren1_dst);
cleanMerge = 0;
- if ( !index_only )
+ if (!index_only)
update_stages(ren1_dst,
- ren1->pair->one->sha1,
- ren1->pair->one->mode,
- ren1->pair->two->sha1,
- ren1->pair->two->mode,
- ren2->pair->two->sha1,
- ren2->pair->two->mode,
+ ren1->pair->one,
+ ren1->pair->two,
+ ren2->pair->two,
1 /* clear */);
}
update_file(mfi.clean, mfi.sha, mfi.mode, ren1_dst);
}
} else {
/* Renamed in 1, maybe changed in 2 */
- remove_file(1, ren1_src);
-
- unsigned char srcShaOtherBranch[20], dstShaOtherBranch[20];
- unsigned srcModeOtherBranch, dstModeOtherBranch;
-
- int stage = renamesA == renames1 ? 3: 2;
+ struct path_list_item *item;
+ /* we only use sha1 and mode of these */
+ struct diff_filespec src_other, dst_other;
+ int tryMerge, stage = renamesA == renames1 ? 3: 2;
- memcpy(srcShaOtherBranch, ren1->src_entry->stages[stage].sha, 20);
- srcModeOtherBranch = ren1->src_entry->stages[stage].mode;
+ remove_file(1, ren1_src);
- memcpy(dstShaOtherBranch, ren1->dst_entry->stages[stage].sha, 20);
- dstModeOtherBranch = ren1->dst_entry->stages[stage].mode;
+ memcpy(src_other.sha1,
+ ren1->src_entry->stages[stage].sha, 20);
+ src_other.mode = ren1->src_entry->stages[stage].mode;
+ memcpy(dst_other.sha1,
+ ren1->dst_entry->stages[stage].sha, 20);
+ dst_other.mode = ren1->dst_entry->stages[stage].mode;
- int tryMerge = 0;
- char *newPath;
+ tryMerge = 0;
if (path_list_has_path(¤tDirectorySet, ren1_dst)) {
cleanMerge = 0;
@@ -1126,14 +972,15 @@ static int process_renames(struct path_l
ren1_src, ren1_dst, branchName1,
ren1_dst, branchName2);
conflict_rename_dir(ren1, branchName1);
- } else if ( memcmp(srcShaOtherBranch, null_sha1, 20) == 0 ) {
+ } else if (sha_eq(src_other.sha1, null_sha1)) {
cleanMerge = 0;
output("CONFLICT (rename/delete): Rename %s->%s in %s "
"and deleted in %s",
ren1_src, ren1_dst, branchName1,
branchName2);
update_file(0, ren1->pair->two->sha1, ren1->pair->two->mode, ren1_dst);
- } else if ( memcmp(dstShaOtherBranch, null_sha1, 20) != 0 ) {
+ } else if (!sha_eq(dst_other.sha1, null_sha1)) {
+ const char *newPath;
cleanMerge = 0;
tryMerge = 1;
output("CONFLICT (rename/add): Rename %s->%s in %s. "
@@ -1142,8 +989,9 @@ static int process_renames(struct path_l
ren1_dst, branchName2);
newPath = unique_path(ren1_dst, branchName2);
output("Adding as %s instead", newPath);
- update_file(0, dstShaOtherBranch, dstModeOtherBranch, newPath);
- } else if ( (ren2 = find_rename_bysrc(renames2Dst, ren1_dst)) ) {
+ update_file(0, dst_other.sha1, dst_other.mode, newPath);
+ } else if ((item = path_list_lookup(ren1_dst, renames2Dst))) {
+ ren2 = item->util;
cleanMerge = 0;
ren2->processed = 1;
output("CONFLICT (rename/rename): Rename %s->%s in %s. "
@@ -1154,53 +1002,41 @@ static int process_renames(struct path_l
} else
tryMerge = 1;
- if ( tryMerge ) {
- const char *oname = ren1_src;
- const char *aname = ren1_dst;
- const char *bname = ren1_src;
- unsigned char osha[20], asha[20], bsha[20];
- unsigned omode = ren1->pair->one->mode;
- unsigned amode = ren1->pair->two->mode;
- unsigned bmode = srcModeOtherBranch;
- memcpy(osha, ren1->pair->one->sha1, 20);
- memcpy(asha, ren1->pair->two->sha1, 20);
- memcpy(bsha, srcShaOtherBranch, 20);
- const char *aBranch = branchName1;
- const char *bBranch = branchName2;
-
- if ( renamesA != renames1 ) {
- memswp(&aname, &bname, sizeof(aname));
- memswp(asha, bsha, 20);
- memswp(&aBranch, &bBranch, sizeof(aBranch));
- }
+ if (tryMerge) {
+ struct diff_filespec *o, *a, *b;
struct merge_file_info mfi;
- mfi = merge_file(oname, osha, omode,
- aname, asha, amode,
- bname, bsha, bmode,
- aBranch, bBranch);
+ src_other.path = (char *)ren1_src;
+
+ o = ren1->pair->one;
+ if (renamesA == renames1) {
+ a = ren1->pair->two;
+ b = &src_other;
+ } else {
+ b = ren1->pair->two;
+ a = &src_other;
+ }
+ mfi = merge_file(o, a, b,
+ branchNameA, branchNameB);
- if ( mfi.merge || !mfi.clean )
+ if (mfi.merge || !mfi.clean)
output("Renaming %s => %s", ren1_src, ren1_dst);
- if ( mfi.merge )
+ if (mfi.merge)
output("Auto-merging %s", ren1_dst);
- if ( !mfi.clean ) {
+ if (!mfi.clean) {
output("CONFLICT (rename/modify): Merge conflict in %s",
ren1_dst);
cleanMerge = 0;
- if ( !index_only )
+ if (!index_only)
update_stages(ren1_dst,
- osha, omode,
- asha, amode,
- bsha, bmode,
- 1 /* clear */);
+ o, a, b, 1);
}
update_file(mfi.clean, mfi.sha, mfi.mode, ren1_dst);
}
}
}
- path_list_clear(&srcNames, 0);
- debug(" processRenames done\n");
+ path_list_clear(&byDstA, 0);
+ path_list_clear(&byDstB, 0);
if (cache_dirty)
flush_cache();
@@ -1229,20 +1065,20 @@ static int process_entry(const char *pat
unsigned aMode = entry->stages[2].mode;
unsigned bMode = entry->stages[3].mode;
- if ( oSha && (!aSha || !bSha) ) {
+ if (oSha && (!aSha || !bSha)) {
/* Case A: Deleted in one */
- if ( (!aSha && !bSha) ||
- (sha_eq(aSha, oSha) && !bSha) ||
- (!aSha && sha_eq(bSha, oSha)) ) {
+ if ((!aSha && !bSha) ||
+ (sha_eq(aSha, oSha) && !bSha) ||
+ (!aSha && sha_eq(bSha, oSha))) {
/* Deleted in both or deleted in one and
* unchanged in the other */
- if ( aSha )
+ if (aSha)
output("Removing %s", path);
remove_file(1, path);
} else {
/* Deleted in one and changed in the other */
cleanMerge = 0;
- if ( !aSha ) {
+ if (!aSha) {
output("CONFLICT (delete/modify): %s deleted in %s "
"and modified in %s. Version %s of %s left in tree.",
path, branch1Name,
@@ -1257,8 +1093,8 @@ static int process_entry(const char *pat
}
}
- } else if ( (!oSha && aSha && !bSha) ||
- (!oSha && !aSha && bSha) ) {
+ } else if ((!oSha && aSha && !bSha) ||
+ (!oSha && !aSha && bSha)) {
/* Case B: Added in one. */
const char *addBranch;
const char *otherBranch;
@@ -1266,7 +1102,7 @@ static int process_entry(const char *pat
const unsigned char *sha;
const char *conf;
- if ( aSha ) {
+ if (aSha) {
addBranch = branch1Name;
otherBranch = branch2Name;
mode = aMode;
@@ -1279,9 +1115,9 @@ static int process_entry(const char *pat
sha = bSha;
conf = "directory/file";
}
- if ( path_list_has_path(¤tDirectorySet, path) ) {
- cleanMerge = 0;
+ if (path_list_has_path(¤tDirectorySet, path)) {
const char *newPath = unique_path(path, addBranch);
+ cleanMerge = 0;
output("CONFLICT (%s): There is a directory with name %s in %s. "
"Adding %s as %s",
conf, path, otherBranch, path, newPath);
@@ -1291,10 +1127,10 @@ static int process_entry(const char *pat
output("Adding %s", path);
update_file(1, sha, mode, path);
}
- } else if ( !oSha && aSha && bSha ) {
+ } else if (!oSha && aSha && bSha) {
/* Case C: Added in both (check for same permissions). */
- if ( sha_eq(aSha, bSha) ) {
- if ( aMode != bMode ) {
+ if (sha_eq(aSha, bSha)) {
+ if (aMode != bMode) {
cleanMerge = 0;
output("CONFLICT: File %s added identically in both branches, "
"but permissions conflict %06o->%06o",
@@ -1306,9 +1142,10 @@ static int process_entry(const char *pat
assert(0 && "This case must be handled by git-read-tree");
}
} else {
+ const char *newPath1, *newPath2;
cleanMerge = 0;
- const char *newPath1 = unique_path(path, branch1Name);
- const char *newPath2 = unique_path(path, branch2Name);
+ newPath1 = unique_path(path, branch1Name);
+ newPath2 = unique_path(path, branch2Name);
output("CONFLICT (add/add): File %s added non-identically "
"in both branches. Adding as %s and %s instead.",
path, newPath1, newPath2);
@@ -1317,22 +1154,30 @@ static int process_entry(const char *pat
update_file(0, bSha, bMode, newPath2);
}
- } else if ( oSha && aSha && bSha ) {
+ } else if (oSha && aSha && bSha) {
/* case D: Modified in both, but differently. */
- output("Auto-merging %s", path);
struct merge_file_info mfi;
- mfi = merge_file(path, oSha, oMode,
- path, aSha, aMode,
- path, bSha, bMode,
+ struct diff_filespec o, a, b;
+
+ output("Auto-merging %s", path);
+ o.path = a.path = b.path = (char *)path;
+ memcpy(o.sha1, oSha, 20);
+ o.mode = oMode;
+ memcpy(a.sha1, aSha, 20);
+ a.mode = aMode;
+ memcpy(b.sha1, bSha, 20);
+ b.mode = bMode;
+
+ mfi = merge_file(&o, &a, &b,
branch1Name, branch2Name);
- if ( mfi.clean )
+ if (mfi.clean)
update_file(1, mfi.sha, mfi.mode, path);
else {
cleanMerge = 0;
output("CONFLICT (content): Merge conflict in %s", path);
- if ( index_only )
+ if (index_only)
update_file(0, mfi.sha, mfi.mode, path);
else
update_file_flags(mfi.sha, mfi.mode, path,
@@ -1347,73 +1192,68 @@ static int process_entry(const char *pat
return cleanMerge;
}
-static struct merge_tree_result merge_trees(struct tree *head,
- struct tree *merge,
- struct tree *common,
- const char *branch1Name,
- const char *branch2Name)
+static int merge_trees(struct tree *head,
+ struct tree *merge,
+ struct tree *common,
+ const char *branch1Name,
+ const char *branch2Name,
+ struct tree **result)
{
- int code;
- struct merge_tree_result result = { NULL, 0 };
- if ( !memcmp(common->object.sha1, merge->object.sha1, 20) ) {
+ int code, clean;
+ if (sha_eq(common->object.sha1, merge->object.sha1)) {
output("Already uptodate!");
- result.tree = head;
- result.clean = 1;
- return result;
+ *result = head;
+ return 1;
}
- debug("merge_trees ...\n");
code = git_merge_trees(index_only ? "-i": "-u", common, head, merge);
- if ( code != 0 )
+ if (code != 0)
die("merging of trees %s and %s failed",
sha1_to_hex(head->object.sha1),
sha1_to_hex(merge->object.sha1));
- result.tree = git_write_tree();
+ *result = git_write_tree();
- if ( !result.tree ) {
+ if (!*result) {
+ struct path_list *entries, *re_head, *re_merge;
+ int i;
path_list_clear(¤tFileSet, 1);
path_list_clear(¤tDirectorySet, 1);
- get_files_dirs(head, ¤tFileSet, ¤tDirectorySet);
- get_files_dirs(merge, ¤tFileSet, ¤tDirectorySet);
+ get_files_dirs(head);
+ get_files_dirs(merge);
- struct path_list *entries = get_unmerged();
- struct path_list *re_head, *re_merge;
+ entries = get_unmerged();
re_head = get_renames(head, common, head, merge, entries);
re_merge = get_renames(merge, common, head, merge, entries);
- result.clean = process_renames(re_head, re_merge,
- branch1Name, branch2Name);
- debug("\tprocessing entries...\n");
- int i;
+ clean = process_renames(re_head, re_merge,
+ branch1Name, branch2Name);
for (i = 0; i < entries->nr; i++) {
const char *path = entries->items[i].path;
struct stage_data *e = entries->items[i].util;
if (e->processed)
continue;
if (!process_entry(path, e, branch1Name, branch2Name))
- result.clean = 0;
+ clean = 0;
}
- free_rename_entries(&re_merge);
- free_rename_entries(&re_head);
- free_index_entries(&entries);
+ path_list_clear(re_merge, 0);
+ path_list_clear(re_head, 0);
+ path_list_clear(entries, 1);
- if (result.clean || index_only)
- result.tree = git_write_tree();
+ if (clean || index_only)
+ *result = git_write_tree();
else
- result.tree = NULL;
- debug("\t processing entries done\n");
+ *result = NULL;
} else {
- result.clean = 1;
+ clean = 1;
printf("merging of trees %s and %s resulted in %s\n",
sha1_to_hex(head->object.sha1),
sha1_to_hex(merge->object.sha1),
- sha1_to_hex(result.tree->object.sha1));
+ sha1_to_hex((*result)->object.sha1));
}
- debug(" merge_trees done\n");
- return result;
+ return clean;
}
/*
@@ -1421,87 +1261,86 @@ static struct merge_tree_result merge_tr
* commit object and a flag indicating the cleaness of the merge.
*/
static
-struct merge_result merge(struct commit *h1,
+int merge(struct commit *h1,
struct commit *h2,
const char *branch1Name,
const char *branch2Name,
int callDepth /* =0 */,
- struct commit *ancestor /* =None */)
+ struct commit *ancestor /* =None */,
+ struct commit **result)
{
- struct merge_result result = { NULL, 0 };
- const char *msg;
- int msglen;
struct commit_list *ca = NULL, *iter;
struct commit *mergedCA;
- struct merge_tree_result mtr;
+ struct tree *mrtree;
+ int clean;
output("Merging:");
- msg = commit_title(h1, &msglen);
- /* TODO: refactor. we always show the sha1 with the title */
- output("%s %.*s", commit_hex_sha1(h1), msglen, msg);
- msg = commit_title(h2, &msglen);
- output("%s %.*s", commit_hex_sha1(h2), msglen, msg);
+ output_commit_title(h1);
+ output_commit_title(h2);
- if ( ancestor )
+ if (ancestor)
commit_list_insert(ancestor, &ca);
else
ca = get_merge_bases(h1, h2, 1);
output("found %u common ancestor(s):", commit_list_count(ca));
- for (iter = ca; iter; iter = iter->next) {
- msg = commit_title(iter->item, &msglen);
- output("%s %.*s", commit_hex_sha1(iter->item), msglen, msg);
- }
+ for (iter = ca; iter; iter = iter->next)
+ output_commit_title(iter->item);
mergedCA = pop_commit(&ca);
- /* TODO: what happens when merge with virtual commits fails? */
for (iter = ca; iter; iter = iter->next) {
output_indent = callDepth + 1;
- result = merge(mergedCA, iter->item,
- "Temporary merge branch 1",
- "Temporary merge branch 2",
- callDepth + 1,
- NULL);
- mergedCA = result.commit;
+ /*
+ * When the merge fails, the result contains files
+ * with conflict markers. The cleanness flag is
+ * ignored, it was never acutally used, as result of
+ * merge_trees has always overwritten it: the commited
+ * "conflicts" were already resolved.
+ */
+ merge(mergedCA, iter->item,
+ "Temporary merge branch 1",
+ "Temporary merge branch 2",
+ callDepth + 1,
+ NULL,
+ &mergedCA);
output_indent = callDepth;
- if ( !mergedCA )
+ if (!mergedCA)
die("merge returned no commit");
}
- if ( callDepth == 0 ) {
- setup_index(0);
+ if (callDepth == 0) {
+ setup_index(0 /* $GIT_DIR/index */);
index_only = 0;
} else {
- setup_index(1);
+ setup_index(1 /* temporary index */);
git_read_tree(h1->tree);
index_only = 1;
}
- mtr = merge_trees(h1->tree, h2->tree,
- mergedCA->tree, branch1Name, branch2Name);
+ clean = merge_trees(h1->tree, h2->tree, mergedCA->tree,
+ branch1Name, branch2Name, &mrtree);
- if ( !ancestor && (mtr.clean || index_only) ) {
- result.commit = make_virtual_commit(mtr.tree, "merged tree");
- commit_list_insert(h1, &result.commit->parents);
- commit_list_insert(h2, &result.commit->parents->next);
+ if (!ancestor && (clean || index_only)) {
+ *result = make_virtual_commit(mrtree, "merged tree");
+ commit_list_insert(h1, &(*result)->parents);
+ commit_list_insert(h2, &(*result)->parents->next);
} else
- result.commit = NULL;
+ *result = NULL;
- result.clean = mtr.clean;
- return result;
+ return clean;
}
static struct commit *get_ref(const char *ref)
{
unsigned char sha1[20];
struct object *object;
-
+
if (get_sha1(ref, sha1))
die("Could not resolve ref '%s'", ref);
object = deref_tag(parse_object(sha1), ref, strlen(ref));
- if (object->type != OBJ_COMMIT)
+ if (object->type != TYPE_COMMIT)
return NULL;
if (parse_commit((struct commit *)object))
die("Could not parse commit '%s'", sha1_to_hex(object->sha1));
@@ -1512,6 +1351,9 @@ int main(int argc, char *argv[])
{
static const char *bases[2];
static unsigned bases_count = 0;
+ int i, clean;
+ const char *branch1, *branch2;
+ struct commit *result, *h1, *h2;
original_index_file = getenv("GIT_INDEX_FILE");
@@ -1523,7 +1365,6 @@ int main(int argc, char *argv[])
if (argc < 4)
die("Usage: %s <base>... -- <head> <remote> ...\n", argv[0]);
- int i;
for (i = 1; i < argc; ++i) {
if (!strcmp(argv[i], "--"))
break;
@@ -1533,26 +1374,23 @@ int main(int argc, char *argv[])
if (argc - i != 3) /* "--" "<head>" "<remote>" */
die("Not handling anything other than two heads merge.");
- const char *branch1, *branch2;
-
branch1 = argv[++i];
branch2 = argv[++i];
printf("Merging %s with %s\n", branch1, branch2);
- struct merge_result result;
- struct commit *h1 = get_ref(branch1);
- struct commit *h2 = get_ref(branch2);
+ h1 = get_ref(branch1);
+ h2 = get_ref(branch2);
if (bases_count == 1) {
struct commit *ancestor = get_ref(bases[0]);
- result = merge(h1, h2, branch1, branch2, 0, ancestor);
+ clean = merge(h1, h2, branch1, branch2, 0, ancestor, &result);
} else
- result = merge(h1, h2, branch1, branch2, 0, NULL);
+ clean = merge(h1, h2, branch1, branch2, 0, NULL, &result);
if (cache_dirty)
flush_cache();
- return result.clean ? 0: 1;
+ return clean ? 0: 1;
}
/*
^ permalink raw reply related
* Re: Licensing and the library version of git
From: Petr Baudis @ 2006-07-27 11:41 UTC (permalink / raw)
To: Jon Smirl; +Cc: git
In-Reply-To: <9e4733910607261436v4c0802e5v7301e904593f9bab@mail.gmail.com>
Dear diary, on Wed, Jul 26, 2006 at 11:36:16PM CEST, I got a letter
where Jon Smirl <jonsmirl@gmail.com> said that...
> Can the library version of git be licensed LGPL instead of GPL? If it
> is GPL then it can't be linked into non-GPL projects like Eclipse.
Probably not since it essentially _is_ the base Git code now. You would
need to find all the Git copyright holders and convince them to
relicence it, since there are thoughts about moving more code to the
library, and even parts of scripts might eventually end up there after
rewrite in C.
And I didn't even get to discussing whether LGPL is actually desirable
for Git.
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Snow falling on Perl. White noise covering line noise.
Hides all the bugs too. -- J. Putnam
^ permalink raw reply
* Re: Licensing and the library version of git
From: Johannes Schindelin @ 2006-07-27 12:02 UTC (permalink / raw)
To: Petr Baudis; +Cc: Jon Smirl, git
In-Reply-To: <20060727114105.GZ13776@pasky.or.cz>
Hi,
On Thu, 27 Jul 2006, Petr Baudis wrote:
> And I didn't even get to discussing whether LGPL is actually desirable
> for Git.
... or whether it is neccessary for an Eclipse-plugin to something else
than GPL.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] Per branch properties for pull and fetch
From: Martin Waitz @ 2006-07-27 12:02 UTC (permalink / raw)
To: Santi; +Cc: Git Mailing List
In-Reply-To: <8aa486160607270306s3f49a01cq91ef61e2c9f005e@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 752 bytes --]
hoi :)
On Thu, Jul 27, 2006 at 12:06:34PM +0200, Santi wrote:
> >> could we default the to-be-merged branch to "remotes/$remote/$branch" if
> >> that exists?. That could make life a lot easier when using
> >> clone --use-separate-remote.
> On the other hand, my patch changes the behaviour only when explicitly
> configured, and your proposed default would change the behaviour even
> without changes to the config.
that is correct.
The current default is to always use the remote's master branch, right?
What do others think: does it make sense to default to the same
branchname on the remote side?
It could make life a bit easier if you want to synchronize several topic
branches between different sites.
--
Martin Waitz
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Git clone stalls at a read(3, ...) saw using strace
From: André Goddard Rosa @ 2006-07-27 12:16 UTC (permalink / raw)
To: git; +Cc: junkio
Hi, all!
Please CC me as I'm not subscribed.
Using GIT 1.4.1, I tried to get this repository:
# git clone git://source.mvista.com/git/linux-davinci-2.6.git
After some time the download stalled completely. I used ps and
saw two git processes.
Using strace, I saw that the first one, "git clone", was waiting
with waitpid()
for its child termination.
Its child, "git pack --all -k", was stalled at a "read(3, ...)"
I went to /proc and saw that fd 3 was a pipe. Anyone know why this
is happening?
I found an issue somewhat related in google (not sure that is the
same problem):
http://groups.google.com/group/fa.linux.kernel/browse_thread/thread/e64a92f28def32a7/93bd8bf5df1fcc66?lnk=st&q=&rnum=1#93bd8bf5df1fcc66
It stalled at the first 60 Mb transfered. After CTRL+C it deletes
and I have to start again from scratch.
Thank you for the great alternative to bitkeeper and CVS,
--
[]s,
André Goddard
^ permalink raw reply
* Re: [PATCH] Eliminate Scalar::Util usage from private-Error.pm
From: Randal L. Schwartz @ 2006-07-27 12:47 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Jakub Narebski, git
In-Reply-To: <Pine.LNX.4.63.0607261702500.29667@wbgn013.biozentrum.uni-wuerzburg.de>
>>>>> "Johannes" == Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Johannes> Think ActiveState.
Think ActiveState for the last time and see Strawberry Perl instead.
<http://vanillaperl.com/>.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
^ permalink raw reply
* Re: Licensing and the library version of git
From: Jon Smirl @ 2006-07-27 12:54 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Petr Baudis, git
In-Reply-To: <Pine.LNX.4.63.0607271400160.29667@wbgn013.biozentrum.uni-wuerzburg.de>
On 7/27/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Hi,
>
> On Thu, 27 Jul 2006, Petr Baudis wrote:
>
> > And I didn't even get to discussing whether LGPL is actually desirable
> > for Git.
>
> ... or whether it is neccessary for an Eclipse-plugin to something else
> than GPL.
Eclipse is not licensed GPL. To use the git library with Eclipse it
would need a JNI wrapper which would link it into the code. The work
around would be to make the user compile and link the JNI wrapper. But
I see that someone is already writing a pure Java version which will
work around the GPL problem assuming the Java version is released
under a compatible license.
In general libraries should be licensed LGPL to avoid the license
incompatibility problem. A GPL library forces the main app to be GPL
too. You may like trying to force GPL onto the app but many apps are
stuck with the license they have and can't be changed since there is
no way to contact the original developers. A GPL git library means
that these apps simply won't use git.
This also means that there will never be integrated git support in
Microsoft Visual Studio. This has impacts on switching cross platform
apps like Mozilla to git.
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply
* Re: [PATCH] Per branch properties for pull and fetch
From: Santi @ 2006-07-27 13:10 UTC (permalink / raw)
To: Martin Waitz; +Cc: Git Mailing List
In-Reply-To: <20060727120220.GD27593@admingilde.org>
> The current default is to always use the remote's master branch, right?
No.
For .git/remotes/ remotes it defaults to the first Pull line.
For .git/branches/ remotes if defaults to master, but you can specify
another branch.
Santi
^ permalink raw reply
* Re: Licensing and the library version of git
From: Petr Baudis @ 2006-07-27 13:11 UTC (permalink / raw)
To: Jon Smirl; +Cc: Johannes Schindelin, git
In-Reply-To: <9e4733910607270554p5622ee20ida8c264cf3122500@mail.gmail.com>
Dear diary, on Thu, Jul 27, 2006 at 02:54:54PM CEST, I got a letter
where Jon Smirl <jonsmirl@gmail.com> said that...
> In general libraries should be licensed LGPL to avoid the license
> incompatibility problem. A GPL library forces the main app to be GPL
> too.
But really another main app here (Git) is ending up in the library.
You can still always use the "Git ABI" - the commands. Or you could try
having a GPL'd "Git/Eclipse toolkit" which would reduce the barrier to
only single exec per Git invocation or something, but it would be
probably somewhat tricky on the derived works playground.
> You may like trying to force GPL onto the app but many apps are
> stuck with the license they have and can't be changed since there is
> no way to contact the original developers.
At this point, git-shortlog lists exactly 200 people (at least entries
like Unknown or No name are all linux@horizon.com ;-).
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Snow falling on Perl. White noise covering line noise.
Hides all the bugs too. -- J. Putnam
^ permalink raw reply
* testing for cloned repository
From: Robert White @ 2006-07-27 13:46 UTC (permalink / raw)
To: git
I am using:
if [ -f ".git/remotes/origin" ]; then
# this repository is a clone
fi
in a bash script to test if a repository was cloned and then do
appropriate pulls and pushes which fit my situation.
Is this the proper way to test this or should I be using something
different?
Thanks in advance for your help and for providing git. I have been
using it on my Linux and MacOSX machines without any problems.
Bob White
^ permalink raw reply
* Re: [PATCH] Eliminate Scalar::Util usage from private-Error.pm
From: Johannes Schindelin @ 2006-07-27 14:00 UTC (permalink / raw)
To: Randal L. Schwartz; +Cc: Jakub Narebski, git
In-Reply-To: <86ejw7b4em.fsf@blue.stonehenge.com>
Hi,
On Thu, 27 Jul 2006, Randal L. Schwartz wrote:
> >>>>> "Johannes" == Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> Johannes> Think ActiveState.
>
> Think ActiveState for the last time and see Strawberry Perl instead.
> <http://vanillaperl.com/>.
Wishful thinking. If it wasn't for political reasons, certain people would
use cygwin's perl already, instead of ActiveState.
Ciao,
Dscho
^ permalink raw reply
* [PATCH] mailinfo: accept >From in message header
From: Michael S. Tsirkin @ 2006-07-27 14:03 UTC (permalink / raw)
To: git
Hi!
Mail I get sometimes has multiple From lines, like this:
>From Majordomo@vger.kernel.org Thu Jul 27 16:39:36 2006
>From mtsirkin Thu Jul 27 16:39:36 2006
Received: from yok.mtl.com [10.0.8.11]
....
which confuses git-mailinfo since that does not recognize >From
as a valid header line. The following patch makes git-applymbox
work for me:
---
Recognize >From XXX as a valid header line.
Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index ac53f76..2b6e9fa 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -446,7 +446,7 @@ static int read_one_header_line(char *li
break;
}
/* Count mbox From headers as headers */
- if (!ofs && !memcmp(line, "From ", 5))
+ if (!ofs && (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6)))
ofs = 1;
return ofs;
}
--
MST
^ permalink raw reply related
* Re: Licensing and the library version of git
From: Johannes Schindelin @ 2006-07-27 14:04 UTC (permalink / raw)
To: Jon Smirl; +Cc: Petr Baudis, git
In-Reply-To: <9e4733910607270554p5622ee20ida8c264cf3122500@mail.gmail.com>
Hi,
On Thu, 27 Jul 2006, Jon Smirl wrote:
> On 7/27/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > Hi,
> >
> > On Thu, 27 Jul 2006, Petr Baudis wrote:
> >
> > > And I didn't even get to discussing whether LGPL is actually desirable
> > > for Git.
> >
> > ... or whether it is neccessary for an Eclipse-plugin to something else
> > than GPL.
>
> Eclipse is not licensed GPL.
We are talking about Eclipse _plugins_ here. Often (especially when the
deciding people have $$ in their eyes), plugins have less restrictions
(for example, WSAD would not be possible if _all_ extensions to Eclipse
would have to be CPL).
Ciao,
Dscho
^ permalink raw reply
* Re: testing for cloned repository
From: Johannes Schindelin @ 2006-07-27 14:10 UTC (permalink / raw)
To: Robert White; +Cc: git
In-Reply-To: <0AC9E5E7-52CC-4715-BB26-622A2177308B@mac.com>
Hi,
On Thu, 27 Jul 2006, Robert White wrote:
> if [ -f ".git/remotes/origin" ]; then
> # this repository is a clone
> fi
> in a bash script to test if a repository was cloned and then do appropriate
> pulls and pushes which fit my situation.
I think it would be better to do this:
-- snip --
. git-parse-remote
test "$(get_remote_url origin)" != origin && echo "is cloned"
-- snap --
There are 3 different ways to store remote information ATM, and this
method gets them all (even if, at a certain distant time in the future,
the default should be changed).
Hth,
Dscho
^ permalink raw reply
* Re: [PATCH] Eliminate Scalar::Util usage from private-Error.pm
From: Randal L. Schwartz @ 2006-07-27 14:22 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Jakub Narebski, git
In-Reply-To: <Pine.LNX.4.63.0607271559161.29667@wbgn013.biozentrum.uni-wuerzburg.de>
>>>>> "Johannes" == Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
Johannes> Wishful thinking. If it wasn't for political reasons, certain people would
Johannes> use cygwin's perl already, instead of ActiveState.
I don't think this is a "cygwin" perl though. This is released under
Perl's terms, so it's not just gnu. It's a complete build system with
a bundled C compiler, running on Windows natively.
--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
^ permalink raw reply
* Re: [PATCH] Eliminate Scalar::Util usage from private-Error.pm
From: Johannes Schindelin @ 2006-07-27 14:32 UTC (permalink / raw)
To: Randal L. Schwartz; +Cc: Jakub Narebski, git
In-Reply-To: <867j1zb00h.fsf@blue.stonehenge.com>
Hi,
On Thu, 27 Jul 2006, Randal L. Schwartz wrote:
> >>>>> "Johannes" == Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> Johannes> Wishful thinking. If it wasn't for political reasons, certain people would
> Johannes> use cygwin's perl already, instead of ActiveState.
>
> I don't think this is a "cygwin" perl though. This is released under
> Perl's terms, so it's not just gnu. It's a complete build system with
> a bundled C compiler, running on Windows natively.
What free people rarely think about: Windows has a severe path problem. It
is not the only problem of Windows, but a very real, and very annoying
one. Nobody in her right mind would try to make ":" part of a path, let
alone ";" part of the $PATH!
So I think it is still better to use cygwin's perl, not ActiveState, or
even Strawberry (which ice cream addict came up with _that_ one?).
At least, it is better, _if_ you have a choice.
Ciao,
Dscho
^ permalink raw reply
* Re: Licensing and the library version of git
From: Jon Smirl @ 2006-07-27 16:11 UTC (permalink / raw)
To: Petr Baudis; +Cc: Johannes Schindelin, git
In-Reply-To: <20060727131127.GA13776@pasky.or.cz>
On 7/27/06, Petr Baudis <pasky@suse.cz> wrote:
> > You may like trying to force GPL onto the app but many apps are
> > stuck with the license they have and can't be changed since there is
> > no way to contact the original developers.
>
> At this point, git-shortlog lists exactly 200 people (at least entries
> like Unknown or No name are all linux@horizon.com ;-).
Inability to integrate with Microsoft Visual Studio is going to have a
lot of impact on the cross platform use of git. Is a conscious
decision being made to stop this integration or is this just unplanned
side effect of the original license? If this is an unplanned side
effect, the quicker we move, the easier it is to fix.
Note that only the code going into the library needs to be LGPL. That
should significantly reduce the number of authors that need to be
contacted.
A first step to fixing this would be to add an immediate requirement
that all new code that is targeted to library functions be licensed
LGPL. That will at least stop the problem from getting any worse.
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply
* Re: Licensing and the library version of git
From: Johannes Schindelin @ 2006-07-27 16:38 UTC (permalink / raw)
To: Jon Smirl; +Cc: Petr Baudis, git
In-Reply-To: <9e4733910607270911p50d25d97w1a898fc7a9119e7d@mail.gmail.com>
Hi,
On Thu, 27 Jul 2006, Jon Smirl wrote:
> On 7/27/06, Petr Baudis <pasky@suse.cz> wrote:
> > > You may like trying to force GPL onto the app but many apps are
> > > stuck with the license they have and can't be changed since there is
> > > no way to contact the original developers.
> >
> > At this point, git-shortlog lists exactly 200 people (at least entries
> > like Unknown or No name are all linux@horizon.com ;-).
>
> Inability to integrate with Microsoft Visual Studio is going to have a
> lot of impact on the cross platform use of git. Is a conscious
> decision being made to stop this integration or is this just unplanned
> side effect of the original license? If this is an unplanned side
> effect, the quicker we move, the easier it is to fix.
If you want to do it, go ahead. I think the reason it has not been done so
far is that nobody had the need, or alternatively was not ready to do
it or hire someone to do it.
> Note that only the code going into the library needs to be LGPL. That
> should significantly reduce the number of authors that need to be
> contacted.
No and no.
Let me tackle the second point first: Almost all functionality is in the
library, and more is to be transferred to it.
The first point: If you want to integrate git into MSVC, you have to
provide it via the SCCI. Note that the letter "I" stands for "Interface",
which makes a runtime linking with the component a non-derivative work.
Which basically means that you need not GPL MSVC.
> A first step to fixing this would be to add an immediate requirement
> that all new code that is targeted to library functions be licensed
> LGPL. That will at least stop the problem from getting any worse.
If you still feel the need for LGPL, go ahead, find all contributors and
contact them.
Ciao,
Dscho
^ 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