version 1.135, 2008/05/22 15:45:01 |
version 1.136, 2008/05/30 10:12:12 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
/* |
/* |
|
* Copyright (c) 2008 Tobias Stoeckmann <tobias@openbsd.org> |
* Copyright (c) 2006 Joris Vink <joris@openbsd.org> |
* Copyright (c) 2006 Joris Vink <joris@openbsd.org> |
* |
* |
* Permission to use, copy, modify, and distribute this software for any |
* Permission to use, copy, modify, and distribute this software for any |
|
|
diff_format = D_RCSDIFF; |
diff_format = D_RCSDIFF; |
break; |
break; |
case 'N': |
case 'N': |
|
strlcat(diffargs, " -N", sizeof(diffargs)); |
Nflag = 1; |
Nflag = 1; |
break; |
break; |
case 'p': |
case 'p': |
|
|
if (rev1 == NULL) |
if (rev1 == NULL) |
fatal("must specify at least one revision/date!"); |
fatal("must specify at least one revision/date!"); |
|
|
|
if (!argc) |
|
fatal("%s", cvs_cmd_rdiff.cmd_synopsis); |
|
|
if (!diff_format) { |
if (!diff_format) { |
strlcat(diffargs, " -c", sizeof(diffargs)); |
strlcat(diffargs, " -c", sizeof(diffargs)); |
diff_format = D_CONTEXT; |
diff_format = D_CONTEXT; |
|
|
void |
void |
cvs_diff_local(struct cvs_file *cf) |
cvs_diff_local(struct cvs_file *cf) |
{ |
{ |
RCSNUM *r1; |
|
BUF *b1; |
BUF *b1; |
int fd1, fd2; |
int fd1, fd2; |
struct stat st; |
struct stat st; |
struct timeval tv[2], tv2[2]; |
struct timeval tv[2], tv2[2]; |
char rbuf[CVS_REV_BUFSZ], *p1, *p2; |
char rbuf[CVS_REV_BUFSZ], *p1, *p2; |
|
|
r1 = NULL; |
|
b1 = NULL; |
b1 = NULL; |
|
fd1 = fd2 = -1; |
|
p1 = p2 = NULL; |
|
|
cvs_log(LP_TRACE, "cvs_diff_local(%s)", cf->file_path); |
cvs_log(LP_TRACE, "cvs_diff_local(%s)", cf->file_path); |
|
|
|
|
|
|
cvs_file_classify(cf, cvs_directory_tag); |
cvs_file_classify(cf, cvs_directory_tag); |
|
|
if (cf->file_status == FILE_LOST) { |
if (cvs_cmdop == CVS_OP_DIFF) { |
cvs_log(LP_ERR, "cannot find file %s", cf->file_path); |
if (cf->file_ent == NULL) { |
return; |
cvs_log(LP_ERR, "I know nothing about %s", |
} else if (cf->file_status == FILE_UNKNOWN) { |
cf->file_path); |
cvs_log(LP_ERR, "I know nothing about %s", cf->file_path); |
return; |
return; |
} |
} else if (cf->file_status == FILE_ADDED && Nflag == 0) { |
|
cvs_log(LP_ERR, "%s is a new entry, no comparison available", |
|
cf->file_path); |
|
return; |
|
} else if (cf->file_status == FILE_REMOVED && Nflag == 0) { |
|
cvs_log(LP_ERR, "%s was removed, no comparison available", |
|
cf->file_path); |
|
return; |
|
} else if (cf->file_status == FILE_UPTODATE && rev1 == NULL && |
|
rev2 == NULL) { |
|
return; |
|
} |
|
|
|
if (kflag) |
switch (cf->file_ent->ce_status) { |
rcs_kwexp_set(cf->file_rcs, kflag); |
case CVS_ENT_ADDED: |
|
if (Nflag == 0) { |
if (rev1 != NULL) |
cvs_log(LP_ERR, "%s is a new entry, no " |
if ((diff_rev1 = rcs_translate_tag(rev1, cf->file_rcs)) == |
"comparison available", cf->file_path); |
NULL) { |
|
if (cvs_cmdop == CVS_OP_DIFF) { |
|
cvs_log(LP_ERR, "tag %s is not in file %s", |
|
rev1, cf->file_path); |
|
return; |
return; |
} |
} |
if (force_head) { |
if (cf->fd == -1) { |
/* -f is not allowed for unknown symbols */ |
cvs_log(LP_ERR, "cannot find %s", |
diff_rev1 = rcsnum_parse(rev1); |
cf->file_path); |
if (diff_rev1 == NULL) |
return; |
fatal("no such tag %s", rev1); |
|
rcsnum_free(diff_rev1); |
|
|
|
diff_rev1 = rcsnum_alloc(); |
|
rcsnum_cpy(cf->file_rcs->rf_head, diff_rev1, 0); |
|
} |
} |
} |
break; |
|
case CVS_ENT_REMOVED: |
if (rev2 != NULL) |
if (Nflag == 0) { |
if ((diff_rev2 = rcs_translate_tag(rev2, cf->file_rcs)) == |
cvs_log(LP_ERR, "%s was removed, no " |
NULL) { |
"comparison available", cf->file_path); |
if (cvs_cmdop == CVS_OP_DIFF) { |
|
rcsnum_free(diff_rev1); |
|
cvs_log(LP_ERR, "tag %s is not in file %s", |
|
rev2, cf->file_path); |
|
return; |
return; |
} |
} |
if (force_head) { |
if (cf->file_rcs == NULL) { |
/* -f is not allowed for unknown symbols */ |
cvs_log(LP_ERR, "cannot find RCS file for %s", |
diff_rev2 = rcsnum_parse(rev2); |
cf->file_path); |
if (diff_rev2 == NULL) |
return; |
fatal("no such tag %s", rev2); |
|
rcsnum_free(diff_rev2); |
|
|
|
diff_rev2 = rcsnum_alloc(); |
|
rcsnum_cpy(cf->file_rcs->rf_head, diff_rev2, 0); |
|
} |
} |
|
break; |
|
default: |
|
if (cf->fd == -1) { |
|
cvs_log(LP_ERR, "cannot find %s", |
|
cf->file_path); |
|
return; |
|
} |
|
break; |
|
if (cf->file_rcs == NULL) { |
|
cvs_log(LP_ERR, "cannot find RCS file for %s", |
|
cf->file_path); |
|
return; |
|
} |
|
break; |
} |
} |
|
} |
|
|
if (cvs_cmdop == CVS_OP_RDIFF && diff_rev1 == NULL && diff_rev2 == NULL) |
if (cf->file_status == FILE_UPTODATE && rev1 == NULL && rev2 == NULL) |
return; |
return; |
|
|
diff_file = cf->file_path; |
if (kflag && cf->file_rcs != NULL) |
|
rcs_kwexp_set(cf->file_rcs, kflag); |
|
|
cvs_printf("Index: %s\n", cf->file_path); |
if (cf->file_rcs == NULL) |
if (cvs_cmdop == CVS_OP_DIFF) |
diff_rev1 = NULL; |
cvs_printf("%s\nRCS file: %s\n", RCS_DIFF_DIV, cf->file_rpath); |
else if (rev1 != NULL) { |
|
diff_rev1 = rcs_translate_tag(rev1, cf->file_rcs); |
|
if (diff_rev1 == NULL && cvs_cmdop == CVS_OP_DIFF) { |
|
cvs_log(LP_ERR, "tag %s not in file %s", rev1, |
|
cf->file_path); |
|
goto cleanup; |
|
} else if (diff_rev1 == NULL && cvs_cmdop == CVS_OP_RDIFF && |
|
force_head) { |
|
/* -f is not allowed for unknown symbols */ |
|
if ((diff_rev1 = rcsnum_parse(rev1)) == NULL) |
|
fatal("no such tag %s", rev1); |
|
rcsnum_free(diff_rev1); |
|
|
(void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir); |
diff_rev1 = cf->file_rcs->rf_head; |
(void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); |
} |
|
} else if (cvs_cmdop == CVS_OP_DIFF) { |
if (cf->file_status != FILE_ADDED) { |
if (cf->file_ent->ce_status == CVS_ENT_ADDED) |
if (diff_rev1 != NULL) |
diff_rev1 = NULL; |
r1 = diff_rev1; |
|
else if (cf->file_ent != NULL) |
|
r1 = cf->file_ent->ce_rev; |
|
else |
else |
r1 = NULL; |
diff_rev1 = cf->file_ent->ce_rev; |
|
} |
|
|
diff_rev1 = r1; |
if (cf->file_rcs == NULL) |
|
diff_rev2 = NULL; |
|
else if (rev2 != NULL) { |
|
diff_rev2 = rcs_translate_tag(rev2, cf->file_rcs); |
|
if (diff_rev2 == NULL && cvs_cmdop == CVS_OP_DIFF) { |
|
cvs_log(LP_ERR, "tag %s not in file %s", rev2, |
|
cf->file_path); |
|
goto cleanup; |
|
} else if (diff_rev2 == NULL && cvs_cmdop == CVS_OP_RDIFF && |
|
force_head) { |
|
/* -f is not allowed for unknown symbols */ |
|
if ((diff_rev2 = rcsnum_parse(rev2)) == NULL) |
|
fatal("no such tag %s", rev2); |
|
rcsnum_free(diff_rev2); |
|
|
if (diff_rev1 != NULL) { |
diff_rev2 = cf->file_rcs->rf_head; |
(void)rcsnum_tostr(r1, rbuf, sizeof(rbuf)); |
} |
|
} else if (cvs_cmdop == CVS_OP_RDIFF) |
|
diff_rev2 = cf->file_rcs->rf_head; |
|
else if (cf->file_ent->ce_status == CVS_ENT_REMOVED) |
|
diff_rev2 = NULL; |
|
|
tv[0].tv_sec = rcs_rev_getdate(cf->file_rcs, r1); |
if (diff_rev1 != NULL && diff_rev2 != NULL && |
tv[0].tv_usec = 0; |
rcsnum_cmp(diff_rev1, diff_rev2, 0) == 0) |
tv[1] = tv[0]; |
goto cleanup; |
|
|
if (cvs_cmdop == CVS_OP_DIFF) |
switch (cvs_cmdop) { |
cvs_printf("retrieving revision %s\n", rbuf); |
case CVS_OP_DIFF: |
fd1 = rcs_rev_write_stmp(cf->file_rcs, r1, p1, 0); |
if (cf->file_status == FILE_UPTODATE && |
if (futimes(fd1, tv) == -1) |
rcsnum_cmp(diff_rev1, cf->file_rcsrev, 0) == 0) |
fatal("cvs_diff_local: utimes failed"); |
goto cleanup; |
|
break; |
|
case CVS_OP_RDIFF: |
|
if (diff_rev1 == NULL && diff_rev2 == NULL) |
|
goto cleanup; |
|
break; |
|
} |
|
|
|
cvs_printf("Index: %s\n", cf->file_path); |
|
if (cvs_cmdop == CVS_OP_DIFF) |
|
cvs_printf("%s\nRCS file: %s\n", RCS_DIFF_DIV, |
|
cf->file_rcs != NULL ? cf->file_rpath : cf->file_path); |
|
|
|
if (diff_rev1 != NULL) { |
|
if (cvs_cmdop == CVS_OP_DIFF && diff_rev1 != NULL) { |
|
(void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf)); |
|
cvs_printf("retrieving revision %s\n", rbuf); |
} |
} |
|
|
|
tv[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev1); |
|
tv[0].tv_usec = 0; |
|
tv[1] = tv[0]; |
|
|
|
(void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir); |
|
fd1 = rcs_rev_write_stmp(cf->file_rcs, diff_rev1, p1, 0); |
|
if (futimes(fd1, tv) == -1) |
|
fatal("cvs_diff_local: utimes failed"); |
} |
} |
|
|
if (diff_rev2 != NULL && cf->file_status != FILE_ADDED && |
if (diff_rev2 != NULL) { |
cf->file_status != FILE_REMOVED) { |
if (cvs_cmdop == CVS_OP_DIFF && rev2 != NULL) { |
(void)rcsnum_tostr(diff_rev2, rbuf, sizeof(rbuf)); |
(void)rcsnum_tostr(diff_rev2, rbuf, sizeof(rbuf)); |
|
cvs_printf("retrieving revision %s\n", rbuf); |
|
} |
|
|
tv2[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev2); |
tv2[0].tv_sec = rcs_rev_getdate(cf->file_rcs, diff_rev2); |
tv2[0].tv_usec = 0; |
tv2[0].tv_usec = 0; |
tv2[1] = tv2[0]; |
tv2[1] = tv2[0]; |
|
|
if (cvs_cmdop == CVS_OP_DIFF) |
(void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); |
cvs_printf("retrieving revision %s\n", rbuf); |
|
fd2 = rcs_rev_write_stmp(cf->file_rcs, diff_rev2, p2, 0); |
fd2 = rcs_rev_write_stmp(cf->file_rcs, diff_rev2, p2, 0); |
if (futimes(fd2, tv2) == -1) |
if (futimes(fd2, tv2) == -1) |
fatal("cvs_diff_local: utimes failed"); |
fatal("cvs_diff_local: utimes failed"); |
} else if (cf->file_status != FILE_REMOVED) { |
} else if (cvs_cmdop == CVS_OP_DIFF && cf->fd != -1 && |
if (cvs_cmdop == CVS_OP_RDIFF || (cvs_server_active == 1 && |
cf->file_ent->ce_status != CVS_ENT_REMOVED) { |
cf->file_status != FILE_MODIFIED)) { |
if (fstat(cf->fd, &st) == -1) |
if (diff_rev2 != NULL) { |
fatal("fstat failed %s", strerror(errno)); |
tv2[0].tv_sec = rcs_rev_getdate(cf->file_rcs, |
b1 = cvs_buf_load_fd(cf->fd); |
cf->file_rcsrev); |
|
tv2[0].tv_usec = 0; |
|
tv2[1] = tv2[0]; |
|
|
|
fd2 = rcs_rev_write_stmp(cf->file_rcs, |
tv2[0].tv_sec = st.st_mtime; |
cf->file_rcsrev, p2, 0); |
tv2[0].tv_usec = 0; |
if (futimes(fd2, tv2) == -1) |
tv2[1] = tv2[0]; |
fatal("cvs_diff_local: utimes failed"); |
|
} |
|
} else { |
|
if (fstat(cf->fd, &st) == -1) |
|
fatal("fstat failed %s", strerror(errno)); |
|
b1 = cvs_buf_load_fd(cf->fd); |
|
|
|
tv2[0].tv_sec = st.st_mtime; |
(void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); |
tv2[0].tv_usec = 0; |
fd2 = cvs_buf_write_stmp(b1, p2, tv2); |
tv2[1] = tv2[0]; |
cvs_buf_free(b1); |
|
|
fd2 = cvs_buf_write_stmp(b1, p2, tv2); |
|
cvs_buf_free(b1); |
|
} |
|
} |
} |
|
|
if (cvs_cmdop == CVS_OP_DIFF) { |
switch (cvs_cmdop) { |
|
case CVS_OP_DIFF: |
cvs_printf("%s", diffargs); |
cvs_printf("%s", diffargs); |
|
|
if (cf->file_status != FILE_ADDED) { |
if (rev1 != NULL && diff_rev1 != NULL) { |
(void)rcsnum_tostr(r1, rbuf, sizeof(rbuf)); |
(void)rcsnum_tostr(diff_rev1, rbuf, sizeof(rbuf)); |
cvs_printf(" -r%s", rbuf); |
cvs_printf(" -r%s", rbuf); |
|
|
if (diff_rev2 != NULL) { |
if (rev2 != NULL && diff_rev2 != NULL) { |
(void)rcsnum_tostr(diff_rev2, rbuf, |
(void)rcsnum_tostr(diff_rev2, rbuf, |
sizeof(rbuf)); |
sizeof(rbuf)); |
cvs_printf(" -r%s", rbuf); |
cvs_printf(" -r%s", rbuf); |
|
|
} |
} |
|
|
if (diff_rev2 == NULL) |
if (diff_rev2 == NULL) |
cvs_printf(" %s", cf->file_name); |
cvs_printf(" %s", cf->file_path); |
cvs_printf("\n"); |
cvs_printf("\n"); |
} else { |
break; |
|
case CVS_OP_RDIFF: |
cvs_printf("diff "); |
cvs_printf("diff "); |
switch (diff_format) { |
switch (diff_format) { |
case D_CONTEXT: |
case D_CONTEXT: |
|
|
cf->file_rcs->rf_head, rbuf, sizeof(rbuf)); |
cf->file_rcs->rf_head, rbuf, sizeof(rbuf)); |
cvs_printf("%s:%s\n", cf->file_path, rbuf); |
cvs_printf("%s:%s\n", cf->file_path, rbuf); |
} |
} |
|
break; |
} |
} |
|
|
if (cf->file_status == FILE_ADDED || |
if (fd1 == -1) { |
(cvs_cmdop == CVS_OP_RDIFF && diff_rev1 == NULL)) { |
if ((fd1 = open(CVS_PATH_DEVNULL, O_RDONLY, 0)) == -1) |
xfree(p1); |
fatal("cannot open %s", CVS_PATH_DEVNULL); |
close(fd1); |
|
(void)xasprintf(&p1, "%s", CVS_PATH_DEVNULL); |
|
if ((fd1 = open(p1, O_RDONLY)) == -1) |
|
fatal("cvs_diff_local: cannot open %s", |
|
CVS_PATH_DEVNULL); |
|
} else if (cf->file_status == FILE_REMOVED || |
|
(cvs_cmdop == CVS_OP_RDIFF && diff_rev2 == NULL)) { |
|
xfree(p2); |
|
close(fd2); |
|
(void)xasprintf(&p2, "%s", CVS_PATH_DEVNULL); |
|
if ((fd2 = open(p2, O_RDONLY)) == -1) |
|
fatal("cvs_diff_local: cannot open %s", |
|
CVS_PATH_DEVNULL); |
|
} |
} |
|
if (fd2 == -1) { |
|
if ((fd2 = open(CVS_PATH_DEVNULL, O_RDONLY, 0)) == -1) |
|
fatal("cannot open %s", CVS_PATH_DEVNULL); |
|
} |
|
|
if (cvs_diffreg(p1, p2, fd1, fd2, NULL) == D_ERROR) |
if (cvs_diffreg(p1 != NULL ? cf->file_path : CVS_PATH_DEVNULL, |
|
p2 != NULL ? cf->file_path : CVS_PATH_DEVNULL, fd1, fd2, NULL) |
|
== D_ERROR) |
fatal("cvs_diff_local: failed to get RCS patch"); |
fatal("cvs_diff_local: failed to get RCS patch"); |
|
|
close(fd1); |
close(fd1); |
|
|
if (p2 != NULL) |
if (p2 != NULL) |
xfree(p2); |
xfree(p2); |
|
|
if (diff_rev1 != NULL && diff_rev1 != cf->file_rcs->rf_head && |
cleanup: |
(cf->file_ent != NULL && diff_rev1 != cf->file_ent->ce_rev)) |
if (diff_rev1 != NULL && |
rcsnum_free(diff_rev1); |
(cf->file_rcs == NULL || diff_rev1 != cf->file_rcs->rf_head) && |
if (diff_rev2 != NULL) |
(cf->file_ent == NULL || diff_rev1 != cf->file_ent->ce_rev)) |
rcsnum_free(diff_rev2); |
xfree(diff_rev1); |
|
diff_rev1 = NULL; |
|
|
diff_rev1 = diff_rev2 = NULL; |
if (diff_rev2 != NULL && |
|
(cf->file_rcs == NULL || diff_rev2 != cf->file_rcs->rf_head)) |
|
xfree(diff_rev2); |
|
diff_rev2 = NULL; |
} |
} |