* Re: What's cooking in git/spearce.git (topics)
From: Steffen Prohaska @ 2007-10-22 15:27 UTC (permalink / raw)
To: Git Mailing List; +Cc: Shawn O. Pearce
In-Reply-To: <20071022063222.GS14735@spearce.org>
On Oct 22, 2007, at 8:32 AM, Shawn O. Pearce wrote:
> * sp/push-refspec (Sun Oct 14 10:54:45 2007 +0200) 6 commits
> - push, send-pack: use same rules as git-rev-parse to resolve
> refspecs
> - add ref_cmp_full_short() comparing full ref name with a short name
> - push, send-pack: support pushing HEAD to real ref name
> - rev-parse: teach "git rev-parse --symbolic" to print the full ref
> name
> - add get_sha1_with_real_ref() returning full name of ref on demand
> - push, send-pack: fix test if remote branch exists for colon-less
> refspec
>
> I've briefly looked at this series and there's reasons why its not
> in next yet.
It's not ready for next. Especially the last patch in the list
changes the existing behaviour in a way that might be unexpected
by longtime git users. And maybe we even need for the 1.6 cycle
before we can change the behaviour of git push.
> Its actually something that I'm interested in seeing
> fixed as the current behavior of how git-push matches refs on the
> remote side is just plain nuts. I'll look at it further after I
> get ph/parseopt and cc/skip into next.
I planned to draw a conclusion from the discussion in
http://marc.info/?l=git&m=119286893014690&w=2
and send an updated proposal based on what I learnt. But
unfortunately I didn't have time yet.
My impression now is that the details of the behaviour of "git
push" are hard to understand and should be made more explicit.
Related tasks are currently encoded in the refspecs, but the
details are not always obvious right away:
- creation of new branches on the remote side.
- deletion of branches on the remote side.
- pushing of branches matching on local and remote side.
- pushing local branches explicitly to a different ref on the remote.
- save newbies from pushing to 'non-standard' location, that
is only push to heads and tags.
- but also allow to push to funny refs if you force git to
do this.
All this is related to the topic above, although its maybe too much
to be solved at once.
Steffen
^ permalink raw reply
* Re: [PATCH] execv_git_cmd(): also try PATH if everything else fails.
From: Johannes Sixt @ 2007-10-22 15:36 UTC (permalink / raw)
To: Andreas Ericsson, Scott Parish; +Cc: Johannes Schindelin, Shawn O. Pearce, git
In-Reply-To: <471CBF88.6020300@op5.se>
Andreas Ericsson schrieb:
> Scott Parish wrote:
>> I'm tempted to try a different approach. What if instead of looping
>> and building up strings of all the different absolute paths we want
>> to try we just prepend to PATH with the correct extra precedence,
>> and then call execvp on the command we want?
>>
>
> That's how the original git --exec-dir feature got implemented. There's
> even a nifty function for it in git.c; prepend_to_path(). It's a
> provably workable solution.
The reason that this was done is for the sake of shell scripts: They need to
have the path that was finally decided as exec-path in $PATH.
But I can't think of any negative side effect if *all* exec-path candidates
are in $PATH. It's important, though, that all paths are absolute because
the tools chdir every now and then.
-- Hannes
^ permalink raw reply
* Re: [PATCH, take 1] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-22 16:33 UTC (permalink / raw)
To: skimo
Cc: Git Mailing List, Junio C Hamano, Shawn O. Pearce, David Kastrup,
Jeff King
In-Reply-To: <20071022070750.GM1179MdfPADPa@greensroom.kotnet.org>
On Mon, 22 Oct 2007, Sven Verdoolaege wrote:
>
> Aren't you truncating the ptr list after the first entry here?
> (While you still need the whole list in free_file_table.)
Yes. I didn't have that bug in the first version (I didn't do a separate
"free_file_table()" at all - I just free'd the src/dst pointer lists at
the end of that function). But I wanted to "clean up" the thing. Duh.
Linus
^ permalink raw reply
* odd behavior with concurrent fetch/checkout
From: J. Bruce Fields @ 2007-10-22 16:51 UTC (permalink / raw)
To: git
Just now I checked out a topic branch in my working repo:
git checkout server-xprt-switch
and while waiting for it to complete (I just started work and caches
were all cold), I ran a
git fetch origin
in another window to update from Linus. The git fetch gave a warning:
remote: Generating pack...
remote: Counting objects: 7550
remote: Done counting 12885 objects.
remote: Result has 8400 objects.
remote: Deltifying 8400 objects...
remote: 100% (8400/8400) done
Indexing 8400 objects...
remote: Total 8400 (delta 7257), reused 5696 (delta 4586)
100% (8400/8400) done
Resolving 7257 deltas...
100% (7257/7257) done
* refs/remotes/origin/master: fast forward to branch 'master' of
* git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
old..new: d85714d..55b70a0
Cannot fetch into the current branch.
Why the warning? Also, afterwards I was left with server-xprt-switch
pointing to the tip of the branch I'd just switched from (another
miscellaneous topic branch). The working directory was in some
completely different state--thanks to a quick reset --hard I don't know
what it was. Also, in the reflog for the checked-out branch:
commit bac1e7977eb4781e62cee7f1c7c3d13a9e5d8d74
Reflog: server-xprt-switch@{0} (J. Bruce Fields <bfields@citi.umich.edu>)
Reflog message: fetch origin: Undoing incorrectly fetched HEAD.
Author: J. Bruce Fields <bfields@citi.umich.edu>
Date: Mon Oct 22 12:32:37 2007 -0400
...
Why was a fetch into the remote fooling with HEAD or anything under
refs/heads/?
--b.
^ permalink raw reply
* [PATCH] "current_exec_path" is a misleading name, use "argv_exec_path"
From: Scott R Parish @ 2007-10-22 17:01 UTC (permalink / raw)
To: git
Signed-off-by: Scott R Parish <srp@srparish.net>
---
exec_cmd.c | 12 ++++++------
exec_cmd.h | 2 +-
git.c | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index 9b74ed2..8b681d0 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -5,11 +5,11 @@
extern char **environ;
static const char *builtin_exec_path = GIT_EXEC_PATH;
-static const char *current_exec_path;
+static const char *argv_exec_path = 0;
-void git_set_exec_path(const char *exec_path)
+void git_set_argv_exec_path(const char *exec_path)
{
- current_exec_path = exec_path;
+ argv_exec_path = exec_path;
}
@@ -18,8 +18,8 @@ const char *git_exec_path(void)
{
const char *env;
- if (current_exec_path)
- return current_exec_path;
+ if (argv_exec_path)
+ return argv_exec_path;
env = getenv(EXEC_PATH_ENVIRONMENT);
if (env && *env) {
@@ -34,7 +34,7 @@ int execv_git_cmd(const char **argv)
{
char git_command[PATH_MAX + 1];
int i;
- const char *paths[] = { current_exec_path,
+ const char *paths[] = { argv_exec_path,
getenv(EXEC_PATH_ENVIRONMENT),
builtin_exec_path };
diff --git a/exec_cmd.h b/exec_cmd.h
index 849a839..da99287 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -1,7 +1,7 @@
#ifndef GIT_EXEC_CMD_H
#define GIT_EXEC_CMD_H
-extern void git_set_exec_path(const char *exec_path);
+extern void git_set_argv_exec_path(const char *exec_path);
extern const char* git_exec_path(void);
extern int execv_git_cmd(const char **argv); /* NULL terminated */
extern int execl_git_cmd(const char *cmd, ...);
diff --git a/git.c b/git.c
index e1c99e3..f659338 100644
--- a/git.c
+++ b/git.c
@@ -51,7 +51,7 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
if (!prefixcmp(cmd, "--exec-path")) {
cmd += 11;
if (*cmd == '=')
- git_set_exec_path(cmd + 1);
+ git_set_argv_exec_path(cmd + 1);
else {
puts(git_exec_path());
exit(0);
--
gitgui.0.8.4.11176.gd9205-dirty
^ permalink raw reply related
* [PATCH] use only the PATH for exec'ing git commands
From: Scott R Parish @ 2007-10-22 17:01 UTC (permalink / raw)
To: git
We need to correctly set up PATH for non-c based git commands. Since we
already do this, we can just use that PATH and execvp, instead of looping
over the paths with execve.
This patch adds a setup_path() function to exec_cmd.c, which sets
the PATH order correctly for our search order. execv_git_cmd() is
stripped down to setting up argv and calling execvp(). git.c's main()
only only needs to call setup_path().
Signed-off-by: Scott R Parish <srp@srparish.net>
---
exec_cmd.c | 122 ++++++++++++++++++++++++++----------------------------------
exec_cmd.h | 1 +
git.c | 43 +++------------------
3 files changed, 61 insertions(+), 105 deletions(-)
diff --git a/exec_cmd.c b/exec_cmd.c
index 8b681d0..b154c24 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -29,85 +29,69 @@ const char *git_exec_path(void)
return builtin_exec_path;
}
+static void add_path(struct strbuf *out, const char *path)
+{
+ if (path && strlen(path)) {
+ if (is_absolute_path(path))
+ strbuf_addstr(out, path);
+ else
+ strbuf_addstr(out, make_absolute_path(path));
+
+ strbuf_addch(out, ':');
+ }
+}
+
+void setup_path(const char *cmd_path)
+{
+ const char *old_path = getenv("PATH");
+ struct strbuf new_path;
+
+ strbuf_init(&new_path, 0);
+
+ add_path(&new_path, argv_exec_path);
+ add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
+ add_path(&new_path, builtin_exec_path);
+ add_path(&new_path, cmd_path);
+
+ if (old_path)
+ strbuf_addstr(&new_path, old_path);
+ else
+ strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
+
+ setenv("PATH", new_path.buf, 1);
+
+ strbuf_release(&new_path);
+}
+
int execv_git_cmd(const char **argv)
{
- char git_command[PATH_MAX + 1];
- int i;
- const char *paths[] = { argv_exec_path,
- getenv(EXEC_PATH_ENVIRONMENT),
- builtin_exec_path };
-
- for (i = 0; i < ARRAY_SIZE(paths); ++i) {
- size_t len;
- int rc;
- const char *exec_dir = paths[i];
- const char *tmp;
-
- if (!exec_dir || !*exec_dir) continue;
-
- if (*exec_dir != '/') {
- if (!getcwd(git_command, sizeof(git_command))) {
- fprintf(stderr, "git: cannot determine "
- "current directory: %s\n",
- strerror(errno));
- break;
- }
- len = strlen(git_command);
-
- /* Trivial cleanup */
- while (!prefixcmp(exec_dir, "./")) {
- exec_dir += 2;
- while (*exec_dir == '/')
- exec_dir++;
- }
-
- rc = snprintf(git_command + len,
- sizeof(git_command) - len, "/%s",
- exec_dir);
- if (rc < 0 || rc >= sizeof(git_command) - len) {
- fprintf(stderr, "git: command name given "
- "is too long.\n");
- break;
- }
- } else {
- if (strlen(exec_dir) + 1 > sizeof(git_command)) {
- fprintf(stderr, "git: command name given "
- "is too long.\n");
- break;
- }
- strcpy(git_command, exec_dir);
- }
-
- len = strlen(git_command);
- rc = snprintf(git_command + len, sizeof(git_command) - len,
- "/git-%s", argv[0]);
- if (rc < 0 || rc >= sizeof(git_command) - len) {
- fprintf(stderr,
- "git: command name given is too long.\n");
- break;
- }
+ struct strbuf cmd;
+ const char *tmp;
- /* argv[0] must be the git command, but the argv array
- * belongs to the caller, and my be reused in
- * subsequent loop iterations. Save argv[0] and
- * restore it on error.
- */
+ strbuf_init(&cmd, 0);
+ strbuf_addf(&cmd, "git-%s", argv[0]);
- tmp = argv[0];
- argv[0] = git_command;
+ /* argv[0] must be the git command, but the argv array
+ * belongs to the caller, and my be reused in
+ * subsequent loop iterations. Save argv[0] and
+ * restore it on error.
+ */
+ tmp = argv[0];
+ argv[0] = cmd.buf;
- trace_argv_printf(argv, -1, "trace: exec:");
+ trace_argv_printf(argv, -1, "trace: exec:");
- /* execve() can only ever return if it fails */
- execve(git_command, (char **)argv, environ);
+ /* execvp() can only ever return if it fails */
+ execvp(cmd.buf, (char **)argv);
- trace_printf("trace: exec failed: %s\n", strerror(errno));
+ trace_printf("trace: exec failed: %s\n", strerror(errno));
- argv[0] = tmp;
- }
- return -1;
+ argv[0] = tmp;
+ strbuf_release(&cmd);
+
+ return -1;
}
diff --git a/exec_cmd.h b/exec_cmd.h
index da99287..a892355 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -3,6 +3,7 @@
extern void git_set_argv_exec_path(const char *exec_path);
extern const char* git_exec_path(void);
+extern void setup_path(const char *);
extern int execv_git_cmd(const char **argv); /* NULL terminated */
extern int execl_git_cmd(const char *cmd, ...);
diff --git a/git.c b/git.c
index f659338..a639e42 100644
--- a/git.c
+++ b/git.c
@@ -6,28 +6,6 @@
const char git_usage_string[] =
"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
-static void prepend_to_path(const char *dir, int len)
-{
- const char *old_path = getenv("PATH");
- char *path;
- int path_len = len;
-
- if (!old_path)
- old_path = "/usr/local/bin:/usr/bin:/bin";
-
- path_len = len + strlen(old_path) + 1;
-
- path = xmalloc(path_len + 1);
-
- memcpy(path, dir, len);
- path[len] = ':';
- memcpy(path + len + 1, old_path, path_len - len);
-
- setenv("PATH", path, 1);
-
- free(path);
-}
-
static int handle_options(const char*** argv, int* argc, int* envchanged)
{
int handled = 0;
@@ -403,7 +381,7 @@ int main(int argc, const char **argv)
{
const char *cmd = argv[0] ? argv[0] : "git-help";
char *slash = strrchr(cmd, '/');
- const char *exec_path = NULL;
+ const char *cmd_path = NULL;
int done_alias = 0;
/*
@@ -413,10 +391,7 @@ int main(int argc, const char **argv)
*/
if (slash) {
*slash++ = 0;
- if (*cmd == '/')
- exec_path = cmd;
- else
- exec_path = xstrdup(make_absolute_path(cmd));
+ cmd_path = cmd;
cmd = slash;
}
@@ -451,16 +426,12 @@ int main(int argc, const char **argv)
cmd = argv[0];
/*
- * We execute external git command via execv_git_cmd(),
- * which looks at "--exec-path" option, GIT_EXEC_PATH
- * environment, and $(gitexecdir) in Makefile while built,
- * in this order. For scripted commands, we prepend
- * the value of the exec_path variable to the PATH.
+ * We use PATH to find git commands, but we prepend some higher
+ * precidence paths: the "--exec-path" option, the GIT_EXEC_PATH
+ * environment, and the $(gitexecdir) from the Makefile at build
+ * time.
*/
- if (exec_path)
- prepend_to_path(exec_path, strlen(exec_path));
- exec_path = git_exec_path();
- prepend_to_path(exec_path, strlen(exec_path));
+ setup_path(cmd_path);
while (1) {
/* See if it's an internal command */
--
gitgui.0.8.4.11176.gd9205-dirty
^ permalink raw reply related
* (unknown)
From: racin @ 2007-10-22 18:16 UTC (permalink / raw)
To: git
Hello,
I found the following on the development version of git.el: saving
non-git-managed files in Emacs threw an error.
It is due to a simple error in the call to condition-case in a
recently added function, git-update-save-file.
I attached the patch for your convenience.
Regards,
Matthieu Lemerre
PS: Please Cc me when you ackwowledge; I'm not subscribed to the list.
As a matter of fact, I found the bug only because I didn't find git.el
for my distribution (debian) so I got directly from the development
version on the website.
^ permalink raw reply
* [PATCH, take 2] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-22 17:29 UTC (permalink / raw)
To: Git Mailing List, Junio C Hamano, Shawn O. Pearce
Cc: David Kastrup, Jeff King, Sven Verdoolaege
In-Reply-To: <alpine.LFD.0.999.0710220932150.10525@woody.linux-foundation.org>
Ok, as some people notices, there were a few bugs in the previous patch. I
didn't free the hashes correctly (stupid) and the Makefile had "hash.o"
instead of "hash.h".
But more importantly, my "testing" had been totally broken, because I had
forgotten to actually move the rename limiting code to after the exact
rename phase, so when I tested the 100,000 file rename, almost none of the
new code triggered, so my performance testing was totally bogus.
When fixing that, I noticed that while my new exact rename detection was
essentially instantaneous, there were some O(n*m) effects in the generic
diff code from the extremely stupid way we handled the "was it a copy or a
rename" issue.
To fix that, I just made the "was the path used by a rename" be a counter
instead of a single "it was used"
With that in place, I could actually time the rename detection of 100,000
files in my big-rename test repository. This is what it looks like when
you rename a hundred thousand files:
[torvalds@woody big-rename]$ time ~/git/git show -C | wc -l
400006
real 0m2.675s
user 0m2.148s
sys 0m0.540s
(each renamed file is 4 lines: they looks like
diff --git a/really-big-dir/file-1-1-1-1-1 b/moved-big-dir/file-1-1-1-1-1
similarity index 100%
rename from really-big-dir/file-1-1-1-1-1
rename to moved-big-dir/file-1-1-1-1-1
and the extra six lines is from a one-liner commit message and all the
commit information and spacing).
So two seconds to do that exact rename detection.
Now, I can't really compare it to the "before" stage, because that is just
so horrible. The rename detection limit triggers, so you never even get
any renames, but if I were to move the limit check later (like I do in
this patch) without my other fixes, it would take hours. Trying to do ten
billion (100k x 100k) SHA1 and pathname compares simply isn't going to
work.
But I *can* compare it to the old code *with* the rename limiting, which
still wastes all the time on the whole "copy usage" crap. So here are the
numbers on that repo without the patch:
[torvalds@woody big-rename]$ time git show -C | wc -l
1400006
real 0m12.383s
user 0m12.365s
sys 0m0.160s
That's right: we used to take 12 seconds and not even do renames (now you
see fourteen lines per file moved: seven lines each for the delete and the
create of a one-liner file, and the same extra six lines of commit
information).
So it not only makes the rename detection possible in the first place, it
removes some stupid code that made it take a long time even when it
failed!
Now, I'd still be careful with this patch, and I'd really like people to
double-check all my logic, but I think it's worthy of some 'pu' love.
Linus
---
Makefile | 4 +-
diff.c | 24 +----
diffcore-rename.c | 275 ++++++++++++++++++++++++++++++----------------------
diffcore.h | 2 +-
hash.c | 110 +++++++++++++++++++++
hash.h | 43 ++++++++
6 files changed, 321 insertions(+), 137 deletions(-)
diff --git a/Makefile b/Makefile
index 8db4dbe..b1ca186 100644
--- a/Makefile
+++ b/Makefile
@@ -291,7 +291,7 @@ LIB_H = \
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
- mailmap.h remote.h
+ mailmap.h remote.h hash.h
DIFF_OBJS = \
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -301,7 +301,7 @@ DIFF_OBJS = \
LIB_OBJS = \
blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \
date.o diff-delta.o entry.o exec_cmd.o ident.o \
- interpolate.o \
+ interpolate.o hash.o \
lockfile.o \
patch-ids.o \
object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \
diff --git a/diff.c b/diff.c
index 6648e01..e892030 100644
--- a/diff.c
+++ b/diff.c
@@ -2586,9 +2586,9 @@ void diff_debug_filepair(const struct diff_filepair *p, int i)
{
diff_debug_filespec(p->one, i, "one");
diff_debug_filespec(p->two, i, "two");
- fprintf(stderr, "score %d, status %c stays %d broken %d\n",
+ fprintf(stderr, "score %d, status %c rename_used %d broken %d\n",
p->score, p->status ? p->status : '?',
- p->source_stays, p->broken_pair);
+ p->rename_used, p->broken_pair);
}
void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
@@ -2606,8 +2606,8 @@ void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
static void diff_resolve_rename_copy(void)
{
- int i, j;
- struct diff_filepair *p, *pp;
+ int i;
+ struct diff_filepair *p;
struct diff_queue_struct *q = &diff_queued_diff;
diff_debug_queue("resolve-rename-copy", q);
@@ -2629,27 +2629,15 @@ static void diff_resolve_rename_copy(void)
* either in-place edit or rename/copy edit.
*/
else if (DIFF_PAIR_RENAME(p)) {
- if (p->source_stays) {
- p->status = DIFF_STATUS_COPIED;
- continue;
- }
/* See if there is some other filepair that
* copies from the same source as us. If so
* we are a copy. Otherwise we are either a
* copy if the path stays, or a rename if it
* does not, but we already handled "stays" case.
*/
- for (j = i + 1; j < q->nr; j++) {
- pp = q->queue[j];
- if (strcmp(pp->one->path, p->one->path))
- continue; /* not us */
- if (!DIFF_PAIR_RENAME(pp))
- continue; /* not a rename/copy */
- /* pp is a rename/copy from the same source */
+ if (--p->one->rename_used > 0)
p->status = DIFF_STATUS_COPIED;
- break;
- }
- if (!p->status)
+ else
p->status = DIFF_STATUS_RENAMED;
}
else if (hashcmp(p->one->sha1, p->two->sha1) ||
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 2077a9b..cc105db 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -4,6 +4,7 @@
#include "cache.h"
#include "diff.h"
#include "diffcore.h"
+#include "hash.h"
/* Table of rename/copy destinations */
@@ -55,12 +56,10 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
static struct diff_rename_src {
struct diff_filespec *one;
unsigned short score; /* to remember the break score */
- unsigned src_path_left : 1;
} *rename_src;
static int rename_src_nr, rename_src_alloc;
static struct diff_rename_src *register_rename_src(struct diff_filespec *one,
- int src_path_left,
unsigned short score)
{
int first, last;
@@ -92,33 +91,9 @@ static struct diff_rename_src *register_rename_src(struct diff_filespec *one,
(rename_src_nr - first - 1) * sizeof(*rename_src));
rename_src[first].one = one;
rename_src[first].score = score;
- rename_src[first].src_path_left = src_path_left;
return &(rename_src[first]);
}
-static int is_exact_match(struct diff_filespec *src,
- struct diff_filespec *dst,
- int contents_too)
-{
- if (src->sha1_valid && dst->sha1_valid &&
- !hashcmp(src->sha1, dst->sha1))
- return 1;
- if (!contents_too)
- return 0;
- if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1))
- return 0;
- if (src->size != dst->size)
- return 0;
- if (src->sha1_valid && dst->sha1_valid)
- return !hashcmp(src->sha1, dst->sha1);
- if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
- return 0;
- if (src->size == dst->size &&
- !memcmp(src->data, dst->data, src->size))
- return 1;
- return 0;
-}
-
static int basename_same(struct diff_filespec *src, struct diff_filespec *dst)
{
int src_len = strlen(src->path), dst_len = strlen(dst->path);
@@ -216,6 +191,7 @@ static void record_rename_pair(int dst_index, int src_index, int score)
die("internal error: dst already matched.");
src = rename_src[src_index].one;
+ src->rename_used++;
one = alloc_filespec(src->path);
fill_filespec(one, src->sha1, src->mode);
@@ -229,7 +205,6 @@ static void record_rename_pair(int dst_index, int src_index, int score)
dp->score = rename_src[src_index].score;
else
dp->score = score;
- dp->source_stays = rename_src[src_index].src_path_left;
rename_dst[dst_index].pair = dp;
}
@@ -247,19 +222,127 @@ static int score_compare(const void *a_, const void *b_)
return b->score - a->score;
}
-static int compute_stays(struct diff_queue_struct *q,
- struct diff_filespec *one)
+struct file_similarity {
+ int src_dst, index;
+ struct diff_filespec *filespec;
+ struct file_similarity *next;
+};
+
+static int find_identical_files(struct file_similarity *src,
+ struct file_similarity *dst)
{
- int i;
- for (i = 0; i < q->nr; i++) {
- struct diff_filepair *p = q->queue[i];
- if (strcmp(one->path, p->two->path))
- continue;
- if (DIFF_PAIR_RENAME(p)) {
- return 0; /* something else is renamed into this */
+ int renames = 0;
+ do {
+ struct diff_filespec *one = src->filespec;
+ struct file_similarity *p, *best;
+ int i = 100;
+
+ best = NULL;
+ for (p = dst; p; p = p->next) {
+ struct diff_filespec *two = p->filespec;
+
+ /* Already picked as a destination? */
+ if (!p->src_dst)
+ continue;
+ /* False hash collission? */
+ if (hashcmp(one->sha1, two->sha1))
+ continue;
+ best = p;
+ if (basename_same(one, two))
+ break;
+
+ /* Too many identical alternatives? Pick one */
+ if (!--i)
+ break;
}
+ if (best) {
+ best->src_dst = 0;
+ record_rename_pair(best->index, src->index, MAX_SCORE);
+ renames++;
+ }
+ } while ((src = src->next) != NULL);
+ return renames;
+}
+
+/*
+ * Note: the rest of the rename logic depends on this
+ * phase also populating all the filespecs for any
+ * entry that isn't matched up with an exact rename.
+ */
+static void free_similarity_list(struct file_similarity *p)
+{
+ while (p) {
+ struct file_similarity *entry = p;
+ p = p->next;
+
+ /* Stupid special case, see note above! */
+ diff_populate_filespec(entry->filespec, 0);
+ free(entry);
+ }
+}
+
+static int find_same_files(void *ptr)
+{
+ int ret;
+ struct file_similarity *p = ptr;
+ struct file_similarity *src = NULL, *dst = NULL;
+
+ /* Split the hash list up into sources and destinations */
+ do {
+ struct file_similarity *entry = p;
+ p = p->next;
+ if (entry->src_dst < 0) {
+ entry->next = src;
+ src = entry;
+ } else {
+ entry->next = dst;
+ dst = entry;
+ }
+ } while (p);
+
+ /*
+ * If we have both sources *and* destinations, see if
+ * we can match them up
+ */
+ ret = (src && dst) ? find_identical_files(src, dst) : 0;
+
+ /* Free the hashes and return the number of renames found */
+ free_similarity_list(src);
+ free_similarity_list(dst);
+ return ret;
+}
+
+static unsigned int hash_filespec(struct diff_filespec *filespec)
+{
+ unsigned int hash;
+ if (!filespec->sha1_valid) {
+ if (diff_populate_filespec(filespec, 0))
+ return 0;
+ hash_sha1_file(filespec->data, filespec->size, "blob", filespec->sha1);
+ }
+ memcpy(&hash, filespec->sha1, sizeof(hash));
+ return hash;
+}
+
+static void insert_file_table(struct hash_table *table, int src_dst, int index, struct diff_filespec *filespec)
+{
+ void **pos;
+ unsigned int hash;
+ struct file_similarity *entry = xmalloc(sizeof(*entry));
+
+ entry->src_dst = src_dst;
+ entry->index = index;
+ entry->filespec = filespec;
+ entry->next = NULL;
+
+ hash = hash_filespec(filespec);
+ pos = insert_hash(hash, entry, table);
+
+ /* We already had an entry there? */
+ if (pos) {
+ entry->next = *pos;
+ *pos = entry;
}
- return 1;
}
/*
@@ -268,50 +351,26 @@ static int compute_stays(struct diff_queue_struct *q,
* The first round matches up the up-to-date entries,
* and then during the second round we try to match
* cache-dirty entries as well.
- *
- * Note: the rest of the rename logic depends on this
- * phase also populating all the filespecs for any
- * entry that isn't matched up with an exact rename,
- * see "is_exact_match()".
*/
static int find_exact_renames(void)
{
- int rename_count = 0;
- int contents_too;
-
- for (contents_too = 0; contents_too < 2; contents_too++) {
- int i;
-
- for (i = 0; i < rename_dst_nr; i++) {
- struct diff_filespec *two = rename_dst[i].two;
- int j;
-
- if (rename_dst[i].pair)
- continue; /* dealt with an earlier round */
- for (j = 0; j < rename_src_nr; j++) {
- int k;
- struct diff_filespec *one = rename_src[j].one;
- if (!is_exact_match(one, two, contents_too))
- continue;
-
- /* see if there is a basename match, too */
- for (k = j; k < rename_src_nr; k++) {
- one = rename_src[k].one;
- if (basename_same(one, two) &&
- is_exact_match(one, two,
- contents_too)) {
- j = k;
- break;
- }
- }
-
- record_rename_pair(i, j, (int)MAX_SCORE);
- rename_count++;
- break; /* we are done with this entry */
- }
- }
- }
- return rename_count;
+ int i;
+ struct hash_table file_table;
+
+ init_hash(&file_table);
+ for (i = 0; i < rename_src_nr; i++)
+ insert_file_table(&file_table, -1, i, rename_src[i].one);
+
+ for (i = 0; i < rename_dst_nr; i++)
+ insert_file_table(&file_table, 1, i, rename_dst[i].two);
+
+ /* Find the renames */
+ i = for_each_hash(&file_table, find_same_files);
+
+ /* .. and free the hash data structure */
+ free_hash(&file_table);
+
+ return i;
}
void diffcore_rename(struct diff_options *options)
@@ -340,20 +399,36 @@ void diffcore_rename(struct diff_options *options)
locate_rename_dst(p->two, 1);
}
else if (!DIFF_FILE_VALID(p->two)) {
- /* If the source is a broken "delete", and
+ /*
+ * If the source is a broken "delete", and
* they did not really want to get broken,
* that means the source actually stays.
+ * So we increment the "rename_used" score
+ * by one, to indicate ourselves as a user
*/
- int stays = (p->broken_pair && !p->score);
- register_rename_src(p->one, stays, p->score);
+ if (p->broken_pair && !p->score)
+ p->one->rename_used++;
+ register_rename_src(p->one, p->score);
+ }
+ else if (detect_rename == DIFF_DETECT_COPY) {
+ /*
+ * Increment the "rename_used" score by
+ * one, to indicate ourselves as a user.
+ */
+ p->one->rename_used++;
+ register_rename_src(p->one, p->score);
}
- else if (detect_rename == DIFF_DETECT_COPY)
- register_rename_src(p->one, 1, p->score);
}
if (rename_dst_nr == 0 || rename_src_nr == 0)
goto cleanup; /* nothing to do */
/*
+ * We really want to cull the candidates list early
+ * with cheap tests in order to avoid doing deltas.
+ */
+ rename_count = find_exact_renames();
+
+ /*
* This basically does a test for the rename matrix not
* growing larger than a "rename_limit" square matrix, ie:
*
@@ -369,12 +444,6 @@ void diffcore_rename(struct diff_options *options)
if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit)
goto cleanup;
- /*
- * We really want to cull the candidates list early
- * with cheap tests in order to avoid doing deltas.
- */
- rename_count = find_exact_renames();
-
/* Have we run out the created file pool? If so we can avoid
* doing the delta matrix altogether.
*/
@@ -474,16 +543,7 @@ void diffcore_rename(struct diff_options *options)
pair_to_free = p;
}
else {
- for (j = 0; j < rename_dst_nr; j++) {
- if (!rename_dst[j].pair)
- continue;
- if (strcmp(rename_dst[j].pair->
- one->path,
- p->one->path))
- continue;
- break;
- }
- if (j < rename_dst_nr)
+ if (p->one->rename_used)
/* this path remains */
pair_to_free = p;
}
@@ -509,23 +569,6 @@ void diffcore_rename(struct diff_options *options)
*q = outq;
diff_debug_queue("done collapsing", q);
- /* We need to see which rename source really stays here;
- * earlier we only checked if the path is left in the result,
- * but even if a path remains in the result, if that is coming
- * from copying something else on top of it, then the original
- * source is lost and does not stay.
- */
- for (i = 0; i < q->nr; i++) {
- struct diff_filepair *p = q->queue[i];
- if (DIFF_PAIR_RENAME(p) && p->source_stays) {
- /* If one appears as the target of a rename-copy,
- * then mark p->source_stays = 0; otherwise
- * leave it as is.
- */
- p->source_stays = compute_stays(q, p->one);
- }
- }
-
for (i = 0; i < rename_dst_nr; i++) {
diff_free_filespec_data(rename_dst[i].two);
free(rename_dst[i].two);
diff --git a/diffcore.h b/diffcore.h
index eb618b1..ceda932 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -30,6 +30,7 @@ struct diff_filespec {
const char *funcname_pattern_ident;
unsigned long size;
int xfrm_flags; /* for use by the xfrm */
+ int rename_used; /* Count of rename users */
unsigned short mode; /* file mode */
unsigned sha1_valid : 1; /* if true, use sha1 and trust mode;
* if false, use the name and read from
@@ -56,7 +57,6 @@ struct diff_filepair {
struct diff_filespec *two;
unsigned short int score;
char status; /* M C R N D U (see Documentation/diff-format.txt) */
- unsigned source_stays : 1; /* all of R/C are copies */
unsigned broken_pair : 1;
unsigned renamed_pair : 1;
unsigned is_unmerged : 1;
diff --git a/hash.c b/hash.c
new file mode 100644
index 0000000..7b492d4
--- /dev/null
+++ b/hash.c
@@ -0,0 +1,110 @@
+/*
+ * Some generic hashing helpers.
+ */
+#include "cache.h"
+#include "hash.h"
+
+/*
+ * Look up a hash entry in the hash table. Return the pointer to
+ * the existing entry, or the empty slot if none existed. The caller
+ * can then look at the (*ptr) to see whether it existed or not.
+ */
+static struct hash_table_entry *lookup_hash_entry(unsigned int hash, struct hash_table *table)
+{
+ unsigned int size = table->size, nr = hash % size;
+ struct hash_table_entry *array = table->array;
+
+ while (array[nr].ptr) {
+ if (array[nr].hash == hash)
+ break;
+ nr++;
+ if (nr >= size)
+ nr = 0;
+ }
+ return array + nr;
+}
+
+
+/*
+ * Insert a new hash entry pointer into the table.
+ *
+ * If that hash entry already existed, return the pointer to
+ * the existing entry (and the caller can create a list of the
+ * pointers or do anything else). If it didn't exist, return
+ * NULL (and the caller knows the pointer has been inserted).
+ */
+static void **insert_hash_entry(unsigned int hash, void *ptr, struct hash_table *table)
+{
+ struct hash_table_entry *entry = lookup_hash_entry(hash, table);
+
+ if (!entry->ptr) {
+ entry->ptr = ptr;
+ entry->hash = hash;
+ table->nr++;
+ return NULL;
+ }
+ return &entry->ptr;
+}
+
+static void grow_hash_table(struct hash_table *table)
+{
+ unsigned int i;
+ unsigned int old_size = table->size, new_size;
+ struct hash_table_entry *old_array = table->array, *new_array;
+
+ new_size = alloc_nr(old_size);
+ new_array = xcalloc(sizeof(struct hash_table_entry), new_size);
+ table->size = new_size;
+ table->array = new_array;
+ table->nr = 0;
+ for (i = 0; i < old_size; i++) {
+ unsigned int hash = old_array[i].hash;
+ void *ptr = old_array[i].ptr;
+ if (ptr)
+ insert_hash_entry(hash, ptr, table);
+ }
+ free(old_array);
+}
+
+void *lookup_hash(unsigned int hash, struct hash_table *table)
+{
+ if (!table->array)
+ return NULL;
+ return &lookup_hash_entry(hash, table)->ptr;
+}
+
+void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table)
+{
+ unsigned int nr = table->nr;
+ if (nr >= table->size/2)
+ grow_hash_table(table);
+ return insert_hash_entry(hash, ptr, table);
+}
+
+int for_each_hash(struct hash_table *table, int (*fn)(void *))
+{
+ int sum = 0;
+ unsigned int i;
+ unsigned int size = table->size;
+ struct hash_table_entry *array = table->array;
+
+ for (i = 0; i < size; i++) {
+ void *ptr = array->ptr;
+ array++;
+ if (ptr) {
+ int val = fn(ptr);
+ if (val < 0)
+ return val;
+ sum += val;
+ }
+ }
+ return sum;
+}
+
+void free_hash(struct hash_table *table)
+{
+ free(table->array);
+ table->array = NULL;
+ table->size = 0;
+ table->nr = 0;
+}
diff --git a/hash.h b/hash.h
new file mode 100644
index 0000000..5056c9a
--- /dev/null
+++ b/hash.h
@@ -0,0 +1,43 @@
+#ifndef HASH_H
+#define HASH_H
+
+/*
+ * These are some simple generic hash table helper functions.
+ * Not necessarily suitable for all users, but good for things
+ * where you want to just keep track of a list of things, and
+ * have a good hash to use on them.
+ *
+ * It keeps the hash table at roughly 50-75% free, so the memory
+ * cost of the hash table itself is roughly
+ *
+ * 3 * 2*sizeof(void *) * nr_of_objects
+ *
+ * bytes.
+ *
+ * FIXME: on 64-bit architectures, we waste memory. It would be
+ * good to have just 32-bit pointers, requiring a special allocator
+ * for hashed entries or something.
+ */
+struct hash_table_entry {
+ unsigned int hash;
+ void *ptr;
+};
+
+struct hash_table {
+ unsigned int size, nr;
+ struct hash_table_entry *array;
+};
+
+extern void *lookup_hash(unsigned int hash, struct hash_table *table);
+extern void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table);
+extern int for_each_hash(struct hash_table *table, int (*fn)(void *));
+extern void free_hash(struct hash_table *table);
+
+static inline void init_hash(struct hash_table *table)
+{
+ table->size = 0;
+ table->nr = 0;
+ table->array = NULL;
+}
+
+#endif
^ permalink raw reply related
* Re: [PATCH] use only the PATH for exec'ing git commands
From: Johannes Schindelin @ 2007-10-22 17:44 UTC (permalink / raw)
To: Scott R Parish; +Cc: git
In-Reply-To: <20071022170148.GB29642@srparish.net>
Hi,
On Mon, 22 Oct 2007, Scott R Parish wrote:
> 3 files changed, 61 insertions(+), 105 deletions(-)
Nice.
Ciao,
Dscho
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Steffen Prohaska @ 2007-10-22 15:42 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Johannes Schindelin, Jakub Narebski, Federico Mena Quintero, git
In-Reply-To: <471CBEB1.2030008@op5.se>
On Oct 22, 2007, at 5:16 PM, Andreas Ericsson wrote:
> Johannes Schindelin wrote:
>> Hi,
>> On Mon, 22 Oct 2007, Andreas Ericsson wrote:
>>> Johannes Schindelin wrote:
>>>
>>>> On Mon, 22 Oct 2007, Andreas Ericsson wrote:
>>>>
>>>>> If I were to suggest any improvements, it'd be to change the
>>>>> semantics of git-pull to always update the local branches set
>>>>> up to be merged with the remote tracking branches when they,
>>>>> prior to fetching, pointed to the same commit, such that when
>>>>>
>>>>> $ git show-ref master
>>>>> d4027a816dd0b416dc8c7b37e2c260e6905f11b6 refs/heads/master
>>>>> d4027a816dd0b416dc8c7b37e2c260e6905f11b6 refs/remotes/origin/
>>>>> master
>>>>>
>>>>> refs/heads/master gets set to refs/remotes/origin/master post-
>>>>> fetch.
>>>> In general, this should fail. Because you are expected to have
>>>> local changes in the local branches.
>>>
>>> BS argument.
>> Aha. So you want to make sure that the local branches are no
>> longer "purely" local. And you want to stop updating them when
>> unpushed changes are in the local branches.
>
> To me, it's more along the lines of "let git help me not make the
> mistake of hacking on a six-week old codebase when I've explicitly
> asked it to merge these and those remote tracking branches into
> these and those local branches". Not updating those branches when
> there *are* changes on them is something users can understand and
> will probably also appreciate, but the reason for not allowing even
> fast-forwards escape me.
Here's also an interesting asymmetry. By default, git push
updates all remote branches matching a local branch. But git
pull "updates" only the current local branch to the state of
the remote head (by updating all local copies of the remote
branches, but merging only a single of these heads).
Maybe this asymmetry adds to the confusion. I see arguments
for both behaviours:
1) In both cases, update only the branch you're on
or
2) in both cases update all matching branches.
(btw, if I do not intend to merge at all, you can always use
"git fetch".)
Steffen
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Robin Rosenberg @ 2007-10-22 17:48 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Wincent Colaiuta, Andreas Ericsson, Jakub Narebski,
Steffen Prohaska, Federico Mena Quintero, git
In-Reply-To: <Pine.LNX.4.64.0710221428390.25221@racer.site>
My list
61 show
35 gitk
31 diff
23 fetch
12 reset
12 blame
11 clone
11 checkout
10 remote
10 rebase
9 status
5 commit
4 branch
3 clean
2 revert
2 merge
2 ls-remote
2 gui
-- robin
^ permalink raw reply
* Re: [PATCH] Dissociating a repository from its alternates
From: Michael Hendricks @ 2007-10-22 18:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Schindelin, git
In-Reply-To: <7v8xex50aa.fsf@assigned-by-dhcp.cox.net>
On Fri, Feb 16, 2007 at 12:13:01PM -0800, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > On Wed, 14 Feb 2007, Junio C Hamano wrote:
> >
> >> People often start out with "clone -l -s" (or --reference) and
> >> later wish to dissociate the repository from its alternates.
> >
> > Why not make a really dumb script which just _copies_ (or maybe
> > optionally hard link) the objects from the alternate repo, and then kills
> > the alternatives file? That should be easier. You always can repack after
> > that.
>
> I think that is much safer.
Was such a script ever incorporated into Git?
--
Michael
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Daniel Barkalow @ 2007-10-22 18:06 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Andreas Ericsson, Jakub Narebski, Steffen Prohaska,
Federico Mena Quintero, git
In-Reply-To: <Pine.LNX.4.64.0710221445170.25221@racer.site>
On Mon, 22 Oct 2007, Johannes Schindelin wrote:
> Hi,
>
> On Mon, 22 Oct 2007, Andreas Ericsson wrote:
>
> > If I were to suggest any improvements, it'd be to change the semantics of
> > git-pull to always update the local branches set up to be merged with the
> > remote tracking branches when they, prior to fetching, pointed to the same
> > commit, such that when
> >
> > $ git show-ref master
> > d4027a816dd0b416dc8c7b37e2c260e6905f11b6 refs/heads/master
> > d4027a816dd0b416dc8c7b37e2c260e6905f11b6 refs/remotes/origin/master
> >
> > refs/heads/master gets set to refs/remotes/origin/master post-fetch.
>
> In general, this should fail. Because you are expected to have local
> changes in the local branches. What you describe suggests that you should
> not use the branch name "master" at all, but "origin/master".
If you push your changes to the origin soon after making them, you'll only
have local changes if somebody else changed something while you were
working on a change. You're expected to create local changes in the local
branches, but you shouldn't generally sit on them forever, and when you've
pushed them, you no longer have any difference in content between local
and remote.
If the project has multiple branches in the central repository, and you
make changes for each of them at different times, but only one each day,
the normal case will be to have local changes sitting in at most one of
the branches, and, in particular, no local changes left in any branch
other than HEAD.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: [PATCH] use only the PATH for exec'ing git commands
From: Alex Riesen @ 2007-10-22 19:01 UTC (permalink / raw)
To: Scott R Parish; +Cc: git
In-Reply-To: <20071022170148.GB29642@srparish.net>
Scott R Parish, Mon, Oct 22, 2007 19:01:48 +0200:
> +static void add_path(struct strbuf *out, const char *path)
> +{
> + if (path && strlen(path)) {
> + if (is_absolute_path(path))
> + strbuf_addstr(out, path);
> + else
> + strbuf_addstr(out, make_absolute_path(path));
> +
> + strbuf_addch(out, ':');
Shouldn't it break MingW32 native port?
> + }
> +}
> +
> +void setup_path(const char *cmd_path)
> +{
> + const char *old_path = getenv("PATH");
> + struct strbuf new_path;
> +
> + strbuf_init(&new_path, 0);
> +
> + add_path(&new_path, argv_exec_path);
> + add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
> + add_path(&new_path, builtin_exec_path);
> + add_path(&new_path, cmd_path);
> +
trailing space
> + if (old_path)
> + strbuf_addstr(&new_path, old_path);
> + else
> + strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
the default PATH is platform-dependent. Git is multi-platform.
You should consider putting the path list somewhere in Makefile,
config.mak or configure.
> +
> + setenv("PATH", new_path.buf, 1);
^ permalink raw reply
* Re: [PATCH] Dissociating a repository from its alternates
From: Johannes Schindelin @ 2007-10-22 19:05 UTC (permalink / raw)
To: Michael Hendricks; +Cc: Junio C Hamano, git
In-Reply-To: <20071022180424.GA17429@ginosko.local>
Hi,
On Mon, 22 Oct 2007, Michael Hendricks wrote:
> On Fri, Feb 16, 2007 at 12:13:01PM -0800, Junio C Hamano wrote:
> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> >
> > > On Wed, 14 Feb 2007, Junio C Hamano wrote:
> > >
> > >> People often start out with "clone -l -s" (or --reference) and
> > >> later wish to dissociate the repository from its alternates.
> > >
> > > Why not make a really dumb script which just _copies_ (or maybe
> > > optionally hard link) the objects from the alternate repo, and then kills
> > > the alternatives file? That should be easier. You always can repack after
> > > that.
> >
> > I think that is much safer.
>
> Was such a script ever incorporated into Git?
Not that I know of, but "git repack -a && rm .git/objects/info/alternates"
should do what you want. You can even make a script of it, add some
documentation and a test case, and earn git fame by posting a patch ;-)
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] use only the PATH for exec'ing git commands
From: Eric Merritt @ 2007-10-22 19:25 UTC (permalink / raw)
To: Alex Riesen; +Cc: Scott R Parish, git
In-Reply-To: <20071022190102.GA23714@steel.home>
> the default PATH is platform-dependent. Git is multi-platform.
> You should consider putting the path list somewhere in Makefile,
> config.mak or configure.
This static configuration that you describe is one of the things this
patch is designed to strip out. Compile time configuration breaks down
completly if you don't deploy to the path defined when the system was
compiled. Thats a problem.
^ permalink raw reply
* Re: [PATCH, take 2] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-22 19:31 UTC (permalink / raw)
To: Git Mailing List, Junio C Hamano, Shawn O. Pearce
Cc: David Kastrup, Jeff King, Sven Verdoolaege
In-Reply-To: <alpine.LFD.0.999.0710221009580.10525@woody.linux-foundation.org>
On Mon, 22 Oct 2007, Linus Torvalds wrote:
>
> Ok, as some people notices, there were a few bugs in the previous patch. I
> didn't free the hashes correctly (stupid) and the Makefile had "hash.o"
> instead of "hash.h".
Ok, there were still more bugs, and before you get too involved with this
last patch (not that I've seen any comments yet), apply this appended
patch to actually fix things a bit more first!
Yes, I'm a moron. I hadn't even bothered to run the test-suite on it, and
that showed several silly problems.
One of the problems was that since the rename detection copied the
diffspecs around, the "rename_used" count couldn't work right, because
things got copied around and the count stayed with one diffspec, but not
the other..
In the kernel, we have a rule that says that any data structure that isn't
ref-counted is basically a bug, and that was true here too. Instead of
copying and splitting the diffspecs, just refcount them and keep track of
how many users there are.
While the above bug was a somewhat subtle issue from me trying to be
clever in avoiding the O(n*m) file copy/rename reuse issue, there were a
few issues that were me just being totally braindead: the exact rename
detection had lost the code that took file modes into account, so it would
generate "renames" from regular files to symlinks, that the generic diff
core layer would just split up again.
And even more stupidly, I had matched up the src/dst things when finding
the rename, which just complicated things (added a totally unnecessary
need to keep track of a destination being used more than once) and also
broke the basename matching comparison. Duh.
So here's an incremental patch on top of the previous failed try. And if
somebody is confused (and that might be me) and cannot get things to
apply, just holler and I'll send the whole thing again. I might even try
to clean up the series a bit and do it in stages.
This patch shouldn't change any performance behaviour (well, it might
speed things up a bit to not allocate those diffspec structures, but it's
unlikely that is even measurable). It just fixes stuff.
I'm sure there's more to come..
Linus
---
diff.c | 17 ++++++++++++-----
diffcore-rename.c | 40 ++++++++++++++++++++++------------------
diffcore.h | 2 ++
3 files changed, 36 insertions(+), 23 deletions(-)
diff --git a/diff.c b/diff.c
index e892030..2e74cb3 100644
--- a/diff.c
+++ b/diff.c
@@ -1440,9 +1440,18 @@ struct diff_filespec *alloc_filespec(const char *path)
memset(spec, 0, sizeof(*spec));
spec->path = (char *)(spec + 1);
memcpy(spec->path, path, namelen+1);
+ spec->count = 1;
return spec;
}
+void free_filespec(struct diff_filespec *spec)
+{
+ if (!--spec->count) {
+ diff_free_filespec_data(spec);
+ free(spec);
+ }
+}
+
void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
unsigned short mode)
{
@@ -2431,10 +2440,8 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
void diff_free_filepair(struct diff_filepair *p)
{
- diff_free_filespec_data(p->one);
- diff_free_filespec_data(p->two);
- free(p->one);
- free(p->two);
+ free_filespec(p->one);
+ free_filespec(p->two);
free(p);
}
@@ -2588,7 +2595,7 @@ void diff_debug_filepair(const struct diff_filepair *p, int i)
diff_debug_filespec(p->two, i, "two");
fprintf(stderr, "score %d, status %c rename_used %d broken %d\n",
p->score, p->status ? p->status : '?',
- p->rename_used, p->broken_pair);
+ p->one->rename_used, p->broken_pair);
}
void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
diff --git a/diffcore-rename.c b/diffcore-rename.c
index cc105db..3946932 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -184,7 +184,7 @@ static int estimate_similarity(struct diff_filespec *src,
static void record_rename_pair(int dst_index, int src_index, int score)
{
- struct diff_filespec *one, *two, *src, *dst;
+ struct diff_filespec *src, *dst;
struct diff_filepair *dp;
if (rename_dst[dst_index].pair)
@@ -192,14 +192,12 @@ static void record_rename_pair(int dst_index, int src_index, int score)
src = rename_src[src_index].one;
src->rename_used++;
- one = alloc_filespec(src->path);
- fill_filespec(one, src->sha1, src->mode);
+ src->count++;
dst = rename_dst[dst_index].two;
- two = alloc_filespec(dst->path);
- fill_filespec(two, dst->sha1, dst->mode);
+ dst->count++;
- dp = diff_queue(NULL, one, two);
+ dp = diff_queue(NULL, src, dst);
dp->renamed_pair = 1;
if (!strcmp(src->path, dst->path))
dp->score = rename_src[src_index].score;
@@ -232,21 +230,30 @@ static int find_identical_files(struct file_similarity *src,
struct file_similarity *dst)
{
int renames = 0;
+
+ /*
+ * Walk over all the destinations ...
+ */
do {
- struct diff_filespec *one = src->filespec;
+ struct diff_filespec *one = dst->filespec;
struct file_similarity *p, *best;
int i = 100;
+ /*
+ * .. to find the best source match
+ */
best = NULL;
- for (p = dst; p; p = p->next) {
+ for (p = src; p; p = p->next) {
struct diff_filespec *two = p->filespec;
- /* Already picked as a destination? */
- if (!p->src_dst)
- continue;
/* False hash collission? */
if (hashcmp(one->sha1, two->sha1))
continue;
+ /* Non-regular files? If so, the modes must match! */
+ if (!S_ISREG(one->mode) || !S_ISREG(two->mode)) {
+ if (one->mode != two->mode)
+ continue;
+ }
best = p;
if (basename_same(one, two))
break;
@@ -256,11 +263,10 @@ static int find_identical_files(struct file_similarity *src,
break;
}
if (best) {
- best->src_dst = 0;
- record_rename_pair(best->index, src->index, MAX_SCORE);
+ record_rename_pair(dst->index, best->index, MAX_SCORE);
renames++;
}
- } while ((src = src->next) != NULL);
+ } while ((dst = dst->next) != NULL);
return renames;
}
@@ -569,10 +575,8 @@ void diffcore_rename(struct diff_options *options)
*q = outq;
diff_debug_queue("done collapsing", q);
- for (i = 0; i < rename_dst_nr; i++) {
- diff_free_filespec_data(rename_dst[i].two);
- free(rename_dst[i].two);
- }
+ for (i = 0; i < rename_dst_nr; i++)
+ free_filespec(rename_dst[i].two);
free(rename_dst);
rename_dst = NULL;
diff --git a/diffcore.h b/diffcore.h
index ceda932..cc96c20 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -29,6 +29,7 @@ struct diff_filespec {
void *cnt_data;
const char *funcname_pattern_ident;
unsigned long size;
+ int count; /* Reference count */
int xfrm_flags; /* for use by the xfrm */
int rename_used; /* Count of rename users */
unsigned short mode; /* file mode */
@@ -44,6 +45,7 @@ struct diff_filespec {
};
extern struct diff_filespec *alloc_filespec(const char *);
+extern void free_filespec(struct diff_filespec *);
extern void fill_filespec(struct diff_filespec *, const unsigned char *,
unsigned short);
^ permalink raw reply related
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Federico Mena Quintero @ 2007-10-22 19:36 UTC (permalink / raw)
To: Andreas Ericsson; +Cc: Johannes Schindelin, git
In-Reply-To: <471CBEB1.2030008@op5.se>
On Mon, 2007-10-22 at 17:16 +0200, Andreas Ericsson wrote:
> To me, it's more along the lines of "let git help me not make the
> mistake of hacking on a six-week old codebase when I've explicitly asked
> it to merge these and those remote tracking branches into these and
> those local branches". Not updating those branches when there *are*
> changes on them is something users can understand and will probably also
> appreciate, but the reason for not allowing even fast-forwards escape me.
I'd love this behavior, FWIW.
The "branches should not track their origin by default" seems suited
only to Linux kernel maintainers who frequently pull from many different
people, not to "random hacker who wants to keep track of a project he
doesn't maintain" :)
Federico
^ permalink raw reply
* Re: [PATCH, take 2] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-22 19:44 UTC (permalink / raw)
To: Git Mailing List, Junio C Hamano, Shawn O. Pearce
Cc: David Kastrup, Jeff King, Sven Verdoolaege
In-Reply-To: <alpine.LFD.0.999.0710221207300.30120@woody.linux-foundation.org>
On Mon, 22 Oct 2007, Linus Torvalds wrote:
>
> I'm sure there's more to come..
One more detail.. The updated comment explains the issue: if we broke a
file apart, and rename detection joined it back together, the result is
neither a rename nor a copy, it's a regular modification (and all
remaining renames will be copies of the original, so don't bother
decrementing the "rename_used" count).
Linus
---
diff.c | 18 ++++++++++++------
1 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/diff.c b/diff.c
index 2e74cb3..e839f59 100644
--- a/diff.c
+++ b/diff.c
@@ -2636,13 +2636,19 @@ static void diff_resolve_rename_copy(void)
* either in-place edit or rename/copy edit.
*/
else if (DIFF_PAIR_RENAME(p)) {
- /* See if there is some other filepair that
- * copies from the same source as us. If so
- * we are a copy. Otherwise we are either a
- * copy if the path stays, or a rename if it
- * does not, but we already handled "stays" case.
+ /*
+ * A rename might have re-connected a broken
+ * pair up, causing the pathnames to be the
+ * same again. If so, that's not a rename at
+ * all, just a modification..
+ *
+ * Otherwise, see if this source was used for
+ * multiple renames, in which case we decrement
+ * the count, and call it a copy.
*/
- if (--p->one->rename_used > 0)
+ if (!strcmp(p->one->path, p->two->path))
+ p->status = DIFF_STATUS_MODIFIED;
+ else if (--p->one->rename_used > 0)
p->status = DIFF_STATUS_COPIED;
else
p->status = DIFF_STATUS_RENAMED;
^ permalink raw reply related
* Re: odd behavior with concurrent fetch/checkout
From: J. Bruce Fields @ 2007-10-22 19:46 UTC (permalink / raw)
To: git
In-Reply-To: <20071022165125.GG583@fieldses.org>
On Mon, Oct 22, 2007 at 12:51:25PM -0400, J. Bruce Fields wrote:
> Just now I checked out a topic branch in my working repo:
>
> git checkout server-xprt-switch
>
> and while waiting for it to complete (I just started work and caches
> were all cold), I ran a
>
> git fetch origin
>
> in another window to update from Linus. The git fetch gave a warning:
>
> remote: Generating pack...
> remote: Counting objects: 7550
> remote: Done counting 12885 objects.
> remote: Result has 8400 objects.
> remote: Deltifying 8400 objects...
> remote: 100% (8400/8400) done
> Indexing 8400 objects...
> remote: Total 8400 (delta 7257), reused 5696 (delta 4586)
> 100% (8400/8400) done
> Resolving 7257 deltas...
> 100% (7257/7257) done
> * refs/remotes/origin/master: fast forward to branch 'master' of
> * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
> old..new: d85714d..55b70a0
> Cannot fetch into the current branch.
By the way, I should have said--this is with git version
1.5.3.4.208.gc990.
--b.
>
> Why the warning? Also, afterwards I was left with server-xprt-switch
> pointing to the tip of the branch I'd just switched from (another
> miscellaneous topic branch). The working directory was in some
> completely different state--thanks to a quick reset --hard I don't know
> what it was. Also, in the reflog for the checked-out branch:
>
> commit bac1e7977eb4781e62cee7f1c7c3d13a9e5d8d74
> Reflog: server-xprt-switch@{0} (J. Bruce Fields <bfields@citi.umich.edu>)
> Reflog message: fetch origin: Undoing incorrectly fetched HEAD.
> Author: J. Bruce Fields <bfields@citi.umich.edu>
> Date: Mon Oct 22 12:32:37 2007 -0400
> ...
>
> Why was a fetch into the remote fooling with HEAD or anything under
> refs/heads/?
>
> --b.
> -
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH] use only the PATH for exec'ing git commands
From: Scott R Parish @ 2007-10-22 19:59 UTC (permalink / raw)
To: Alex Riesen, git
> Alex Reisen, Mon, Oct 22, 2007 12:01:
> > + strbuf_addch(out, ':');
>
> Shouldn't it break MingW32 native port?
>
<snip>
> > + if (old_path)
> > + strbuf_addstr(&new_path, old_path);
> > + else
> > + strbuf_addstr(&new_path,
"/usr/local/bin:/usr/bin:/bin");
>
> the default PATH is platform-dependent. Git is multi-platform.
> You should consider putting the path list somewhere in Makefile,
> config.mak or configure.
>
The original code was already doing both of these things (see git.c's
prepend_to_path())
sRp
^ permalink raw reply
* Re: [PATCH] use only the PATH for exec'ing git commands
From: Scott R Parish @ 2007-10-22 19:59 UTC (permalink / raw)
To: Alex Riesen, git
> Alex Reisen, Mon, Oct 22, 2007 12:01:
> > + strbuf_addch(out, ':');
>
> Shouldn't it break MingW32 native port?
>
<snip>
> > + if (old_path)
> > + strbuf_addstr(&new_path, old_path);
> > + else
> > + strbuf_addstr(&new_path,
"/usr/local/bin:/usr/bin:/bin");
>
> the default PATH is platform-dependent. Git is multi-platform.
> You should consider putting the path list somewhere in Makefile,
> config.mak or configure.
>
The original code was already doing both of these things (see git.c's
prepend_to_path())
sRp
^ permalink raw reply
* [PATCH] More updates and corrections to the russian translation of git-gui
From: Alex Riesen @ 2007-10-22 20:28 UTC (permalink / raw)
To: git; +Cc: Shawn O. Pearce, Kirill
In particular many screw-ups after po regeneration were fixed.
Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
po/ru.po | 362 ++++++++++++++++++++++----------------------------------------
1 files changed, 127 insertions(+), 235 deletions(-)
diff --git a/po/ru.po b/po/ru.po
index ed5b67a..b8e9447 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-10-10 04:04-0400\n"
-"PO-Revision-Date: 2007-10-20 14:29-0500\n"
-"Last-Translator: Kirill <kirillathome@gmail.com>\n"
+"PO-Revision-Date: 2007-10-22 22:30-0200\n"
+"Last-Translator: Alex Riesen <raa.lkml@gmail.com>\n"
"Language-Team: Russian Translation <git@vger.kernel.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -21,9 +21,9 @@ msgid "git-gui: fatal error"
msgstr "git-gui: критическая ошибка"
#: git-gui.sh:595
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Invalid font specified in %s:"
-msgstr "В оболочке установлен неверный шрифт.%s:"
+msgstr "В %s установлен неверный шрифт:"
#: git-gui.sh:620
msgid "Main Font"
@@ -31,7 +31,7 @@ msgstr "Шрифт интерфейса"
#: git-gui.sh:621
msgid "Diff/Console Font"
-msgstr "Шрифт в консоли diff"
+msgstr "Шрифт консоли и изменений (diff)"
#: git-gui.sh:635
msgid "Cannot find git in PATH."
@@ -64,9 +64,8 @@ msgid "Git directory not found:"
msgstr "Каталог Git не найден:"
#: git-gui.sh:860
-#, fuzzy
msgid "Cannot move to top of working directory:"
-msgstr "Каталог.git испорчен: "
+msgstr "Невозможно перейти к корню рабочего каталога репозитория: "
#: git-gui.sh:867
msgid "Cannot use funny .git directory:"
@@ -78,7 +77,7 @@ msgstr "Отсутствует рабочий каталог"
#: git-gui.sh:1019
msgid "Refreshing file status..."
-msgstr "Обновление состояния файлов проекта..."
+msgstr "Обновление информации о состоянии файлов..."
#: git-gui.sh:1084
msgid "Scanning for modified files ..."
@@ -94,7 +93,7 @@ msgstr "Не изменено"
#: git-gui.sh:1527
msgid "Modified, not staged"
-msgstr "Изменено, но не включено"
+msgstr "Изменено, не подготовлено"
#: git-gui.sh:1528 git-gui.sh:1533
msgid "Staged for commit"
@@ -105,7 +104,6 @@ msgid "Portions staged for commit"
msgstr "Части, подготовленные для сохранения"
#: git-gui.sh:1530 git-gui.sh:1535
-#, fuzzy
msgid "Staged for commit, missing"
msgstr "Подготовлено для сохранения, отсутствует"
@@ -123,7 +121,7 @@ msgstr "Подготовлено для удаления"
#: git-gui.sh:1539
msgid "Staged for removal, still present"
-msgstr "Подготовлено для удаления, но еще не удалено"
+msgstr "Подготовлено для удаления, еще не удалено"
#: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544
msgid "Requires merge resolution"
@@ -157,7 +155,6 @@ msgid "Branch"
msgstr "Ветвь"
#: git-gui.sh:1794 lib/choose_rev.tcl:547
-#, fuzzy
msgid "Commit@@noun"
msgstr "Состояние"
@@ -166,18 +163,16 @@ msgid "Merge"
msgstr "Объединить"
#: git-gui.sh:1798 lib/choose_rev.tcl:556
-#, fuzzy
msgid "Remote"
-msgstr "внешний:"
+msgstr "Внешние репозитории"
#: git-gui.sh:1807
msgid "Browse Current Branch's Files"
msgstr "Просмотреть файлы текущей ветви"
#: git-gui.sh:1811
-#, fuzzy
msgid "Browse Branch Files..."
-msgstr "Показать файлы ветви"
+msgstr "Показать файлы ветви..."
#: git-gui.sh:1816
msgid "Visualize Current Branch's History"
@@ -188,9 +183,9 @@ msgid "Visualize All Branch History"
msgstr "История всех ветвей наглядно"
#: git-gui.sh:1827
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Browse %s's Files"
-msgstr "Показать файлы ветви"
+msgstr "Показать файлы ветви %s"
#: git-gui.sh:1829
#, tcl-format
@@ -281,12 +276,10 @@ msgid "Rescan"
msgstr "Перечитать"
#: git-gui.sh:1953
-#, fuzzy
msgid "Stage To Commit"
msgstr "Подготовить для сохранения"
#: git-gui.sh:1958
-#, fuzzy
msgid "Stage Changed Files To Commit"
msgstr "Подготовить измененные файлы для сохранения"
@@ -303,7 +296,6 @@ msgid "Sign Off"
msgstr "Подписать"
#: git-gui.sh:1980 git-gui.sh:2296
-#, fuzzy
msgid "Commit@@verb"
msgstr "Сохранить"
@@ -319,11 +311,10 @@ msgstr "Прервать объединение..."
msgid "Push..."
msgstr "Отправить..."
-# carbon copy
#: git-gui.sh:2019 lib/choose_repository.tcl:41
#, fuzzy
msgid "Apple"
-msgstr "Apple"
+msgstr ""
#: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13
#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
@@ -347,9 +338,8 @@ msgstr "Помощь"
msgid "Online Documentation"
msgstr "Документация в интернете"
-# TOVERIFY
#: git-gui.sh:2165
-#, fuzzy, tcl-format
+#, tcl-format
msgid "fatal: cannot stat path %s: No such file or directory"
msgstr "критическая ошибка: %s: нет такого файла или каталога"
@@ -358,43 +348,34 @@ msgid "Current Branch:"
msgstr "Текущая ветвь:"
#: git-gui.sh:2219
-#, fuzzy
msgid "Staged Changes (Will Commit)"
msgstr "Подготовлено (будет сохранено)"
-# TOVERIFY
#: git-gui.sh:2239
-#, fuzzy
msgid "Unstaged Changes"
-msgstr "Изменено"
+msgstr "Изменено (не будет сохранено)"
-# carbon copy
#: git-gui.sh:2286
-#, fuzzy
msgid "Stage Changed"
-msgstr "Stage Changed"
+msgstr "Подготовить все"
#: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182
msgid "Push"
msgstr "Отправить"
#: git-gui.sh:2332
-#, fuzzy
msgid "Initial Commit Message:"
-msgstr "Первоначальный комментарий к состоянию:"
+msgstr "Комментарий к первому состоянию:"
#: git-gui.sh:2333
-#, fuzzy
msgid "Amended Commit Message:"
-msgstr "Исправленный комментарий к состоянию:"
+msgstr "Комментарий к исправленному состоянию:"
#: git-gui.sh:2334
-#, fuzzy
msgid "Amended Initial Commit Message:"
-msgstr "Первоначальный комментарий к исправленному состоянию:"
+msgstr "Комментарий к исправленному первоначальному состоянию:"
#: git-gui.sh:2335
-#, fuzzy
msgid "Amended Merge Commit Message:"
msgstr "Комментарий к исправленному объединению:"
@@ -467,9 +448,7 @@ msgstr ""
"запущенными из %s\n"
"\n"
-# TOVERIFY
#: git-gui.sh:2707
-#, fuzzy
msgid ""
"\n"
"This is due to a known issue with the\n"
@@ -491,10 +470,10 @@ msgid ""
msgstr ""
"\n"
"\n"
-"Хорошая замена для %s\n"
-"сохраняет значения для user.name и\n"
-"user.email в Ваш персональный\n"
-"~/.gitconfig файл.\n"
+"Вместо использования %s можно\n"
+"сохранить значения user.name и\n"
+"user.email в Вашем персональном\n"
+"файле ~/.gitconfig.\n"
#: lib/about.tcl:25
msgid "git-gui - a graphical user interface for Git."
@@ -510,69 +489,56 @@ msgstr "Сохраненное состояние:"
#: lib/blame.tcl:249
msgid "Copy Commit"
-msgstr "Копировать сохраненное состояние"
+msgstr "Скопировать SHA-1"
#: lib/blame.tcl:369
#, tcl-format
msgid "Reading %s..."
msgstr "Чтение %s..."
-# carbon copy
#: lib/blame.tcl:473
-#, fuzzy
msgid "Loading copy/move tracking annotations..."
-msgstr "Loading copy/move tracking annotations..."
+msgstr "Загрузка аннотации копирований/переименований..."
-# TOVERIFY
#: lib/blame.tcl:493
-#, fuzzy
msgid "lines annotated"
-msgstr "строк прокоментировано"
+msgstr "строк прокомментировано"
-# carbon copy
#: lib/blame.tcl:674
-#, fuzzy
msgid "Loading original location annotations..."
-msgstr "Loading original location annotations..."
+msgstr "Загрузка аннотаций первоначального положения объекта..."
-# carbon copy
#: lib/blame.tcl:677
-#, fuzzy
msgid "Annotation complete."
-msgstr "Annotation complete."
+msgstr "Аннотация завершена."
#: lib/blame.tcl:731
-#, fuzzy
msgid "Loading annotation..."
-msgstr "Загрузка %s..."
+msgstr "Загрузка аннотации..."
#: lib/blame.tcl:787
msgid "Author:"
msgstr "Автор:"
#: lib/blame.tcl:791
-#, fuzzy
msgid "Committer:"
-msgstr "Сохраненное состояние:"
+msgstr "Сохранил:"
#: lib/blame.tcl:796
msgid "Original File:"
msgstr "Исходный файл:"
-# carbon copy
#: lib/blame.tcl:910
-#, fuzzy
msgid "Originally By:"
-msgstr "Originally By:"
+msgstr "Источник:"
#: lib/blame.tcl:916
-#, fuzzy
msgid "In File:"
msgstr "Файл:"
#: lib/blame.tcl:921
msgid "Copied Or Moved Here By:"
-msgstr "Кто скопировал/переместил сюда:"
+msgstr "Скопировано/перемещено в:"
#: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19
msgid "Checkout Branch"
@@ -702,7 +668,7 @@ msgid ""
"\n"
" Delete the selected branches?"
msgstr ""
-"Восстановить удаленную ветвь сложно. \n"
+"Восстанавливать удаленные ветви сложно. \n"
"\n"
" Удалить выбранные ветви?"
@@ -773,14 +739,14 @@ msgid "Browse"
msgstr "Показать"
#: lib/checkout_op.tcl:79
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Fetching %s from %s"
-msgstr "Получение изменений из %s "
+msgstr "Получение %s из %s "
#: lib/checkout_op.tcl:127
#, tcl-format
msgid "fatal: Cannot resolve %s"
-msgstr "критическая ошибка: не могу распознать %s"
+msgstr "критическая ошибка: невозможно разрешить %s"
#: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31
msgid "Close"
@@ -807,7 +773,7 @@ msgstr ""
#: lib/checkout_op.tcl:220
#, tcl-format
msgid "Merge strategy '%s' not supported."
-msgstr "Операция объединения '%s' не поддерживается."
+msgstr "Стратегия объединения '%s' не поддерживается."
#: lib/checkout_op.tcl:239
#, tcl-format
@@ -815,9 +781,8 @@ msgid "Failed to update '%s'."
msgstr "Не удалось обновить '%s'."
#: lib/checkout_op.tcl:251
-#, fuzzy
msgid "Staging area (index) is already locked."
-msgstr "Индекс заблокирован."
+msgstr "Рабочая область заблокирована другим процессом."
#: lib/checkout_op.tcl:266
msgid ""
@@ -829,14 +794,15 @@ msgid ""
msgstr ""
"Последнее прочитанное состояние репозитория не соответствует текущему.\n"
"\n"
-"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n"
+"С момента последней проверки репозиторий был изменен другой программой Git. "
+"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n"
"\n"
"Это будет сделано сейчас автоматически.\n"
#: lib/checkout_op.tcl:322
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Updating working directory to '%s'..."
-msgstr "Отсутствует рабочий каталог"
+msgstr "Обновление рабочего каталога из '%s'..."
#: lib/checkout_op.tcl:353
#, tcl-format
@@ -863,9 +829,9 @@ msgstr ""
"Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, начиная с 'Текущего отсоединенного состояния'."
#: lib/checkout_op.tcl:446
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Checked out '%s'."
-msgstr "Перейти..."
+msgstr "Ветвь '%s' сделана текущей."
#: lib/checkout_op.tcl:478
#, tcl-format
@@ -901,7 +867,6 @@ msgstr ""
"Этого не должно было произойти. %s завершается."
#: lib/choose_font.tcl:39
-#, fuzzy
msgid "Select"
msgstr "Выделить все"
@@ -910,15 +875,13 @@ msgid "Font Family"
msgstr "Шрифт"
#: lib/choose_font.tcl:73
-#, fuzzy
msgid "Font Size"
-msgstr "Уменьшить размер шрифта"
+msgstr "Размер шрифта"
#: lib/choose_font.tcl:90
msgid "Font Example"
msgstr "Пример текста"
-# TOVERIFY: what's the Russian version of the font sample (see Windows Fonts).
#: lib/choose_font.tcl:101
msgid ""
"This is example text.\n"
@@ -929,39 +892,34 @@ msgstr ""
#: lib/choose_repository.tcl:25
msgid "Git Gui"
-msgstr "Git Gui"
+msgstr ""
#: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204
-#, fuzzy
msgid "Create New Repository"
-msgstr "Из репозитория"
+msgstr "Создать новый репозиторий"
#: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291
-#, fuzzy
msgid "Clone Existing Repository"
-msgstr "Репозиторий назначения"
+msgstr "Склонировать существующий репозиторий"
#: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800
-#, fuzzy
msgid "Open Existing Repository"
-msgstr "Репозиторий назначения"
+msgstr "Выбрать существующий репозиторий"
-# TOVERIFY
#: lib/choose_repository.tcl:91
-#, fuzzy
msgid "Next >"
msgstr "Дальше >"
#: lib/choose_repository.tcl:152
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Location %s already exists."
-msgstr "Ветвь '%s' уже существует."
+msgstr "Путь '%s' уже существует."
#: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165
#: lib/choose_repository.tcl:172
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Failed to create repository %s:"
-msgstr "Не удалось полностью сохранить настройки:"
+msgstr "Не удалось создать репозиторий %s:"
#: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309
msgid "Directory:"
@@ -969,121 +927,98 @@ msgstr "Каталог:"
#: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363
#: lib/choose_repository.tcl:834
-#, fuzzy
msgid "Git Repository"
msgstr "Репозиторий"
#: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Directory %s already exists."
-msgstr "Ветвь '%s' уже существует."
+msgstr "Каталог '%s' уже существует."
#: lib/choose_repository.tcl:265
-#, fuzzy, tcl-format
+#, tcl-format
msgid "File %s already exists."
-msgstr "Ветвь '%s' уже существует."
+msgstr "Файл '%s' уже существует."
#: lib/choose_repository.tcl:286
-#, fuzzy
msgid "Clone"
-msgstr "Закрыть"
+msgstr "Склонировать"
#: lib/choose_repository.tcl:299
msgid "URL:"
msgstr "Ссылка:"
-# TOVERIFY
#: lib/choose_repository.tcl:319
-#, fuzzy
msgid "Clone Type:"
msgstr "Тип клона:"
-# TOVERIFY
#: lib/choose_repository.tcl:325
-#, fuzzy
msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)"
-# TOVERIFY
#: lib/choose_repository.tcl:331
-#, fuzzy
msgid "Full Copy (Slower, Redundant Backup)"
-msgstr "Полная копия (Медленный, избыточная резервная копия)"
+msgstr "Полная копия (Медленный, создает резервную копию)"
-# TOVERIFY
#: lib/choose_repository.tcl:337
-#, fuzzy
msgid "Shared (Fastest, Not Recommended, No Backup)"
msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)"
#: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418
#: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630
#: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Not a Git repository: %s"
-msgstr "Не указан репозиторий"
+msgstr "Каталог не является репозиторием: %s"
-# TOVERIFY
#: lib/choose_repository.tcl:405
-#, fuzzy
msgid "Standard only available for local repository."
msgstr "Стандартный клон возможен только для локального репозитория."
-# TOVERIFY
#: lib/choose_repository.tcl:409
-#, fuzzy
msgid "Shared only available for local repository."
msgstr "Общий клон возможен только для локального репозитория."
-# TOVERIFY
#: lib/choose_repository.tcl:439
-#, fuzzy
msgid "Failed to configure origin"
-msgstr "Не могу сконфигурировать искходник."
+msgstr "Не могу сконфигурировать исходный репозиторий."
#: lib/choose_repository.tcl:451
msgid "Counting objects"
msgstr "Считаю объекты"
-# carbon copy
#: lib/choose_repository.tcl:452
#, fuzzy
msgid "buckets"
-msgstr "buckets"
+msgstr ""
-# TOVERIFY
#: lib/choose_repository.tcl:476
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Unable to copy objects/info/alternates: %s"
-msgstr "Не могу скопировать объекты/инфо/альтернативы: %s"
+msgstr "Не могу скопировать objects/info/alternates: %s"
#: lib/choose_repository.tcl:512
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Nothing to clone from %s."
-msgstr "Получение изменений из %s "
+msgstr "Нечего клонировать с %s."
-# TOVERIFY
#: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728
#: lib/choose_repository.tcl:740
-#, fuzzy
msgid "The 'master' branch has not been initialized."
msgstr "Не инициализирована ветвь 'master'."
-# TOVERIFY
#: lib/choose_repository.tcl:527
-#, fuzzy
msgid "Hardlinks are unavailable. Falling back to copying."
msgstr "\"Жесткие ссылки\" не доступны. Буду использовать копирование."
#: lib/choose_repository.tcl:539
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Cloning from %s"
-msgstr "Получение изменений из %s "
+msgstr "Клонирование %s"
#: lib/choose_repository.tcl:570
-#, fuzzy
msgid "Copying objects"
-msgstr "Сжатие базы объектов"
+msgstr "Копирование objects"
#: lib/choose_repository.tcl:571
msgid "KiB"
@@ -1096,42 +1031,33 @@ msgstr "Не могу скопировать объект: %s"
#: lib/choose_repository.tcl:605
msgid "Linking objects"
-msgstr "Связываю объекты"
+msgstr "Создание ссылок на objects"
-# TOVERIFY
#: lib/choose_repository.tcl:606
-#, fuzzy
msgid "objects"
-msgstr "объектов"
+msgstr "объекты"
-# TOVERIFY
#: lib/choose_repository.tcl:614
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Unable to hardlink object: %s"
msgstr "Не могу \"жестко связать\" объект: %s"
-# TOVERIFY
#: lib/choose_repository.tcl:669
-#, fuzzy
msgid "Cannot fetch branches and objects. See console output for details."
-msgstr "Не могу получить ветви и объекты. Детали - на консоле."
+msgstr "Не могу получить ветви и объекты. Дополнительная информация на консоли."
-# TOVERIFY
#: lib/choose_repository.tcl:680
-#, fuzzy
msgid "Cannot fetch tags. See console output for details."
-msgstr "Не могу получить таги. Детали - на консоле."
+msgstr "Не могу получить метки. Дополнительная информация на консоли."
-# TOVERIFY
#: lib/choose_repository.tcl:704
-#, fuzzy
msgid "Cannot determine HEAD. See console output for details."
-msgstr "Не могу определить главную ветвь. Детали - на консоле."
+msgstr "Не могу определить HEAD. Дополнительная информация на консоли."
#: lib/choose_repository.tcl:713
#, tcl-format
msgid "Unable to cleanup %s"
-msgstr "Не могу почистить %s"
+msgstr "Не могу очистить %s"
#: lib/choose_repository.tcl:719
msgid "Clone failed."
@@ -1139,7 +1065,7 @@ msgstr "Клонирование не удалось."
#: lib/choose_repository.tcl:726
msgid "No default branch obtained."
-msgstr "Не возможно получить ветвь по умолчанию."
+msgstr "Не было получено ветви по умолчанию."
#: lib/choose_repository.tcl:737
#, tcl-format
@@ -1147,9 +1073,8 @@ msgid "Cannot resolve %s as a commit."
msgstr "Не могу распознать %s как состояние."
#: lib/choose_repository.tcl:749
-#, fuzzy
msgid "Creating working directory"
-msgstr "Отсутствует рабочий каталог"
+msgstr "Создаю рабочий каталог"
#: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80
#: lib/index.tcl:149
@@ -1158,21 +1083,20 @@ msgstr "файлов"
#: lib/choose_repository.tcl:779
msgid "Initial file checkout failed."
-msgstr "Первое получение файла не удалось."
+msgstr "Не удалось получить начальное состояние файлов репозитория."
#: lib/choose_repository.tcl:795
msgid "Open"
msgstr "Открыть"
#: lib/choose_repository.tcl:805
-#, fuzzy
msgid "Repository:"
-msgstr "Репозиторий"
+msgstr "Репозиторий:"
#: lib/choose_repository.tcl:854
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Failed to open repository %s:"
-msgstr "Не удалось полностью сохранить настройки:"
+msgstr "Не удалось открыть репозиторий %s:"
#: lib/choose_rev.tcl:53
msgid "This Detached Checkout"
@@ -1205,7 +1129,7 @@ msgstr "Версия не указана."
#: lib/choose_rev.tcl:346
msgid "Revision expression is empty."
-msgstr "Пустое выражения для определения версии."
+msgstr "Пустое выражение для определения версии."
#: lib/choose_rev.tcl:530
msgid "Updated"
@@ -1223,7 +1147,7 @@ msgid ""
msgstr ""
"Отсутствует состояние для исправления.\n"
"\n"
-"Вы можете создать начальное сохраненное состояние. Других состояний для исправления нет.\n"
+"Вы создаете первое состояние в репозитории, здесь еще нечего исправлять.\n"
#: lib/commit.tcl:18
msgid ""
@@ -1257,12 +1181,12 @@ msgid ""
msgstr ""
"Последнее прочитанное состояние репозитория не соответствует текущему.\n"
"\n"
-"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n"
+"С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n"
"\n"
"Это будет сделано сейчас автоматически.\n"
#: lib/commit.tcl:154
-#, fuzzy, tcl-format
+#, tcl-format
msgid ""
"Unmerged files cannot be committed.\n"
"\n"
@@ -1284,7 +1208,6 @@ msgstr ""
"Файл %s не может быть сохранен данной программой.\n"
#: lib/commit.tcl:170
-#, fuzzy
msgid ""
"No changes to commit.\n"
"\n"
@@ -1416,14 +1339,14 @@ msgid ""
msgstr ""
"Этот репозиторий сейчас содержит примерно %i свободных объектов\n"
"\n"
-"Для лучшей производительности рекомендуется сжать базу данных, когда есть более %i свободных объектов.\n"
+"Для лучшей производительности рекомендуется сжать базу данных, когда есть более %i несвязанных объектов.\n"
"\n"
"Сжать базу данных сейчас?"
#: lib/date.tcl:25
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Invalid date from Git: %s"
-msgstr "Неверная версия: %s"
+msgstr "Неправильная дата в репозитории: %s"
#: lib/diff.tcl:42
#, tcl-format
@@ -1445,9 +1368,9 @@ msgstr ""
"Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы."
#: lib/diff.tcl:81
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Loading diff of %s..."
-msgstr "Загрузка %s..."
+msgstr "Загрузка изменений в %s..."
#: lib/diff.tcl:114 lib/diff.tcl:184
#, tcl-format
@@ -1460,7 +1383,7 @@ msgstr "Ошибка загрузки файла:"
#: lib/diff.tcl:122
msgid "Git Repository (subproject)"
-msgstr "Репозиторий Git (под-проект)"
+msgstr "Репозиторий Git (подпроект)"
#: lib/diff.tcl:134
msgid "* Binary file (not showing content)."
@@ -1472,11 +1395,11 @@ msgstr "Ошибка загрузки diff:"
#: lib/diff.tcl:302
msgid "Failed to unstage selected hunk."
-msgstr "Не удалось исключить выбранную часть"
+msgstr "Не удалось исключить выбранную часть."
#: lib/diff.tcl:309
msgid "Failed to stage selected hunk."
-msgstr "Не удалось подготовить к сохранению выбранную часть"
+msgstr "Не удалось подготовить к сохранению выбранную часть."
#: lib/error.tcl:12 lib/error.tcl:102
msgid "error"
@@ -1491,19 +1414,19 @@ msgid "You must correct the above errors before committing."
msgstr "Прежде чем сохранить, исправьте вышеуказанные ошибки."
#: lib/index.tcl:241
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Unstaging %s from commit"
-msgstr "Убрать из подготовленного"
+msgstr "Удаление %s из подготовленного"
#: lib/index.tcl:285
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Adding %s"
-msgstr "Чтение %s..."
+msgstr "Добавление %s..."
#: lib/index.tcl:340
-#, fuzzy, tcl-format
+#, tcl-format
msgid "Revert changes in file %s?"
-msgstr "Отменить изменения"
+msgstr "Отменить изменения в файле %s?"
#: lib/index.tcl:342
#, tcl-format
@@ -1511,11 +1434,8 @@ msgid "Revert changes in these %i files?"
msgstr "Отменить изменения в %i файле(-ах)?"
#: lib/index.tcl:348
-#, fuzzy
msgid "Any unstaged changes will be permanently lost by the revert."
msgstr ""
-"Отменить изменения в %s?\n"
-"\n"
"Любые изменения, не подготовленные к сохранению, будут потеряны при данной операции."
#: lib/index.tcl:351
@@ -1542,12 +1462,12 @@ msgid ""
msgstr ""
"Последнее прочитанное состояние репозитория не соответствует текущему.\n"
"\n"
-"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n"
+"С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n"
"\n"
"Это будет сделано сейчас автоматически.\n"
#: lib/merge.tcl:44
-#, fuzzy, tcl-format
+#, tcl-format
msgid ""
"You are in the middle of a conflicted merge.\n"
"\n"
@@ -1599,9 +1519,8 @@ msgid "Merge Into %s"
msgstr "Объединить с %s"
#: lib/merge.tcl:177
-#, fuzzy
msgid "Revision To Merge"
-msgstr "Версия"
+msgstr "Версия для объединения"
#: lib/merge.tcl:212
msgid ""
@@ -1622,12 +1541,12 @@ msgid ""
"Continue with aborting the current merge?"
msgstr ""
"Прервать объединение?\n"
+"\n"
"Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n"
"\n"
"Продолжить?"
#: lib/merge.tcl:228
-#, fuzzy
msgid ""
"Reset changes?\n"
"\n"
@@ -1636,6 +1555,7 @@ msgid ""
"Continue with resetting the current changes?"
msgstr ""
"Прервать объединение?\n"
+"\n"
"Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n"
"\n"
"Продолжить?"
@@ -1663,7 +1583,7 @@ msgstr "Сохранить"
#: lib/option.tcl:96
#, tcl-format
msgid "%s Repository"
-msgstr "для репозитория %s "
+msgstr "для репозитория %s"
#: lib/option.tcl:97
msgid "Global (All Repositories)"
@@ -1710,7 +1630,6 @@ msgid "New Branch Name Template"
msgstr "Шаблон для имени новой ветви"
#: lib/option.tcl:176
-#, fuzzy
msgid "Change Font"
msgstr "Шрифт интерфейса"
@@ -1723,7 +1642,7 @@ msgstr "Выберите %s"
#: lib/option.tcl:186
#, fuzzy
msgid "pt."
-msgstr "pt."
+msgstr ""
#: lib/option.tcl:200
msgid "Preferences"
@@ -1734,17 +1653,14 @@ msgid "Failed to completely save options:"
msgstr "Не удалось полностью сохранить настройки:"
#: lib/remote.tcl:165
-#, fuzzy
msgid "Prune from"
-msgstr "Чистка %s... "
+msgstr "Чистка"
#: lib/remote.tcl:170
-#, fuzzy
msgid "Fetch from"
-msgstr "Чистка %s... "
+msgstr "Получение из"
#: lib/remote.tcl:213
-#, fuzzy
msgid "Push to"
msgstr "Отправить"
@@ -1785,18 +1701,22 @@ msgid "A branch is required for 'Merged Into'."
msgstr "Для опции 'Объединено с' требуется указать ветвь."
#: lib/remote_branch_delete.tcl:184
-#, fuzzy, tcl-format
+#, tcl-format
msgid ""
"The following branches are not completely merged into %s:\n"
"\n"
" - %s"
-msgstr "Следующие ветви объединены с %s не полностью:"
+msgstr ""
+"Следующие ветви объединены с %s не полностью:"
+"\n"
+" - %s"
-# TOVERIFY
#: lib/remote_branch_delete.tcl:189
-#, fuzzy, tcl-format
+#, tcl-format
msgid "One or more of the merge tests failed because you have not fetched the necessary commits. Try fetching from %s first."
-msgstr "Один или несколько тестов на объединение не прошли, потому что Вы не получили необходимые состояния. Попробуйте сначала получить из %s."
+msgstr ""
+"Один или несколько тестов на объединение не прошли, потому что "
+"Вы не получили необходимые состояния. Попробуйте сначала получить их из %s."
#: lib/remote_branch_delete.tcl:207
msgid "Please select one or more branches to delete."
@@ -1819,7 +1739,7 @@ msgstr "Удаление ветвей из %s"
#: lib/remote_branch_delete.tcl:286
msgid "No repository selected."
-msgstr "Не указан репозиторий"
+msgstr "Не указан репозиторий."
#: lib/remote_branch_delete.tcl:291
#, tcl-format
@@ -1840,9 +1760,9 @@ msgid "%s ... %*i of %*i %s (%3i%%)"
msgstr "%s ... %*i из %*i %s (%3i%%)"
#: lib/transport.tcl:6
-#, fuzzy, tcl-format
+#, tcl-format
msgid "fetch %s"
-msgstr "Получить"
+msgstr "получение %s"
#: lib/transport.tcl:7
#, tcl-format
@@ -1851,9 +1771,9 @@ msgstr "Получение изменений из %s "
# carbon copy
#: lib/transport.tcl:18
-#, fuzzy, tcl-format
+#, tcl-format
msgid "remote prune %s"
-msgstr "remote prune %s"
+msgstr "чистка внешнего %s"
#: lib/transport.tcl:19
#, tcl-format
@@ -1877,7 +1797,7 @@ msgstr "Отправка %s %s в %s"
#: lib/transport.tcl:89
msgid "Push Branches"
-msgstr "Отправить изменения"
+msgstr "Отправить изменения в ветвях"
#: lib/transport.tcl:103
msgid "Source Branches"
@@ -1889,7 +1809,7 @@ msgstr "Репозиторий назначения"
#: lib/transport.tcl:158
msgid "Transfer Options"
-msgstr "Настройки передачи"
+msgstr "Настройки отправки"
#: lib/transport.tcl:160
msgid "Force overwrite existing branch (may discard changes)"
@@ -1903,31 +1823,3 @@ msgstr "Использовать thin pack (для медленных сетев
msgid "Include tags"
msgstr "Включить метки"
-#~ msgid "Cannot find the git directory:"
-#~ msgstr "Каталог Git не найден:"
-#~ msgid "Add To Commit"
-#~ msgstr "Подготовить к сохранению"
-#~ msgid "Add Existing To Commit"
-#~ msgstr "Подготовить имеющиеся файлы к сохранению"
-#~ msgid "Unstaged Changes (Will Not Be Committed)"
-#~ msgstr "Изменено (не будет сохранено)"
-#~ msgid "Add Existing"
-#~ msgstr "Добавить имеющиеся файлы"
-#~ msgid ""
-#~ "Abort commit?\n"
-#~ "\n"
-#~ "Aborting the current commit will cause *ALL* uncommitted changes to be "
-#~ "lost.\n"
-#~ "\n"
-#~ "Continue with aborting the current commit?"
-#~ msgstr ""
-#~ "Отменить изменения?\n"
-#~ "\n"
-#~ "Вызванная операция приведет к потере *ВСЕХ* несохраненных изменений.\n"
-#~ "\n"
-#~ "Продолжить?"
-#~ msgid "Aborting... please wait..."
-#~ msgstr "Прерывание выполнения... Пожалуйста, ждите..."
-#~ msgid "Push to %s..."
-#~ msgstr "Отправка в %s..."
-
--
1.5.3.4.245.g150b
^ permalink raw reply related
* Re: [PATCH] Add color to git-add--interactive diffs (Total different idea to solve the problem)
From: Peter Baumann @ 2007-10-22 20:47 UTC (permalink / raw)
To: Tom Tobin
Cc: Dan Zwell, Jonathan del Strother, Johannes Schindelin,
Shawn O. Pearce, Git Mailing List
In-Reply-To: <1192351494.7226.18.camel@athena>
On Sun, Oct 14, 2007 at 03:44:54AM -0500, Tom Tobin wrote:
> (This is repost; my damned mail client wrapped a line in the patch last
> time, and now I've got that under control. My apologies!) :(
>
> Seeing the recent discussion and code regarding adding color to
> git-add--interactive, I thought I'd throw in my recent attempt at
> colorizing the diffs. (This doesn't handle anything else, such as the
> prompts.)
>
> After banging my head against parsing colorized output of git-add-files,
> I gave up and implemented internal colorization keying off of the
> color.diff configuration.
>
> Hopefully this can be of some use towards fully colorizing
> git-add--interactive; I'll admit up front that Perl isn't my primary
> language, so I apologize in advance for whatever stupidities I've
> introduced. ;)
>
> Signed-off-by: Tom Tobin <korpios@korpios.com>
[...skiping patch ...]
Tossing around ideas, so feel free to ignore me.
Wouldn't it make more sense to implement the diff coloring inside git apply
so that you could use something like
diff file1 file2|git apply --color
to make the generated diff with colors [1]? It already implements the
same semantic for generating a diffstat, using
diff file1 file2|git apply --stat
so we would get a generic diff colorizing tool and you could use inside
git add -i the diff without color and just print it out with the
git apply --color filter. So if someone implements another tool which
needs color handling he could use this output filter.
-Peter
[1]: there is a programm colordiff which does exactly this, but AFAIK git
colorization has more features.
^ permalink raw reply
* Re: [PATCH] use only the PATH for exec'ing git commands
From: Alex Riesen @ 2007-10-22 20:57 UTC (permalink / raw)
To: Scott R Parish; +Cc: git
In-Reply-To: <1193083141.v2.fusewebmail-240137@f>
Scott R Parish, Mon, Oct 22, 2007 21:59:01 +0200:
> > > + if (old_path)
> > > + strbuf_addstr(&new_path, old_path);
> > > + else
> > > + strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
> >
> > the default PATH is platform-dependent. Git is multi-platform.
> > You should consider putting the path list somewhere in Makefile,
> > config.mak or configure.
> >
>
> The original code was already doing both of these things (see git.c's
> prepend_to_path())
Well, would be nice if your code was better in this respect.
Anyway, I suspect the mingw people will trash the code anyway sometime
(or not, which is just as well - it is a rare case).
^ 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