Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [PATCH] _git: offer changed files relative to current directory



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



Messages sorted by: Reverse Date, Date, Thread, Author