version 1.13, 2005/04/18 21:02:50 |
version 1.14, 2005/04/19 18:51:30 |
|
|
*/ |
*/ |
|
|
#include <sys/types.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
|
|
|
#include <errno.h> |
#include <errno.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <fcntl.h> |
|
#include <stdlib.h> |
#include <stdlib.h> |
#include <unistd.h> |
|
#include <string.h> |
#include <string.h> |
|
|
#include "cvs.h" |
#include "cvs.h" |
|
|
#include "proto.h" |
#include "proto.h" |
|
|
|
|
int cvs_tag_file(CVSFILE *, void *); |
static int cvs_tag_local (CVSFILE *, void *); |
int cvs_tag_options(char *, int, char **, int *); |
static int cvs_tag_remote (CVSFILE *, void *); |
int cvs_tag_sendflags(struct cvsroot *); |
static int cvs_tag_options (char *, int, char **, int *); |
|
static int cvs_tag_sendflags (struct cvsroot *); |
|
|
static char *tag, *old_tag, *date; |
static char *tag_name = NULL; |
static int branch, delete; |
static char *tag_date = NULL; |
|
static char *tag_oldname = NULL; |
|
static int tag_branch = 0; |
|
static int tag_delete = 0; |
|
static int tag_forcehead = 0; |
|
|
struct cvs_cmd_info cvs_tag = { |
struct cvs_cmd_info cvs_tag = { |
cvs_tag_options, |
cvs_tag_options, |
cvs_tag_sendflags, |
cvs_tag_sendflags, |
cvs_tag_file, |
cvs_tag_remote, |
NULL, NULL, |
NULL, NULL, |
CF_SORT | CF_IGNORE | CF_RECURSE, |
CF_SORT | CF_IGNORE | CF_RECURSE, |
CVS_REQ_TAG, |
CVS_REQ_TAG, |
CVS_CMD_ALLOWSPEC |
CVS_CMD_ALLOWSPEC | CVS_CMD_SENDDIR |
}; |
}; |
|
|
int |
static int |
cvs_tag_options(char *opt, int argc, char **argv, int *arg) |
cvs_tag_options(char *opt, int argc, char **argv, int *arg) |
{ |
{ |
int ch; |
int ch; |
|
|
date = old_tag = NULL; |
tag_date = tag_oldname = NULL; |
branch = delete = 0; |
|
|
|
while ((ch = getopt(argc, argv, opt)) != -1) { |
while ((ch = getopt(argc, argv, opt)) != -1) { |
switch (ch) { |
switch (ch) { |
case 'b': |
case 'b': |
branch = 1; |
tag_branch = 1; |
break; |
break; |
case 'd': |
case 'd': |
delete = 1; |
tag_delete = 1; |
break; |
break; |
|
case 'f': |
|
tag_forcehead = 1; |
|
break; |
case 'D': |
case 'D': |
date = optarg; |
tag_date = optarg; |
break; |
break; |
case 'l': |
case 'l': |
cvs_tag.file_flags &= ~CF_RECURSE; |
cvs_tag.file_flags &= ~CF_RECURSE; |
break; |
break; |
case 'r': |
case 'r': |
old_tag = optarg; |
tag_oldname = optarg; |
break; |
break; |
default: |
default: |
return (CVS_EX_USAGE); |
return (CVS_EX_USAGE); |
|
|
if (argc == 0) { |
if (argc == 0) { |
return (CVS_EX_USAGE); |
return (CVS_EX_USAGE); |
} else { |
} else { |
tag = argv[0]; |
tag_name = argv[0]; |
argc--; |
argc--; |
argv++; |
argv++; |
*arg += 1; |
*arg += 1; |
} |
} |
|
|
if (branch && delete) { |
if (tag_branch && tag_delete) { |
cvs_log(LP_WARN, "ignoring -b with -d options"); |
cvs_log(LP_WARN, "ignoring -b with -d options"); |
branch = 0; |
tag_branch = 0; |
} |
} |
|
|
if (delete && old_tag) |
if (tag_delete && tag_oldname) |
old_tag = NULL; |
tag_oldname = NULL; |
|
|
if (delete && date) |
if (tag_delete && tag_date) |
date = NULL; |
tag_date = NULL; |
|
|
if (old_tag != NULL && date != NULL) { |
if (tag_oldname != NULL && tag_date != NULL) { |
cvs_log(LP_ERROR, "-r and -D options are mutually exclusive"); |
cvs_log(LP_ERROR, "-r and -D options are mutually exclusive"); |
return (CVS_EX_USAGE); |
return (CVS_EX_USAGE); |
} |
} |
|
|
return (0); |
return (0); |
} |
} |
|
|
int |
static int |
cvs_tag_sendflags(struct cvsroot *root) |
cvs_tag_sendflags(struct cvsroot *root) |
{ |
{ |
if (branch && (cvs_sendarg(root, "-b", 0) < 0)) |
if (tag_branch && (cvs_sendarg(root, "-b", 0) < 0)) |
return (CVS_EX_PROTO); |
return (CVS_EX_PROTO); |
|
|
if (delete && (cvs_sendarg(root, "-d", 0) < 0)) |
if (tag_delete && (cvs_sendarg(root, "-d", 0) < 0)) |
return (CVS_EX_PROTO); |
return (CVS_EX_PROTO); |
|
|
if (old_tag) { |
if (tag_oldname) { |
if ((cvs_sendarg(root, "-r", 0) < 0) || |
if ((cvs_sendarg(root, "-r", 0) < 0) || |
(cvs_sendarg(root, old_tag, 0) < 0)) |
(cvs_sendarg(root, tag_oldname, 0) < 0)) |
return (CVS_EX_PROTO); |
return (CVS_EX_PROTO); |
} |
} |
|
|
if (date) { |
if (tag_date) { |
if ((cvs_sendarg(root, "-D", 0) < 0) || |
if ((cvs_sendarg(root, "-D", 0) < 0) || |
(cvs_sendarg(root, date, 0) < 0)) |
(cvs_sendarg(root, tag_date, 0) < 0)) |
return (CVS_EX_PROTO); |
return (CVS_EX_PROTO); |
} |
} |
|
|
if (cvs_sendarg(root, tag, 0) < 0) |
if (cvs_sendarg(root, tag_name, 0) < 0) |
return (CVS_EX_PROTO); |
return (CVS_EX_PROTO); |
|
|
return (0); |
return (0); |
|
|
|
|
|
|
/* |
/* |
* cvs_tag_file() |
* cvs_tag_remote() |
* |
* |
* Get the status of a single file. |
* Get the status of a single file. |
*/ |
*/ |
int |
static int |
cvs_tag_file(CVSFILE *cfp, void *arg) |
cvs_tag_remote(CVSFILE *cfp, void *arg) |
{ |
{ |
int ret, l; |
int ret; |
char *repo, fpath[MAXPATHLEN], rcspath[MAXPATHLEN]; |
char fpath[MAXPATHLEN]; |
RCSFILE *rf; |
|
struct cvsroot *root; |
struct cvsroot *root; |
|
|
ret = 0; |
ret = 0; |
rf = NULL; |
|
root = CVS_DIR_ROOT(cfp); |
root = CVS_DIR_ROOT(cfp); |
|
|
if ((root->cr_method != CVS_METHOD_LOCAL) && (cfp->cf_type == DT_DIR)) { |
if (cfp->cf_type == DT_DIR) { |
if (cvs_senddir(root, cfp) < 0) |
ret = cvs_senddir(root, cfp); |
return (CVS_EX_PROTO); |
return (ret); |
return (0); |
|
} |
} |
|
|
|
if (cvs_sendentry(root, cfp) < 0) { |
|
return (CVS_EX_PROTO); |
|
} |
|
|
cvs_file_getpath(cfp, fpath, sizeof(fpath)); |
cvs_file_getpath(cfp, fpath, sizeof(fpath)); |
|
|
if (root->cr_method != CVS_METHOD_LOCAL) { |
switch (cfp->cf_cvstat) { |
if (cvs_sendentry(root, cfp) < 0) { |
case CVS_FST_UNKNOWN: |
return (CVS_EX_PROTO); |
ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, cfp->cf_name); |
} |
break; |
|
case CVS_FST_UPTODATE: |
|
ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, cfp->cf_name); |
|
break; |
|
case CVS_FST_MODIFIED: |
|
ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, cfp->cf_name); |
|
default: |
|
break; |
|
} |
|
|
switch (cfp->cf_cvstat) { |
return (ret); |
case CVS_FST_UNKNOWN: |
} |
ret = cvs_sendreq(root, CVS_REQ_QUESTIONABLE, |
|
CVS_FILE_NAME(cfp)); |
|
break; |
|
case CVS_FST_UPTODATE: |
|
ret = cvs_sendreq(root, CVS_REQ_UNCHANGED, |
|
CVS_FILE_NAME(cfp)); |
|
break; |
|
case CVS_FST_MODIFIED: |
|
ret = cvs_sendreq(root, CVS_REQ_ISMODIFIED, |
|
CVS_FILE_NAME(cfp)); |
|
default: |
|
break; |
|
} |
|
} else { |
|
if (cfp->cf_cvstat == CVS_FST_UNKNOWN) { |
|
cvs_log(LP_WARN, "I know nothing about %s", fpath); |
|
return (0); |
|
} |
|
|
|
repo = CVS_DIR_REPO(cfp); |
|
l = snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s", |
|
root->cr_dir, repo, CVS_FILE_NAME(cfp), RCS_FILE_EXT); |
|
if (l == -1 || l >= (int)sizeof(rcspath)) { |
|
errno = ENAMETOOLONG; |
|
cvs_log(LP_ERRNO, "%s", rcspath); |
|
return (-1); |
|
} |
|
|
|
rf = rcs_open(rcspath, RCS_READ); |
static int |
if (rf == NULL) { |
cvs_tag_local(CVSFILE *cf, void *arg) |
return (CVS_EX_DATA); |
{ |
} |
int len; |
|
char *repo, fpath[MAXPATHLEN], rcspath[MAXPATHLEN]; |
|
struct cvsroot *root; |
|
RCSFILE *rf; |
|
RCSNUM *tag_rev; |
|
|
rcs_close(rf); |
cvs_file_getpath(cf, fpath, sizeof(fpath)); |
|
|
|
if (cf->cf_cvstat == CVS_FST_UNKNOWN) { |
|
cvs_log(LP_WARN, "I know nothing about %s", fpath); |
|
return (0); |
} |
} |
|
|
return (ret); |
repo = CVS_DIR_REPO(cf); |
|
root = CVS_DIR_ROOT(cf); |
|
|
|
len = snprintf(rcspath, sizeof(rcspath), "%s/%s/%s%s", |
|
root->cr_dir, repo, cf->cf_name, RCS_FILE_EXT); |
|
if (len == -1 || len >= (int)sizeof(rcspath)) { |
|
errno = ENAMETOOLONG; |
|
cvs_log(LP_ERRNO, "%s", rcspath); |
|
return (-1); |
|
} |
|
|
|
rf = rcs_open(rcspath, RCS_READ|RCS_WRITE); |
|
if (rf == NULL) { |
|
cvs_log(LP_ERR, "failed to open %s: %s", rcspath, |
|
rcs_errstr(rcs_errno)); |
|
return (-1); |
|
} |
|
|
|
if (rcs_sym_add(rf, tag_name, tag_rev) < 0) { |
|
cvs_log(LP_ERR, "failed to tag %s: %s", rcspath, |
|
rcs_errstr(rcs_errno)); |
|
} |
|
|
|
rcs_close(rf); |
|
return (0); |
} |
} |