Skip to content

Commit

Permalink
quote.c: separate quoting and relative path generation
Browse files Browse the repository at this point in the history
This is in preparation of relative path support for ls-files, which
quotes a path only if the line terminator is not the NUL character.

Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Clemens Buchacher authored and gitster committed Jun 5, 2010
1 parent c8b2964 commit b167cff
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 29 deletions.
89 changes: 61 additions & 28 deletions quote.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,42 +295,75 @@ void write_name_quotedpfx(const char *pfx, size_t pfxlen,
fputc(terminator, fp);
}

/* quote path as relative to the given prefix */
char *quote_path_relative(const char *in, int len,
struct strbuf *out, const char *prefix)
static const char *path_relative(const char *in, int len,
struct strbuf *sb, const char *prefix,
int prefix_len);

void write_name_quoted_relative(const char *name, size_t len,
const char *prefix, size_t prefix_len,
FILE *fp, int terminator)
{
int needquote;
struct strbuf sb = STRBUF_INIT;

name = path_relative(name, len, &sb, prefix, prefix_len);
write_name_quoted(name, fp, terminator);

strbuf_release(&sb);
}

/*
* Give path as relative to prefix.
*
* The strbuf may or may not be used, so do not assume it contains the
* returned path.
*/
static const char *path_relative(const char *in, int len,
struct strbuf *sb, const char *prefix,
int prefix_len)
{
int off, i;

if (len < 0)
len = strlen(in);
if (prefix && prefix_len < 0)
prefix_len = strlen(prefix);

off = 0;
i = 0;
while (i < prefix_len && i < len && prefix[i] == in[i]) {
if (prefix[i] == '/')
off = i + 1;
i++;
}
in += off;
len -= off;

if (i >= prefix_len)
return in;

/* "../" prefix itself does not need quoting, but "in" might. */
needquote = next_quote_pos(in, len) < len;
strbuf_setlen(out, 0);
strbuf_grow(out, len);

if (needquote)
strbuf_addch(out, '"');
if (prefix) {
int off = 0;
while (prefix[off] && off < len && prefix[off] == in[off])
if (prefix[off] == '/') {
prefix += off + 1;
in += off + 1;
len -= off + 1;
off = 0;
} else
off++;

for (; *prefix; prefix++)
if (*prefix == '/')
strbuf_addstr(out, "../");
strbuf_reset(sb);
strbuf_grow(sb, len);

while (i < prefix_len) {
if (prefix[i] == '/')
strbuf_addstr(sb, "../");
i++;
}
strbuf_add(sb, in, len);

return sb->buf;
}

quote_c_style_counted (in, len, out, NULL, 1);
/* quote path as relative to the given prefix */
char *quote_path_relative(const char *in, int len,
struct strbuf *out, const char *prefix)
{
struct strbuf sb = STRBUF_INIT;
const char *rel = path_relative(in, len, &sb, prefix, -1);
strbuf_reset(out);
quote_c_style_counted(rel, strlen(rel), out, NULL, 0);
strbuf_release(&sb);

if (needquote)
strbuf_addch(out, '"');
if (!out->len)
strbuf_addstr(out, "./");

Expand Down
5 changes: 4 additions & 1 deletion quote.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,12 @@ extern void quote_two_c_style(struct strbuf *, const char *, const char *, int);
extern void write_name_quoted(const char *name, FILE *, int terminator);
extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
const char *name, FILE *, int terminator);
extern void write_name_quoted_relative(const char *name, size_t len,
const char *prefix, size_t prefix_len,
FILE *fp, int terminator);

/* quote path as relative to the given prefix */
char *quote_path_relative(const char *in, int len,
extern char *quote_path_relative(const char *in, int len,
struct strbuf *out, const char *prefix);

/* quoting as a string literal for other languages */
Expand Down

0 comments on commit b167cff

Please sign in to comment.