//
// aegis - project change supervisor
// Copyright (C) 2004-2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
//
// remove
//
// Remove a file. This uses any previous Argument, Directory, Entry,
// or Modified requests, if they have been sent. The last Directory
// sent specifies the working directory at the time of the operation.
//
// Root required: yes.
// Response expected: yes.
//
// Note that this request does not actually do anything to the repository;
// the only effect of a successful "remove" request is to supply the
// client with a new entries line containing /-/ to indicate a removed
// file. In fact, the client probably could perform this operation
// without contacting the server, although using "remove" may cause the
// server to perform a few more checks.
//
// The client sends a subsequent "ci" request to actually record the
// removal in the repository.
//
//
// From the cvs(1) man page:
//
// cvs remove file...
// Use this command (after erasing any files listed) to declare that
// you wish to eliminate files from the repository. The removal
// does not affect others until you run cvs commit.
//
// remove
// Remove files from the source repository, pending a cvs commit on
// the same files. (Does not directly affect repository; changes
// working directory.)
//
// remove [-lR] [files...]
// Requires: Working directory.
// Changes: Working directory.
// Synonyms: rm, delete
// Use this command to declare that you wish to remove files from the
// source repository. Like most cvs commands, cvs remove works on
// files in your working directory, not directly on the repository.
// As a safeguard, it also requires that you first erase the specified
// files from your working directory.
//
// The files are not actually removed until you apply your changes to
// the repository with commit; at that point, the corresponding RCS
// files in the source repository are moved into the Attic directory
// (also within the source repository).
//
// This command is recursive by default, scheduling all physically
// removed files that it finds for removal by the next commit.
// Use the -l option to avoid this recursion, or just specify that
// actual files that you wish remove to consider.
//
//
// Reverse Engineering Notes:
//
#include
#include // HACK
#include
#include
#include
#include
request_remove::~request_remove()
{
}
request_remove::request_remove()
{
}
void
request_remove::run_inner(server_ty *sp, string_ty *)
const
{
size_t j;
if (server_root_required(sp, "remove"))
return;
if (server_directory_required(sp, "remove"))
return;
//
// Process the options.
//
module_ty::options opt;
for (j = 0; j < sp->np->argument_count(); ++j)
{
string_ty *arg = sp->np->argument_nth(j);
if (arg->str_text[0] != '-')
break;
if (0 == strcmp(arg->str_text, "--"))
{
++j;
break;
}
switch (arg->str_text[1])
{
case 'f':
//
// Force a head revision match if tag/date not found.
//
opt.f++;
break;
case 'l':
//
// Local directory only, no recursion.
//
opt.l++;
break;
case 'R':
//
// Process directories recursively.
//
opt.R++;
break;
default:
server_e(sp, "remove: unknown '%s' option", arg->str_text);
break;
}
}
//
// Now process the rest of the arguments.
// Each is a file or directory to be added.
//
bool ok = true;
directory_ty *dp = sp->np->get_curdir();
for (; j < sp->np->argument_count(); ++j)
{
string_ty *arg;
string_ty *client_side;
string_ty *server_side;
//
// Build the (more complete) name of the file on both the client
// side and the server side.
//
arg = sp->np->argument_nth(j);
client_side = os_path_cat(dp->client_side, arg);
server_side = os_path_cat(dp->server_side, arg);
//
// If they have asked for a directory to be removed, we politely
// ignore the request, because Aegis doesn't track directory
// existence, except as implied by file existence.
//
if (sp->np->directory_find_client_side(client_side))
{
server_m
(
sp,
"Directory " ROOT_PATH "/%s removed from the repository "
"(ignored)",
server_side->str_text
);
str_free(client_side);
str_free(server_side);
continue;
}
//
// Pass the remove to the relevant module, one argument at a time.
//
// The CVS client is able to remove files in more than one module
// in a single command. This means we have to lookup the module
// for every argument.
//
module mp = module::find_trim(server_side);
if (!mp->remove(sp, client_side, server_side, opt))
ok = false;
str_free(client_side);
str_free(server_side);
//
// Bail if something went wrong.
//
if (!ok)
break;
}
if (ok)
{
server_e(sp, "use 'cvs commit' to make the 'cvs remove' permanent");
server_ok(sp);
}
}
const char *
request_remove::name()
const
{
return "remove";
}
bool
request_remove::reset()
const
{
return true;
}