/*ARGSUSED*/ static int register_subdir_proc (Node *p, void *closure) { List *entries = (List *) closure; Subdir_Register (entries, (char *) NULL, p->key); return 0; }
int cvsrename(int argc, char **argv) { int c; int err = 0; char *repos_file1, *repos_file2; char *root1, *root2; const char *filename1, *filename2, *dir1, *dir2; int rootlen; List *ent,*ent2; Node *node; Entnode *entnode; const char *cwd; if (argc == -1) usage (rename_usage); quiet = 0; optind = 0; while ((c = getopt (argc, argv, "+q")) != -1) { switch (c) { case 'q': quiet = 1; break; case '?': default: usage (rename_usage); break; } } argc -= optind; argv += optind; if(argc!=2) { usage(rename_usage); }; error(0,0,"Warning: rename is still experimental and may not behave as you would expect"); if(current_parsed_root->isremote) { if(!supported_request("Rename")) error(1,0,"Remote server does not support rename"); if(!supported_request("Can-Rename")) error(1,0,"Renames are currently disabled"); } if(!strcmp(argv[0],argv[1])) return 0; rootlen = strlen(current_parsed_root->directory); if(!isfile(argv[0])) error(1,0,"%s does not exist",argv[0]); if(isfile(argv[1]) && fncmp(argv[0],argv[1])) /* We allow case renames (on Unix this is redundant) */ error(1,0,"%s already exists",argv[1]); if(isdir(argv[0])) error(1,0,"Directory renames are not currently supported"); validate_file(argv[0],&root1, &repos_file1, &filename1, &dir1, 1); validate_file(argv[1],&root2, &repos_file2, &filename2, &dir2, 0); if(strcmp(root1,root2) || strcmp(root1,current_parsed_root->original)) error(1,0,"%s and %s are in different repositories",argv[0],argv[1]); xfree(root1); xfree(root2); repos_file1 = (char*)xrealloc(repos_file1, strlen(filename1)+strlen(repos_file1)+rootlen+10); repos_file2 = (char*)xrealloc(repos_file2, strlen(filename2)+strlen(repos_file2)+rootlen+10); memmove(repos_file1+rootlen+1,repos_file1,strlen(repos_file1)+1); memmove(repos_file2+rootlen+1,repos_file2,strlen(repos_file2)+1); strcpy(repos_file1,current_parsed_root->directory); strcpy(repos_file2,current_parsed_root->directory); repos_file1[rootlen]='/'; repos_file2[rootlen]='/'; strcat(repos_file1,"/"); strcat(repos_file2,"/"); strcat(repos_file1,filename1); strcat(repos_file2,filename2); if(fncmp(argv[0],argv[1])) set_mapping(dir2,repos_file2+rootlen+1,""); /* Delete old file */ if(fncmp(dir1,dir2)) set_mapping(dir1,repos_file1+rootlen+1,""); set_mapping(dir2,repos_file1+rootlen+1,repos_file2+rootlen+1); /* Rename to new file */ cwd = xgetwd(); if(CVS_CHDIR(dir1)) error(1,errno,"Couldn't chdir to %s",dir1); ent = Entries_Open(0, NULL); node = findnode_fn(ent, filename1); entnode=(Entnode*)node->data; if(!node) { error(1,0,"%s is not listed in CVS/Entries",filename1); CVS_CHDIR(cwd); xfree(cwd); return 1; } if(!fncmp(dir1,dir2)) Rename_Entry(ent,filename1,filename2); else { if(CVS_CHDIR(cwd)) error(1,errno,"Couldn't chdir to %s",cwd); if(CVS_CHDIR(dir2)) error(1,errno,"Couldn't chdir to %s",dir2); ent2 = Entries_Open(0, NULL); if(entnode->type==ENT_FILE) Register(ent2,(char*)filename2,entnode->version,entnode->timestamp,entnode->options,entnode->tag,entnode->date,entnode->conflict,entnode->merge_from_tag_1,entnode->merge_from_tag_2,entnode->rcs_timestamp,entnode->edit_revision,entnode->edit_tag,entnode->edit_bugid,entnode->md5); else if(entnode->type==ENT_SUBDIR) Subdir_Register(ent2,NULL,filename2); else error(1,0,"Unknown entry type %d in entries file",node->type); Entries_Close(ent2); if(CVS_CHDIR(cwd)) error(1,errno,"Couldn't chdir to %s",cwd); if(CVS_CHDIR(dir1)) error(1,errno,"Couldn't chdir to %s",dir1); if(entnode->type==ENT_SUBDIR) Subdir_Deregister(ent,NULL,filename1); else if(entnode->type==ENT_FILE) Scratch_Entry(ent,filename1); else error(1,0,"Unknown entry type %d in entries file",node->type); } Entries_Close(ent); CVS_RENAME(argv[0],argv[1]); if(isdir(argv[1])) { char *tmp=(char*)xmalloc(strlen(argv[1])+strlen(CVSADM_VIRTREPOS)+10); FILE *fp; sprintf(tmp,"%s/%s",argv[1],CVSADM_VIRTREPOS); fp = fopen(tmp,"w"); if(!fp) error(0,errno,"Couldn't write %s",tmp); fprintf(fp,"%s\n",repos_file2+rootlen+1); fclose(fp); } xfree(repos_file1); xfree(repos_file2); xfree(dir1); xfree(dir2); CVS_CHDIR(cwd); xfree(cwd); return (err); }
/* * Add this directory to the list of data to be printed for a directory and * decide whether to tell the recursion processor whether to continue * recursing or not. */ static Dtype ls_direntproc (void *callerdat, const char *dir, const char *repos, const char *update_dir, List *entries) { Dtype retval; Node *p; /* Due to the way we called start_recursion() from ls_proc() with a single * argument at a time, we can assume that if we don't yet have a parent * directory in DIRS then this directory should be processed. */ if (strcmp (dir, ".")) { /* Search for our parent directory. */ char *parent; parent = xmalloc (strlen (update_dir) - strlen (dir) + 1); strncpy (parent, update_dir, strlen (update_dir) - strlen (dir)); parent[strlen (update_dir) - strlen (dir)] = '\0'; strip_trailing_slashes (parent); p = findnode (callerdat, parent); } else p = NULL; if (p) { /* Push this dir onto our parent directory's listing. */ Node *n = getnode(); if (entries_format) n->data = Xasprintf ("D/%s////\n", dir); else if (long_format) { struct long_format_data *out = xmalloc (sizeof (struct long_format_data)); out->header = xstrdup ("d--- "); out->time = gmformat_time_t (unix_time_stamp (repos)); out->footer = Xasprintf ("%12s%s%s", "", show_dead_revs ? " " : "", dir); n->data = out; n->delproc = long_format_data_delproc; } else n->data = Xasprintf ("%s\n", dir); addnode (p->data, n); } if (!p || recurse) { /* Create a new list for this directory. */ p = getnode (); p->key = xstrdup (strcmp (update_dir, ".") ? update_dir : ""); p->data = getlist (); p->delproc = ls_delproc; addnode (callerdat, p); /* Create a local directory and mark it as needing deletion. This is * the behavior the recursion processor relies upon, a la update & * checkout. */ if (!isdir (dir)) { int nonbranch; if (show_tag == NULL && show_date == NULL) { ParseTag (&show_tag, &show_date, &nonbranch); set_tag = true; } if (!created_dir) created_dir = xstrdup (update_dir); make_directory (dir); Create_Admin (dir, update_dir, repos, show_tag, show_date, nonbranch, 0, 0); Subdir_Register (entries, NULL, dir); } /* Tell do_recursion to keep going. */ retval = R_PROCESS; } else retval = R_SKIP_ALL; return retval; }