version 1.57, 2005/11/08 15:58:38 |
version 1.58, 2005/11/16 19:06:41 |
|
|
#include "diff.h" |
#include "diff.h" |
#include "rcsprog.h" |
#include "rcsprog.h" |
|
|
|
#define CI_OPTSTRING "d::f::i::j::k:l::m:M::N:n:qr::s:u::Vw:" |
#define DATE_NOW -1 |
#define DATE_NOW -1 |
#define DATE_MTIME -2 |
#define DATE_MTIME -2 |
|
|
static char * checkin_diff_file(RCSFILE *, RCSNUM *, const char *); |
#define LOG_INIT "Initial revision" |
|
#define LOG_PROMPT "enter log message, terminated with a single '.' " \ |
|
"or end of file:\n>> " |
|
#define DESC_PROMPT "enter description, terminated with single '.' " \ |
|
"or end of file:\nNOTE: This is NOT the log message!\n" |
|
|
|
struct checkin_params { |
|
int flags, openflags; |
|
mode_t fmode; |
|
time_t date; |
|
RCSFILE *file; |
|
RCSNUM *frev, *newrev; |
|
char fpath[MAXPATHLEN], *rcs_msg, *username, *deltatext, *filename; |
|
const char *symbol, *state; |
|
}; |
|
|
|
static int checkin_attach_symbol(struct checkin_params *pb); |
|
static int checkin_checklock(struct checkin_params *pb); |
|
static char * checkin_diff_file(struct checkin_params *); |
|
static char * checkin_getdesc(void); |
|
static char * checkin_getinput(const char *); |
static char * checkin_getlogmsg(RCSNUM *, RCSNUM *); |
static char * checkin_getlogmsg(RCSNUM *, RCSNUM *); |
|
static void checkin_init(struct checkin_params *); |
|
static void checkin_revert(struct checkin_params *pb); |
|
|
void |
void |
checkin_usage(void) |
checkin_usage(void) |
{ |
{ |
fprintf(stderr, |
fprintf(stderr, |
"usage: ci [-jMNqV] [-d[date]] [-f[rev]] [-kmode] [-l[rev]]\n" |
"usage: ci [-MNqV] [-d[date]] [-f[rev]] [-i[rev]] [-j[rev]]\n" |
" [-M[rev]] [-mmsg] [-Nsymbol] [-nsymbol] [-r[rev]]\n" |
" [-kmode] [-l[rev]] [-M[rev]] [-mmsg] [-Nsymbol]\n" |
" [-sstate] [-u[rev]] [-wusername] file ...\n"); |
" [-nsymbol] [-r[rev]] [-sstate] [-u[rev]] [-wusername]\n" |
|
" file ...\n"); |
} |
} |
|
|
|
|
|
|
/* |
/* |
* checkin_main() |
* checkin_main() |
* |
* |
|
|
int |
int |
checkin_main(int argc, char **argv) |
checkin_main(int argc, char **argv) |
{ |
{ |
int found, notlocked, ret, status; |
int i, ch, status; |
int i, ch, flags; |
char *filec; |
mode_t fmode; |
struct stat sb; |
time_t date; |
struct checkin_params pb; |
RCSFILE *file; |
|
RCSNUM *frev, *newrev; |
|
char fpath[MAXPATHLEN]; |
|
char *rcs_msg, *filec, *deltatext, *username, rbuf[16]; |
|
const char *symbol, *state; |
|
struct rcs_lock *lkp; |
|
BUF *bp; |
BUF *bp; |
|
|
date = DATE_NOW; |
pb.date = DATE_NOW; |
file = NULL; |
pb.file = NULL; |
rcs_msg = username = NULL; |
pb.rcs_msg = pb.username = NULL; |
state = symbol = NULL; |
pb.state = pb.symbol = NULL; |
newrev = NULL; |
pb.newrev = NULL; |
fmode = flags = status = 0; |
pb.fmode = pb.flags = status = 0; |
|
|
flags |= INTERACTIVE; |
pb.flags = INTERACTIVE; |
|
pb.openflags = RCS_RDWR|RCS_CREATE; |
|
|
while ((ch = rcs_getopt(argc, argv, "d::f::j:k:l::m:M::N:n:qr::s:u::Vw:")) != -1) { |
while ((ch = rcs_getopt(argc, argv, CI_OPTSTRING)) != -1) { |
switch (ch) { |
switch (ch) { |
case 'd': |
case 'd': |
if (rcs_optarg == NULL) |
if (rcs_optarg == NULL) |
date = DATE_MTIME; |
pb.date = DATE_MTIME; |
else if ((date = cvs_date_parse(rcs_optarg)) <= 0) { |
else if ((pb.date = cvs_date_parse(rcs_optarg)) <= 0) { |
cvs_log(LP_ERR, "invalide date"); |
cvs_log(LP_ERR, "invalide date"); |
exit(1); |
exit(1); |
} |
} |
break; |
break; |
case 'f': |
case 'f': |
rcs_set_rev(rcs_optarg, &newrev); |
rcs_set_rev(rcs_optarg, &pb.newrev); |
flags |= FORCE; |
pb.flags |= FORCE; |
break; |
break; |
case 'h': |
case 'h': |
(usage)(); |
(usage)(); |
exit(0); |
exit(0); |
|
case 'i': |
|
rcs_set_rev(rcs_optarg, &pb.newrev); |
|
pb.openflags |= RCS_CREATE; |
|
break; |
|
case 'j': |
|
rcs_set_rev(rcs_optarg, &pb.newrev); |
|
pb.openflags &= ~RCS_CREATE; |
|
break; |
case 'l': |
case 'l': |
rcs_set_rev(rcs_optarg, &newrev); |
rcs_set_rev(rcs_optarg, &pb.newrev); |
flags |= CO_LOCK; |
pb.flags |= CO_LOCK; |
break; |
break; |
case 'M': |
case 'M': |
rcs_set_rev(rcs_optarg, &newrev); |
rcs_set_rev(rcs_optarg, &pb.newrev); |
flags |= CO_REVDATE; |
pb.flags |= CO_REVDATE; |
break; |
break; |
case 'm': |
case 'm': |
rcs_msg = rcs_optarg; |
pb.rcs_msg = rcs_optarg; |
flags &= ~INTERACTIVE; |
if (pb.rcs_msg == NULL) { |
|
cvs_log(LP_ERR, |
|
"missing message for -m option"); |
|
exit(1); |
|
} |
|
pb.flags &= ~INTERACTIVE; |
break; |
break; |
case 'N': |
case 'N': |
if ((symbol = strdup(rcs_optarg)) == NULL) { |
if ((pb.symbol = strdup(rcs_optarg)) == NULL) { |
cvs_log(LP_ERRNO, "out of memory"); |
cvs_log(LP_ERRNO, "out of memory"); |
exit(1); |
exit(1); |
} |
} |
if (rcs_sym_check(symbol) != 1) { |
if (rcs_sym_check(pb.symbol) != 1) { |
cvs_log(LP_ERR, "invalid symbol `%s'", symbol); |
cvs_log(LP_ERR, "invalid symbol `%s'", |
|
pb.symbol); |
exit(1); |
exit(1); |
} |
} |
flags |= CI_SYMFORCE; |
pb.flags |= CI_SYMFORCE; |
break; |
break; |
case 'n': |
case 'n': |
if ((symbol = strdup(rcs_optarg)) == NULL) { |
if ((pb.symbol = strdup(rcs_optarg)) == NULL) { |
cvs_log(LP_ERRNO, "out of memory"); |
cvs_log(LP_ERRNO, "out of memory"); |
exit(1); |
exit(1); |
} |
} |
if (rcs_sym_check(symbol) != 1) { |
if (rcs_sym_check(pb.symbol) != 1) { |
cvs_log(LP_ERR, "invalid symbol `%s'", symbol); |
cvs_log(LP_ERR, "invalid symbol `%s'", |
|
pb.symbol); |
exit(1); |
exit(1); |
} |
} |
break; |
break; |
|
|
verbose = 0; |
verbose = 0; |
break; |
break; |
case 'r': |
case 'r': |
rcs_set_rev(rcs_optarg, &newrev); |
rcs_set_rev(rcs_optarg, &pb.newrev); |
flags |= CI_DEFAULT; |
pb.flags |= CI_DEFAULT; |
break; |
break; |
case 's': |
case 's': |
state = rcs_optarg; |
pb.state = rcs_optarg; |
if (rcs_state_check(state) < 0) { |
if (rcs_state_check(pb.state) < 0) { |
cvs_log(LP_ERR, "invalid state `%s'", state); |
cvs_log(LP_ERR, "invalid state `%s'", |
|
pb.state); |
exit(1); |
exit(1); |
} |
} |
break; |
break; |
case 'u': |
case 'u': |
rcs_set_rev(rcs_optarg, &newrev); |
rcs_set_rev(rcs_optarg, &pb.newrev); |
flags |= CO_UNLOCK; |
pb.flags |= CO_UNLOCK; |
break; |
break; |
case 'V': |
case 'V': |
printf("%s\n", rcs_version); |
printf("%s\n", rcs_version); |
exit(0); |
exit(0); |
case 'w': |
case 'w': |
username = rcs_optarg; |
pb.username = rcs_optarg; |
break; |
break; |
default: |
default: |
(usage)(); |
(usage)(); |
|
|
exit(1); |
exit(1); |
} |
} |
|
|
if ((username == NULL) && (username = getlogin()) == NULL) { |
if ((pb.username == NULL) && (pb.username = getlogin()) == NULL) { |
cvs_log(LP_ERRNO, "failed to get username"); |
cvs_log(LP_ERRNO, "failed to get username"); |
exit(1); |
exit(1); |
} |
} |
|
|
|
|
for (i = 0; i < argc; i++) { |
for (i = 0; i < argc; i++) { |
if (rcs_statfile(argv[i], fpath, sizeof(fpath)) < 0) |
pb.filename = argv[i]; |
|
if (rcs_statfile(pb.filename, pb.fpath, sizeof(pb.fpath)) < 0) |
continue; |
continue; |
|
|
file = rcs_open(fpath, RCS_RDWR, fmode); |
/* |
if (file == NULL) { |
* Test for existence of ,v file. If we are expected to |
cvs_log(LP_ERR, "failed to open rcsfile '%s'", fpath); |
* create one, set NEWFILE flag. |
|
*/ |
|
if ((pb.openflags & RCS_CREATE) && (stat(pb.fpath, &sb) < 0)) |
|
pb.flags |= NEWFILE; |
|
else |
|
pb.openflags &= ~RCS_CREATE; |
|
|
|
pb.file = rcs_open(pb.fpath, pb.openflags, pb.fmode); |
|
|
|
if (pb.file == NULL) { |
|
cvs_log(LP_ERR, "failed to open rcsfile '%s'", pb.fpath); |
exit(1); |
exit(1); |
} |
} |
|
|
frev = file->rf_head; |
|
|
|
if (verbose == 1) |
if (verbose == 1) |
printf("%s <-- %s\n", fpath, argv[i]); |
printf("%s <-- %s\n", pb.fpath, pb.filename); |
|
|
|
pb.frev = pb.file->rf_head; |
|
|
/* |
/* |
* If revision passed on command line is less than HEAD, bail. |
* If revision passed on command line is less than HEAD, bail. |
*/ |
*/ |
if ((newrev != NULL) && (rcsnum_cmp(newrev, frev, 0) > 0)) { |
if ((pb.newrev != NULL) |
|
&& (rcsnum_cmp(pb.newrev, pb.frev, 0) > 0)) { |
cvs_log(LP_ERR, "revision is too low!"); |
cvs_log(LP_ERR, "revision is too low!"); |
status = 1; |
status = 1; |
rcs_close(file); |
rcs_close(pb.file); |
continue; |
continue; |
} |
} |
|
|
|
|
* Load file contents |
* Load file contents |
*/ |
*/ |
if ((bp = cvs_buf_load(argv[i], BUF_AUTOEXT)) == NULL) { |
if ((bp = cvs_buf_load(argv[i], BUF_AUTOEXT)) == NULL) { |
cvs_log(LP_ERR, "failed to load '%s'", argv[i]); |
cvs_log(LP_ERR, "failed to load '%s'", pb.filename); |
exit(1); |
exit(1); |
} |
} |
|
|
|
|
/* |
/* |
* Get RCS patch |
* Get RCS patch |
*/ |
*/ |
if ((deltatext = checkin_diff_file(file, frev, argv[i])) == NULL) { |
if ((pb.deltatext = checkin_diff_file(&pb)) == NULL) { |
cvs_log(LP_ERR, "failed to get diff"); |
cvs_log(LP_ERR, "failed to get diff"); |
exit(1); |
exit(1); |
} |
} |
|
|
/* |
/* |
* If -f is not specified and there are no differences, tell the |
* If -f is not specified and there are no differences, tell |
* user and revert to latest version. |
* the user and revert to latest version. |
*/ |
*/ |
if ((flags & FORCE) && (strlen(deltatext) < 1)) { |
if (!(pb.flags & FORCE) && (strlen(pb.deltatext) < 1)) { |
rcsnum_tostr(frev, rbuf, sizeof(rbuf)); |
checkin_revert(&pb); |
cvs_log(LP_WARN, |
|
"file is unchanged; reverting to previous revision %s", |
|
rbuf); |
|
(void)unlink(argv[i]); |
|
if ((flags & CO_LOCK) || (flags & CO_UNLOCK)) |
|
checkout_rev(file, frev, argv[i], flags, |
|
username); |
|
rcs_lock_remove(file, frev); |
|
rcs_close(file); |
|
if (verbose == 1) |
|
printf("done\n"); |
|
continue; |
continue; |
} |
} |
|
|
|
|
* Check for a lock belonging to this user. If none, |
* Check for a lock belonging to this user. If none, |
* abort check-in. |
* abort check-in. |
*/ |
*/ |
found = 0; |
if (checkin_checklock(&pb) < 0) { |
notlocked = 1; |
|
if (!TAILQ_EMPTY(&(file->rf_locks))) { |
|
TAILQ_FOREACH(lkp, &(file->rf_locks), rl_list) { |
|
if (!strcmp(lkp->rl_name, username)) |
|
notlocked = 0; |
|
|
|
if (!strcmp(lkp->rl_name, username) && |
|
!rcsnum_cmp(lkp->rl_num, frev, 0)) { |
|
found = 1; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
if ((found == 0) && (notlocked == 0)) { |
|
cvs_log(LP_ERR, "no locks set for '%s'", username); |
|
status = 1; |
status = 1; |
rcs_close(file); |
|
continue; |
continue; |
} |
} |
|
|
/* |
/* |
* If no log message specified, get it interactively. |
* If no log message specified, get it interactively. |
*/ |
*/ |
if (rcs_msg == NULL) |
if (pb.flags & INTERACTIVE) |
rcs_msg = checkin_getlogmsg(frev, newrev); |
pb.rcs_msg = checkin_getlogmsg(pb.frev, pb.newrev); |
|
|
/* |
/* |
* Remove the lock |
* Remove the lock |
*/ |
*/ |
if (rcs_lock_remove(file, frev) < 0) { |
if (rcs_lock_remove(pb.file, pb.frev) < 0) { |
if (rcs_errno != RCS_ERR_NOENT) |
if (rcs_errno != RCS_ERR_NOENT) |
cvs_log(LP_WARN, "failed to remove lock"); |
cvs_log(LP_WARN, "failed to remove lock"); |
} |
} |
|
|
/* |
/* |
* Current head revision gets the RCS patch as rd_text |
* Current head revision gets the RCS patch as rd_text |
*/ |
*/ |
if (rcs_deltatext_set(file, frev, deltatext) == -1) { |
if (rcs_deltatext_set(pb.file, pb.frev, pb.deltatext) == -1) { |
cvs_log(LP_ERR, |
cvs_log(LP_ERR, |
"failed to set new rd_text for head rev"); |
"failed to set new rd_text for head rev"); |
exit (1); |
exit (1); |
} |
} |
|
|
/* |
/* |
* Set the date of the revision to be the last modification time |
* Set the date of the revision to be the last modification |
* of the working file if -d is specified without an argument. |
* time of the working file if -d has no argument. |
*/ |
*/ |
if (date == DATE_MTIME) { |
if (pb.date == DATE_MTIME) { |
struct stat sb; |
if (stat(pb.filename, &sb) != 0) { |
if (stat(argv[i], &sb) != 0) { |
|
cvs_log(LP_ERRNO, "failed to stat: `%s'", |
cvs_log(LP_ERRNO, "failed to stat: `%s'", |
argv[i]); |
pb.filename); |
rcs_close(file); |
rcs_close(pb.file); |
continue; |
continue; |
} |
} |
date = (time_t)sb.st_mtimespec.tv_sec; |
pb.date = (time_t)sb.st_mtimespec.tv_sec; |
} |
} |
|
|
/* |
/* |
* Now add our new revision |
* Now add our new revision |
*/ |
*/ |
if (rcs_rev_add(file, (newrev == NULL ? RCS_HEAD_REV : newrev), |
if (rcs_rev_add(pb.file, |
rcs_msg, date, username) != 0) { |
(pb.newrev == NULL ? RCS_HEAD_REV : pb.newrev), |
|
pb.rcs_msg, pb.date, pb.username) != 0) { |
cvs_log(LP_ERR, "failed to add new revision"); |
cvs_log(LP_ERR, "failed to add new revision"); |
exit(1); |
exit(1); |
} |
} |
|
|
* If we are checking in to a non-default (ie user-specified) |
* If we are checking in to a non-default (ie user-specified) |
* revision, set head to this revision. |
* revision, set head to this revision. |
*/ |
*/ |
if (newrev != NULL) |
if (pb.newrev != NULL) |
rcs_head_set(file, newrev); |
rcs_head_set(pb.file, pb.newrev); |
else |
else |
newrev = file->rf_head; |
pb.newrev = pb.file->rf_head; |
|
|
/* |
/* |
* New head revision has to contain entire file; |
* New head revision has to contain entire file; |
*/ |
*/ |
if (rcs_deltatext_set(file, frev, filec) == -1) { |
if (rcs_deltatext_set(pb.file, pb.frev, filec) == -1) { |
cvs_log(LP_ERR, "failed to set new head revision"); |
cvs_log(LP_ERR, "failed to set new head revision"); |
exit(1); |
exit(1); |
} |
} |
|
|
/* |
/* |
* Attach a symbolic name to this revision if specified. |
* Attach a symbolic name to this revision if specified. |
*/ |
*/ |
if (symbol != NULL) { |
if (pb.symbol != NULL |
if (verbose == 1) |
&& (checkin_attach_symbol(&pb) < 0)) { |
printf("symbol: %s\n", symbol); |
status = 1; |
if (flags & CI_SYMFORCE) |
continue; |
rcs_sym_remove(file, symbol); |
|
if ((ret = rcs_sym_add(file, symbol, newrev) == -1) |
|
&& (rcs_errno == RCS_ERR_DUPENT)) { |
|
rcsnum_tostr(rcs_sym_getrev(file, symbol), |
|
rbuf, sizeof(rbuf)); |
|
cvs_log(LP_ERR, |
|
"symbolic name %s already bound to %s", |
|
symbol, rbuf); |
|
status = 1; |
|
rcs_close(file); |
|
continue; |
|
} else if (ret == -1) { |
|
cvs_log(LP_ERR, "problem adding symbol: %s", |
|
symbol); |
|
status = 1; |
|
rcs_close(file); |
|
continue; |
|
} |
|
} |
} |
|
|
/* |
/* |
* Set the state of this revision if specified. |
* Set the state of this revision if specified. |
*/ |
*/ |
if (state != NULL) |
if (pb.state != NULL) |
(void)rcs_state_set(file, newrev, state); |
(void)rcs_state_set(pb.file, pb.newrev, pb.state); |
|
|
free(deltatext); |
free(pb.deltatext); |
free(filec); |
free(filec); |
(void)unlink(argv[i]); |
(void)unlink(pb.filename); |
|
|
/* |
/* |
* Do checkout if -u or -l are specified. |
* Do checkout if -u or -l are specified. |
*/ |
*/ |
if (((flags & CO_LOCK) || (flags & CO_UNLOCK)) |
if (((pb.flags & CO_LOCK) || (pb.flags & CO_UNLOCK)) |
&& !(flags & CI_DEFAULT)) |
&& !(pb.flags & CI_DEFAULT)) |
checkout_rev(file, newrev, argv[i], flags, username); |
checkout_rev(pb.file, pb.newrev, pb.filename, pb.flags, |
|
pb.username); |
|
|
/* File will NOW be synced */ |
/* File will NOW be synced */ |
rcs_close(file); |
rcs_close(pb.file); |
|
|
if (flags & INTERACTIVE) { |
if (pb.flags & INTERACTIVE) { |
free(rcs_msg); |
free(pb.rcs_msg); |
rcs_msg = NULL; |
pb.rcs_msg = NULL; |
} |
} |
} |
} |
|
|
|
|
} |
} |
|
|
static char * |
static char * |
checkin_diff_file(RCSFILE *rfp, RCSNUM *rev, const char *filename) |
checkin_diff_file(struct checkin_params *pb) |
{ |
{ |
char path1[MAXPATHLEN], path2[MAXPATHLEN]; |
char path1[MAXPATHLEN], path2[MAXPATHLEN]; |
BUF *b1, *b2, *b3; |
BUF *b1, *b2, *b3; |
char rbuf[64], *deltatext; |
char rbuf[64], *deltatext; |
|
|
rcsnum_tostr(rev, rbuf, sizeof(rbuf)); |
rcsnum_tostr(pb->frev, rbuf, sizeof(rbuf)); |
|
|
if ((b1 = cvs_buf_load(filename, BUF_AUTOEXT)) == NULL) { |
if ((b1 = cvs_buf_load(pb->filename, BUF_AUTOEXT)) == NULL) { |
cvs_log(LP_ERR, "failed to load file: '%s'", filename); |
cvs_log(LP_ERR, "failed to load file: '%s'", pb->filename); |
return (NULL); |
return (NULL); |
} |
} |
|
|
if ((b2 = rcs_getrev(rfp, rev)) == NULL) { |
if ((b2 = rcs_getrev(pb->file, pb->frev)) == NULL) { |
cvs_log(LP_ERR, "failed to load revision"); |
cvs_log(LP_ERR, "failed to load revision"); |
cvs_buf_free(b1); |
cvs_buf_free(b1); |
return (NULL); |
return (NULL); |
|
|
static char * |
static char * |
checkin_getlogmsg(RCSNUM *rev, RCSNUM *rev2) |
checkin_getlogmsg(RCSNUM *rev, RCSNUM *rev2) |
{ |
{ |
char *rcs_msg, buf[128], nrev[16], prev[16]; |
char *rcs_msg, nrev[16], prev[16]; |
BUF *logbuf; |
|
RCSNUM *tmprev; |
RCSNUM *tmprev; |
|
|
rcs_msg = NULL; |
rcs_msg = NULL; |
|
|
rcsnum_tostr(rev2, nrev, sizeof(nrev)); |
rcsnum_tostr(rev2, nrev, sizeof(nrev)); |
rcsnum_free(tmprev); |
rcsnum_free(tmprev); |
|
|
if ((logbuf = cvs_buf_alloc((size_t)64, BUF_AUTOEXT)) == NULL) { |
|
cvs_log(LP_ERR, "failed to allocate log buffer"); |
|
return (NULL); |
|
} |
|
|
|
if (verbose == 1) |
if (verbose == 1) |
printf("new revision: %s; previous revision: %s\n", nrev, |
printf("new revision: %s; previous revision: %s\n", nrev, |
prev); |
prev); |
printf("enter log message, terminated with single " |
|
"'.' or end of file:\n"); |
|
printf(">> "); |
|
|
|
|
rcs_msg = checkin_getinput(LOG_PROMPT); |
|
return (rcs_msg); |
|
} |
|
|
|
|
|
/* |
|
* checkin_getdesc() |
|
* |
|
* Get file description interactively. |
|
* Returns NULL on failure. |
|
*/ |
|
static char * |
|
checkin_getdesc() |
|
{ |
|
char *description; |
|
|
|
description = checkin_getinput(DESC_PROMPT); |
|
return (description); |
|
} |
|
|
|
/* |
|
* checkin_getinput() |
|
* |
|
* Get some input from the user. |
|
*/ |
|
static char * |
|
checkin_getinput(const char *prompt) |
|
{ |
|
BUF *inputbuf; |
|
char *input, buf[128]; |
|
|
|
if ((inputbuf = cvs_buf_alloc((size_t)64, BUF_AUTOEXT)) == NULL) { |
|
cvs_log(LP_ERR, "failed to allocate input buffer"); |
|
return (NULL); |
|
} |
|
|
|
printf(prompt); |
for (;;) { |
for (;;) { |
fgets(buf, (int)sizeof(buf), stdin); |
fgets(buf, (int)sizeof(buf), stdin); |
if (feof(stdin) || ferror(stdin) || buf[0] == '.') |
if (feof(stdin) || ferror(stdin) || buf[0] == '.') |
break; |
break; |
cvs_buf_append(logbuf, buf, strlen(buf)); |
cvs_buf_append(inputbuf, buf, strlen(buf)); |
printf(">> "); |
printf(">> "); |
} |
} |
|
|
cvs_buf_putc(logbuf, '\0'); |
cvs_buf_putc(inputbuf, '\0'); |
rcs_msg = (char *)cvs_buf_release(logbuf); |
input = (char *)cvs_buf_release(inputbuf); |
|
|
return (rcs_msg); |
return (input); |
|
} |
|
|
|
/* |
|
* checkin_init() |
|
* |
|
* Does an initial check in, just enough to create the new ,v file |
|
*/ |
|
static void |
|
checkin_init(struct checkin_params *pb) |
|
{ |
|
BUF *bp; |
|
char *rcs_desc, *filec; |
|
|
|
/* |
|
* Load file contents |
|
*/ |
|
if ((bp = cvs_buf_load(pb->filename, BUF_AUTOEXT)) == NULL) { |
|
cvs_log(LP_ERR, "failed to load '%s'", pb->filename); |
|
exit(1); |
|
} |
|
|
|
if (cvs_buf_putc(bp, '\0') < 0) |
|
exit(1); |
|
|
|
filec = (char *)cvs_buf_release(bp); |
|
|
|
/* |
|
* Get description from user |
|
*/ |
|
rcs_desc = checkin_getdesc(); |
|
rcs_desc_set(pb->file, rcs_desc); |
|
|
|
/* |
|
* Now add our new revision |
|
*/ |
|
if (rcs_rev_add(pb->file, RCS_HEAD_REV, LOG_INIT, |
|
-1, pb->username) != 0) { |
|
cvs_log(LP_ERR, "failed to add new revision"); |
|
exit(1); |
|
} |
|
} |
|
|
|
static int |
|
checkin_attach_symbol(struct checkin_params *pb) |
|
{ |
|
char rbuf[16]; |
|
int ret; |
|
if (verbose == 1) |
|
printf("symbol: %s\n", pb->symbol); |
|
if (pb->flags & CI_SYMFORCE) |
|
rcs_sym_remove(pb->file, pb->symbol); |
|
if ((ret = rcs_sym_add(pb->file, pb->symbol, pb->newrev) == -1) |
|
&& (rcs_errno == RCS_ERR_DUPENT)) { |
|
rcsnum_tostr(rcs_sym_getrev(pb->file, pb->symbol), |
|
rbuf, sizeof(rbuf)); |
|
cvs_log(LP_ERR, |
|
"symbolic name %s already bound to %s", |
|
pb->symbol, rbuf); |
|
rcs_close(pb->file); |
|
return (-1); |
|
} else if (ret == -1) { |
|
cvs_log(LP_ERR, "problem adding symbol: %s", |
|
pb->symbol); |
|
rcs_close(pb->file); |
|
return (-1); |
|
} |
|
return (0); |
|
} |
|
|
|
static void |
|
checkin_revert(struct checkin_params *pb) |
|
{ |
|
char rbuf[16]; |
|
|
|
rcsnum_tostr(pb->frev, rbuf, sizeof(rbuf)); |
|
cvs_log(LP_WARN, |
|
"file is unchanged; reverting to previous revision %s", |
|
rbuf); |
|
(void)unlink(pb->filename); |
|
if ((pb->flags & CO_LOCK) || (pb->flags & CO_UNLOCK)) |
|
checkout_rev(pb->file, pb->frev, pb->filename, |
|
pb->flags, pb->username); |
|
rcs_lock_remove(pb->file, pb->frev); |
|
rcs_close(pb->file); |
|
if (verbose == 1) |
|
printf("done\n"); |
|
} |
|
|
|
static int |
|
checkin_checklock(struct checkin_params *pb) |
|
{ |
|
int found = 0, notlocked = 1; |
|
struct rcs_lock *lkp; |
|
|
|
if (!TAILQ_EMPTY(&(pb->file->rf_locks))) { |
|
TAILQ_FOREACH(lkp, &(pb->file->rf_locks), rl_list) { |
|
if (!strcmp(lkp->rl_name, pb->username)) |
|
notlocked = 0; |
|
|
|
if (!strcmp(lkp->rl_name, pb->username) && |
|
!rcsnum_cmp(lkp->rl_num, pb->frev, 0)) { |
|
found = 1; |
|
return (0); |
|
} |
|
} |
|
} |
|
|
|
if ((found == 0) && (notlocked == 0)) { |
|
cvs_log(LP_ERR, "no locks set for '%s'", pb->username); |
|
rcs_close(pb->file); |
|
return (-1); |
|
} |
|
return (0); |
} |
} |