On Sat, Dec 05, 2009 at 01:07:54PM +0100, ??t??p??n N??mec wrote: > No, this is wrong as far as I recall. At least this is better than current behavior. > I was solving the same problem before some time. Your solution (i.e. > git-diff-index --relative) only displays the changed files under a > subdirectory, which is incorrect when not in the repository root. Same problem exists for __git_*_files (__git_files). > I solved the problem by writing a 50 line or so "ueberfunction" which > manually relativizes the paths returned by git-diff-index to the correct > form required by git-commit You can get current subdirectory with "git rev-parse --show-prefix", then all "absolute" paths must be turned into relative. On my system there is "relative" program (comes with rpm-build package), so the code would look like: local -a rawfiles files local f prefix prefix=$(_call_program gitprefix git rev-parse --show-prefix 2>/dev/null) __git_command_successful || return rawfiles=( ... git ls-files or git diff-index call ... ) for f in $rawfiles; do files+=( $(relative /$prefix /$f) ) done _wanted ... Just need pure-zsh "relative" implementation. relative.c attached. P.S. I don't like this for loop. Can this be done with single expansion expression? -- Regards, Sir Raorn.
/* Copyright (C) 2001 Dmitry V. Levin <ldv@xxxxxxxxxxxx> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <error.h> #include <sys/param.h> static void * xmalloc(size_t size) { void *r = malloc(size); if (!r) error(EXIT_FAILURE, errno, "malloc: allocating %lu bytes", (unsigned long) size); return r; } static char * xstrdup(const char *s) { size_t len = strlen(s); char *r = xmalloc(len + 1); memcpy(r, s, len + 1); return r; } static void __attribute__ ((noreturn)) result(const char *str) { puts(str); exit(0); } static const char * normalize(char *str) { char *p; size_t len; for (p = strstr(str, "//"); p; p = strstr(str, "//")) memmove(p, p + 1, strlen(p)); for (p = strstr(str, "/./"); p; p = strstr(str, "/./")) memmove(p, p + 2, strlen(p + 1)); len = strlen(str); if ((len >= 2) && ('/' == str[len - 2]) && ('.' == str[len - 1])) str[len - 1] = '\0'; return str; } static void strip_trailing(char *str, const char sym) { char *p; for (p = strrchr(str, sym); p && (p >= str) && (sym == *p); --p) *p = '\0'; } static const char * base_name(const char *name) { const char *p = strrchr(name, '/'); if (p) return p + 1; else return name; } static char * lookup_back(const char *str, const char sym, const char *pos) { for (; pos >= str; --pos) if (sym == *pos) return (char *) pos; return 0; } int main(int ac, char *av[]) { const char *orig_what; char *what_p, *to_p, *res; char *what, *to; if (ac < 3) { fprintf(stderr, "Usage: %s <what> <to>\n", program_invocation_short_name); return 1; } what = xstrdup(av[1]); to = xstrdup(av[2]); orig_what = normalize(av[1]); normalize(av[2]); what = xstrdup(av[1]); to = xstrdup(av[2]); if ('/' != *what) result(what); if ('/' != *to) error(EXIT_FAILURE, 0, "destination must be absolute filename"); strip_trailing(what, '/'); strip_trailing(to, '/'); for (what_p = what, to_p = to; *what_p && *to_p; ++what_p, ++to_p) if (*what_p != *to_p) break; if (!*what_p && !*to_p) result(base_name(orig_what)); res = xmalloc(strlen(what) + strlen(to) * 3 / 2 + 3); if (('/' == *what_p) && !*to_p) result(orig_what + (++what_p - what)); if ('/' != *to_p || *what_p) { what_p = lookup_back(what, '/', what_p - 1); strcpy(res, ".."); } else { res[0] = '\0'; } for (; *to_p; ++to_p) { if ('/' == *to_p) { if (*res) strcat(res, "/.."); else strcpy(res, ".."); } } strcat(res, orig_what + (what_p - what)); result(res); }
Attachment:
signature.asc
Description: Digital signature