* [RFC] Add "rcs format diff" support
@ 2006-05-13 21:14 Linus Torvalds
2006-05-14 0:12 ` Al Viro
0 siblings, 1 reply; 3+ messages in thread
From: Linus Torvalds @ 2006-05-13 21:14 UTC (permalink / raw)
To: Junio C Hamano, Git Mailing List; +Cc: Al Viro, Davide Libenzi
Al was asking for the "diff -n" format, which is the old RCS format, and
which is really easy to parse.
Now, we can't use the "-n" flag, because we use that for something else,
and quite frankly, I don't know what to do about the diff _header_ (RCS
format doesn't have a header, afaik), but this implements the actual core
"xdiff" rcs-format patch emit logic, and exposes it with the
XDL_EMIT_RCSFORMAT flag.
(In order to get valid diffs, you also have to set the context to zero
when you set the RCSFORMAT flag).
It also adds a "--rcs-format" flag to the git diff option parsing, so you
can test it out, but as mentioned, we will still emit the full git header.
Davide - I think the "xdiff/" sub-part of the patch should apply fine to
the standard xdiff sources, but I'm not sure you're really interested. The
header issue doesn't matter there, of course, since xdiff doesn't output
any headers (ie that is an issue for the higher-level user).
The biggest issue for the xdiff library was that I needed to pass down
the xecfg parameter deeper into the call-chain (ie down to xdl_emit_record
& co). The rest is pretty trivial.
Al - feel free to play with this. I didn't test it heavily, but it gave
the right output for the one case I compared with "diff -n". This patch is
on top of my previous patch to parse "-U" and "--unified".
Junio - this is not really meant for applying, although I don't think
there is any real down-side to this either.
Linus
---
diff --git a/diff.c b/diff.c
index be925a3..fd8f454 100644
--- a/diff.c
+++ b/diff.c
@@ -568,6 +568,10 @@ static void builtin_diff(const char *nam
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
ecb.outf = fn_out;
ecb.priv = &ecbdata;
+ if (o->rcs_format) {
+ xecfg.flags |= XDL_EMIT_RCSFORMAT;
+ xecfg.ctxlen = 0;
+ }
xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
}
@@ -1277,6 +1281,8 @@ int diff_opt_parse(struct diff_options *
options->output_format = DIFF_FORMAT_PATCH;
else if (opt_arg(arg, 'U', "unified", &options->context))
options->output_format = DIFF_FORMAT_PATCH;
+ else if (!strcmp(arg, "--rcs-format"))
+ options->rcs_format = 1;
else if (!strcmp(arg, "--patch-with-raw")) {
options->output_format = DIFF_FORMAT_PATCH;
options->with_raw = 1;
diff --git a/diff.h b/diff.h
index bef586d..953beb9 100644
--- a/diff.h
+++ b/diff.h
@@ -29,6 +29,7 @@ struct diff_options {
with_stat:1,
tree_in_recursive:1,
binary:1,
+ rcs_format:1,
full_index:1,
silent_on_remove:1,
find_copies_harder:1;
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 2540e8a..a52359e 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -36,6 +36,7 @@ #define XDL_PATCH_MODEMASK ((1 << 8) - 1
#define XDL_PATCH_IGNOREBSPACE (1 << 8)
#define XDL_EMIT_FUNCNAMES (1 << 0)
+#define XDL_EMIT_RCSFORMAT (1 << 1)
#define XDL_MMB_READONLY (1 << 0)
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index ad5bfb1..e127469 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -26,7 +26,7 @@ #include "xinclude.h"
static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec);
-static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb);
+static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb, xdemitconf_t const *xecfg);
static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
@@ -40,12 +40,13 @@ static long xdl_get_rec(xdfile_t *xdf, l
}
-static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb) {
+static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre,
+ xdemitcb_t *ecb, xdemitconf_t const *xecfg) {
long size, psize = strlen(pre);
char const *rec;
size = xdl_get_rec(xdf, ri, &rec);
- if (xdl_emit_diffrec(rec, size, pre, psize, ecb) < 0) {
+ if (xdl_emit_diffrec(rec, size, pre, psize, ecb, xecfg) < 0) {
return -1;
}
@@ -129,14 +130,14 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange
sizeof(funcbuf), &funclen);
}
if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
- funcbuf, funclen, ecb) < 0)
+ funcbuf, funclen, ecb, xecfg) < 0)
return -1;
/*
* Emit pre-context.
*/
for (; s1 < xch->i1; s1++)
- if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0)
+ if (xdl_emit_record(&xe->xdf1, s1, " ", ecb, xecfg) < 0)
return -1;
for (s1 = xch->i1, s2 = xch->i2;; xch = xch->next) {
@@ -144,21 +145,21 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange
* Merge previous with current change atom.
*/
for (; s1 < xch->i1 && s2 < xch->i2; s1++, s2++)
- if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0)
+ if (xdl_emit_record(&xe->xdf1, s1, " ", ecb, xecfg) < 0)
return -1;
/*
* Removes lines from the first file.
*/
for (s1 = xch->i1; s1 < xch->i1 + xch->chg1; s1++)
- if (xdl_emit_record(&xe->xdf1, s1, "-", ecb) < 0)
+ if (xdl_emit_record(&xe->xdf1, s1, "-", ecb, xecfg) < 0)
return -1;
/*
* Adds lines from the second file.
*/
for (s2 = xch->i2; s2 < xch->i2 + xch->chg2; s2++)
- if (xdl_emit_record(&xe->xdf2, s2, "+", ecb) < 0)
+ if (xdl_emit_record(&xe->xdf2, s2, "+", ecb, xecfg) < 0)
return -1;
if (xch == xche)
@@ -171,7 +172,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange
* Emit post-context.
*/
for (s1 = xche->i1 + xche->chg1; s1 < e1; s1++)
- if (xdl_emit_record(&xe->xdf1, s1, " ", ecb) < 0)
+ if (xdl_emit_record(&xe->xdf1, s1, " ", ecb, xecfg) < 0)
return -1;
}
diff --git a/xdiff/xutils.c b/xdiff/xutils.c
index 21ab8e7..b0d075a 100644
--- a/xdiff/xutils.c
+++ b/xdiff/xutils.c
@@ -43,10 +43,20 @@ long xdl_bogosqrt(long n) {
int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
- xdemitcb_t *ecb) {
+ xdemitcb_t *ecb, xdemitconf_t const *xecfg) {
mmbuffer_t mb[3];
int i;
+ if (xecfg->flags & XDL_EMIT_RCSFORMAT) {
+ if (*pre != '+')
+ return 0;
+ mb[0].ptr = (char *) rec;
+ mb[0].size = size;
+ if (ecb->outf(ecb->priv, mb, 1) < 0)
+ return -1;
+ return 0;
+ }
+
mb[0].ptr = (char *) pre;
mb[0].size = psize;
mb[1].ptr = (char *) rec;
@@ -249,11 +259,34 @@ long xdl_atol(char const *str, char cons
int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
- const char *func, long funclen, xdemitcb_t *ecb) {
+ const char *func, long funclen,
+ xdemitcb_t *ecb, xdemitconf_t const *xecfg) {
int nb = 0;
mmbuffer_t mb;
char buf[128];
+ if (xecfg->flags & XDL_EMIT_RCSFORMAT) {
+ if (c1) {
+ buf[nb++] = 'd';
+ nb += xdl_num_out(buf + nb, s1);
+ buf[nb++] = ' ';
+ nb += xdl_num_out(buf + nb, c1);
+ buf[nb++] = '\n';
+ }
+ if (c2) {
+ buf[nb++] = 'a';
+ nb += xdl_num_out(buf + nb, s2);
+ buf[nb++] = ' ';
+ nb += xdl_num_out(buf + nb, c2);
+ buf[nb++] = '\n';
+ }
+ mb.ptr = buf;
+ mb.size = nb;
+ if (ecb->outf(ecb->priv, &mb, 1) < 0)
+ return -1;
+ return 0;
+ }
+
memcpy(buf, "@@ -", 4);
nb += 4;
diff --git a/xdiff/xutils.h b/xdiff/xutils.h
index ea38ee9..e5c6ed0 100644
--- a/xdiff/xutils.h
+++ b/xdiff/xutils.h
@@ -26,7 +26,7 @@ #define XUTILS_H
long xdl_bogosqrt(long n);
int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
- xdemitcb_t *ecb);
+ xdemitcb_t *ecb, xdemitconf_t const *xecfg);
int xdl_cha_init(chastore_t *cha, long isize, long icount);
void xdl_cha_free(chastore_t *cha);
void *xdl_cha_alloc(chastore_t *cha);
@@ -38,7 +38,8 @@ unsigned int xdl_hashbits(unsigned int s
int xdl_num_out(char *out, long val);
long xdl_atol(char const *str, char const **next);
int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
- const char *func, long funclen, xdemitcb_t *ecb);
+ const char *func, long funclen,
+ xdemitcb_t *ecb, xdemitconf_t const *xecfg);
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [RFC] Add "rcs format diff" support
2006-05-13 21:14 [RFC] Add "rcs format diff" support Linus Torvalds
@ 2006-05-14 0:12 ` Al Viro
2006-05-16 20:49 ` Al Viro
0 siblings, 1 reply; 3+ messages in thread
From: Al Viro @ 2006-05-14 0:12 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Junio C Hamano, Git Mailing List, Al Viro, Davide Libenzi
On Sat, May 13, 2006 at 02:14:15PM -0700, Linus Torvalds wrote:
>
> Al was asking for the "diff -n" format, which is the old RCS format, and
> which is really easy to parse.
Heh... And I've just managed to get around that stuff on plain git. Have fun:
Use:
git-remap-data [git-diff arguments] > map
git-remap map <old-log >remapped-old
git-remap /dev/null <new-log >remapped-new
diff -u remapped-old remapped-new
with old-log and new-log being build/sparse/whatever logs produced on
trees in question (for values of "whatever logs" including e.g. grep -n
results, etc.)
git-remap-data builds the description of how lines of old tree are mapped
to the new one; git-remap is a filter using that data to massage log
from the old tree to new one; lines of form
<file>:<line>:<text>
are turned into
N:<new-file>:<new-line>:<text>
if they survive in new tree and
O:<file>:<line>:<text>
otherwise.
Here they are; enjoy. BTW, that puppy can be used on unified diffs with
zero context; won't catch renames, obviously...
git-remap-data.sh:
#!/bin/sh
GIT_DIFF_OPTS="-u 0" git-diff -M "$@" | git-remap
git-remap.c:
/*
* Copyright (c) 2006, Al Viro. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
char *prefix1 = "a/", *prefix2 = "b/";
size_t len1, len2;
char *line;
size_t size;
void die(char *s)
{
fprintf(stderr, "remap: %s\n", s);
exit(1);
}
void Enomem(void)
{
die("out of memory");
}
void Eio(void)
{
die("IO error");
}
int getline(FILE *f)
{
char *s;
if (!fgets(line, size, f)) {
if (!feof(f))
Eio();
return 0;
}
for (s = line + strlen(line); s[-1] != '\n'; s = s + strlen(s)) {
if (s == line + size - 1) {
line = realloc(line, 2 * size);
if (!line)
Enomem();
s = line + size - 1;
size *= 2;
}
if (!fgets(s, size - (s - line), f)) {
if (!feof(f))
Eio();
return 1;
}
}
s[-1] = '\0';
return 1;
}
/* to == 0 -> deletion */
struct range_map {
int from, to;
};
struct file_map {
char *name;
struct file_map *next;
char *new_name;
int count;
int allocated;
int last;
struct range_map ranges[];
};
struct file_map *alloc_map(char *name)
{
struct file_map *map;
map = malloc(sizeof(struct file_map) + 16 * sizeof(struct range_map));
if (!map)
Enomem();
map->name = map->new_name = strdup(name);
if (!map->name)
Enomem();
map->count = 0;
map->allocated = 16;
map->next = NULL;
map->last = 0;
return map;
}
/* this is 32bit FNV1 */
uint32_t FNV_hash(char *name)
{
uint32_t n = 0x811c9dc5;
while (*name) {
unsigned char c = *name++;
n *= 0x01000193;
n ^= c;
}
return n;
}
struct file_map *hash[1024];
int hash_map(struct file_map *map)
{
int n = FNV_hash(map->name) % 1024;
struct file_map **p = &hash[n];
while (*p) {
if (!strcmp((*p)->name, map->name))
return 0;
p = &(*p)->next;
}
*p = map;
if (map->new_name && !map->count)
return 0;
if (map->new_name && map->ranges[0].from != 1)
return 0;
return 1;
}
struct file_map *find_map(char *name)
{
static struct file_map *last = NULL;
int n = FNV_hash(name) % 1024;
struct file_map *p;
if (last && !strcmp(last->name, name))
return last;
for (p = hash[n]; p && strcmp(p->name, name); p = p->next)
;
if (p)
last = p;
return p;
}
void parse_map(char *name)
{
struct file_map *map = NULL;
struct range_map *range;
char *s;
FILE *f;
f = fopen(name, "r");
if (!f)
die("can't open map");
while (getline(f)) {
if (line[0] == 'D') {
if (map && !hash_map(map))
goto Ebadmap;
if (line[1] != ' ')
goto Ebadmap;
if (strchr(line + 2, ' '))
goto Ebadmap;
map = alloc_map(line + 2);
map->new_name = NULL;
continue;
}
if (line[0] == 'M') {
if (map && !hash_map(map))
goto Ebadmap;
if (line[1] != ' ')
goto Ebadmap;
s = strchr(line + 2, ' ');
if (!s)
goto Ebadmap;
*s++ = '\0';
if (strchr(s, ' '))
goto Ebadmap;
map = alloc_map(line + 2);
if (strcmp(line + 2, s)) {
map->new_name = strdup(s);
if (!map->new_name)
Enomem();
}
continue;
}
if (!map || !map->new_name)
goto Ebadmap;
if (map->count == map->allocated) {
int n = 2 * map->allocated;
map = realloc(map, sizeof(struct file_map) +
n * sizeof(struct range_map));
if (!map)
Enomem();
map->allocated = n;
}
range = &map->ranges[map->count++];
if (sscanf(line, "%d %d%*c", &range->from, &range->to) != 2)
goto Ebadmap;
if (range > map->ranges && range->from <= range[-1].from)
goto Ebadmap;
}
if (map && !hash_map(map))
goto Ebadmap;
fclose(f);
return;
Ebadmap:
die("bad map");
}
struct range_map *find_range(struct file_map *map, int l)
{
struct range_map *range = &map->ranges[map->last];
struct range_map *p;
if (range->from <= l) {
p = &map->ranges[map->count - 1];
if (p->from > l) {
for (p = range; p->from <= l; p++)
;
p--;
}
} else {
for (p = map->ranges; p->from <= l; p++)
;
p--;
}
map->last = p - map->ranges;
return p;
}
void mapline(void)
{
struct file_map *map;
struct range_map *range;
unsigned long l;
char *s1, *s2;
char *name;
s1 = strchr(line, ':');
if (!s1)
goto noise;
s2 = strchr(line, ' ');
if (s2 && s2 < s1)
goto noise;
l = strtoul(s1 + 1, &s2, 10);
if (s2 == s1 + 1 || *s2 != ':' || !l || l > INT_MAX)
goto noise;
*s1++ = *s2++ = '\0';
name = line;
map = find_map(line);
if (!map)
goto new;
if (!map->new_name)
goto old;
name = map->new_name;
range = find_range(map, l);
if (!range->to)
goto old;
l += range->to - range->from;
new:
printf("N:%s:%lu:%s\n", name, l, s2);
return;
old:
s1[-1] = s2[-1] = ':';
printf("O:%s\n", line);
return;
noise:
printf("%s\n", line);
}
int parse_hunk(int *l1, int *l2, int *n1, int *n2)
{
unsigned long n;
char *s, *p;
if (line[3] != '-')
return 0;
n = strtoul(line + 4, &s, 10);
if (s == line + 4 || n > INT_MAX)
return 0;
*l1 = n;
if (*s == ',') {
n = strtoul(s + 1, &p, 10);
if (p == s + 1 || n > INT_MAX)
return 0;
*n1 = n;
if (!n)
(*l1)++;
} else {
p = s;
*n1 = 1;
}
if (*p != ' ' || p[1] != '+')
return 0;
n = strtoul(p + 2, &s, 10);
if (s == p + 2 || n > INT_MAX)
return 0;
*l2 = n;
if (*s == ',') {
n = strtoul(s + 1, &p, 10);
if (p == s + 1 || n > INT_MAX)
return 0;
*n2 = n;
if (!n)
(*l2)++;
} else {
p = s;
*n2 = 1;
}
return 1;
}
void parse_diff(void)
{
int skipping = -1, suppress = 1;
char *name1 = NULL, *name2 = NULL;
int from = 1, to = 1;
int l1, l2, n1, n2;
enum cmd {
Diff, Hunk, New, Del, Copy, Rename, Junk
} cmd;
static struct { const char *s; size_t len; } pref[] = {
[Hunk] = {"@@ ", 3},
[Diff] = {"diff ", 5},
[New] = {"new file ", 9},
[Del] = {"deleted file ", 12},
[Copy] = {"copy from ", 10},
[Rename] = {"rename from ", 11},
[Junk] = {"", 0},
};
size_t len1 = strlen(prefix1), len2 = strlen(prefix2);
while (getline(stdin)) {
if (skipping > 0) {
switch (line[0]) {
case '+':
case '-':
case '\\':
continue;
}
}
for (cmd = 0; strncmp(line, pref[cmd].s, pref[cmd].len); cmd++)
;
switch (cmd) {
case Hunk:
if (skipping < 0)
goto Ediff;
if (!suppress) {
if (!skipping)
printf("M %s %s\n", name1, name2);
if (!parse_hunk(&l1, &l2, &n1, &n2))
goto Ediff;
if (l1 > from)
printf("%d %d\n", from, to);
if (n1)
printf("%d 0\n", l1);
from = l1 + n1;
to = l2 + n2;
}
skipping = 1;
break;
case Diff:
if (!suppress) {
if (!skipping)
printf("M %s %s\n", name1, name2);
printf("%d %d\n", from, to);
}
free(name1);
free(name2);
name2 = strrchr(line, ' ');
if (!name2)
goto Ediff;
*name2 = '\0';
name1 = strrchr(line, ' ');
if (!name1)
goto Ediff;
if (strncmp(name1 + 1, prefix1, len1))
goto Ediff;
if (strncmp(name2 + 1, prefix2, len2))
goto Ediff;
name1 = strdup(name1 + len1 + 1);
name2 = strdup(name2 + len2 + 1);
if (!name1 || !name2)
goto Ediff;
skipping = 0;
suppress = 0;
from = to = 1;
break;
case New:
if (skipping)
goto Ediff;
suppress = 1;
break;
case Del:
case Copy:
if (skipping)
goto Ediff;
printf("D %s\n", name2);
suppress = 1;
break;
case Rename:
if (skipping)
goto Ediff;
printf("D %s\n", name2);
break;
default:
break;
}
}
return;
Ediff:
die("odd diff");
}
int main(int argc, char **argv)
{
int skipping = 0;
size = 256;
line = malloc(size);
if (!line)
Enomem();
if (argc < 2) {
parse_diff();
} else {
parse_map(argv[1]);
while (getline(stdin))
mapline();
}
return 0;
}
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC] Add "rcs format diff" support
2006-05-14 0:12 ` Al Viro
@ 2006-05-16 20:49 ` Al Viro
0 siblings, 0 replies; 3+ messages in thread
From: Al Viro @ 2006-05-16 20:49 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Junio C Hamano, Git Mailing List, Al Viro, Davide Libenzi
Use:
diff-remap-data <dir1> <dir2> >map
or
git-remap-data <git-diff arguments> >map
will build information for remapper,
git-remap <map> <options>
will do line numbers remapping.
git-remap is a filter. It takes map as argument and, in the simplest form,
will look at the lines in stdin that have form
<filename>:<number>:<text>
If the indicated line from old tree had survived into the new one, we will
get
N:<new-filename>:<new-number>:<text>
on the output. If it hadn't, we get
O:<filename>:<number>:<text>
Lines that do not have such form are passed unchanged.
Even that is already very useful for log comparison. E.g. if old-log is
from the old tree and new-log is from the new one, we can do
git-remap map <old-log >foo
git-remap /dev/null <new-log >bar
diff -u foo bar
and have the noise due to line number changes excluded (empty map means
identity mapping, so the second line will simply slap N: on all lines of
form <filename>:<number>:<text> in new-log).
Note that it's not just for build logs; the thing is useful for sparse logs,
grep -n output, etc., etc.
Behaviour described above is the default; what _really_ happens is
that we take lines of form
<original_prefix><filename>:<number>:<text>
and replace them with
<prefix_for_new><new-filename>:<new-number>:<text>
or
<prefix_for_old><filename>:<number>:<text>
Defaults are :", "N:" and "O:" resp.; what it gives us is the ability to
do multiple remappings. IOW, we can say
diff-remap-data old-tree newer-tree > map1
diff-remap-data newer-tree current-tree > map2
git-remap -o old: map1 <old-log | git-remap -p N: -o newer: -n current: map2>foo
and get lines that didn't make it into the newer tree marked with old: and
otherwise be unchanged, ones that made it to newer, but not the current to
be marked with newer: and have the filenames/line numbers remapped and ones
that made it all the way be marked with current: and remapped all the way
to current tree.
That's quite useful when you want to carry logs for a while, basically using
them as annotated TODO ("logs" here can very well be results of grep -n with
annotations added to them). You can have all still relevant bits stay with
the locations in text and see what had fallen out.
Note on relation to git:
* git-remap, despite the name, doesn't need git to work
* diff-remap-data doesn't need git to work
* git-remap-data _does_ need it. Aside of working on revisions in
git repository instead of a couple of directory trees, it generates slightly
better map than diff-remap-data does. I.e. it manages to remap more lines -
it does notice renames.
This stuff lives on ftp.linux.org.uk/pub/people/viro/remapper/; I'm not
sure what to do with it wrt distributing - submit for inclusion into
git, or leave that sucker standalone. It can be used without git, but
OTOH having it in git would make my life easier - I wouldn't have to
think about packaging it myself ;-)
Seriously,
a) feel free to play with it; hopefully it will be useful.
b) review and comments are welcome.
c) so would any thoughts regarding the right way to distribute it.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2006-05-16 20:49 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-13 21:14 [RFC] Add "rcs format diff" support Linus Torvalds
2006-05-14 0:12 ` Al Viro
2006-05-16 20:49 ` Al Viro
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).