// // 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 // . // // // ci // // Actually do a CVS ci command. 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. No provision is made for any input from the user. // This means that ci must use a -m argument if it wants to specify a // log message. // // Response expected: yes. // Root required: yes. // // // Example // // After the user modifies the file and instructs the client to check // it back in. The client sends arguments to specify the log message // and file to check in: // // C: Argument -m // C: Argument Well, you see, it took me hours and hours to find // C: Argumentx this typo and I searched and searched and eventually // C: Argumentx had to ask John for help. // C: Argument mungeall.c // // It also sends information about the contents of the working directory, // including the new contents of the modified file. Note that the user // has changed into the "supermunger" directory before executing this // command; the top level directory is a user-visible concept because // the server should print filenames in M and E responses relative to // that directory. // // (We are waving our hands about the order of the requests. "Directory" // and "Argument" can be in any order, but this probably isn't specified // very well.) // // C: Directory . // C: /u/cvsroot/supermunger // C: Entry /mungeall.c/1.1/// // C: Modified mungeall.c // C: u=rw,g=r,o=r // C: 26 // C: int main () { abort (); } // // And finally, the client issues the checkin command (which makes use // of the data just sent): // // C: ci // // And the server tells the client that the checkin succeeded: // // S: M Checking in mungeall.c; // S: E /u/cvsroot/supermunger/mungeall.c,v <-- mungeall.c // S: E new revision: 1.2; previous revision: 1.1 // S: E done // S: Mode u=rw,g=r,o=r // S: Checked-in ./ // S: /u/cvsroot/supermunger/mungeall.c // S: /mungeall.c/1.2/// // S: ok // // // Reverse Engineering Notes: // // First comes the command line arguments from the client. // The following options are known to be transmitted by the client: // -m As two Argument requests, plus optional Argumentx // // Then follows a series of Directory/Entry/Modified requests for // all the files which have changed in some way. // // Then comes a Directory request, specifying what the // remaining arguments are relative to. // // Then a series of Argument requests, listing all of the files to be // committed. Conceivably this list could differ from the implicit // list you can derived from the Modified requests, because the -f // ("force") flag on the client side can be used to commit files // which have not been modified. // // Last, they send the "ci" request. // // The ugly part is that they could send more than one change at // a time! CVS is more than happy to commit more than one module // at once. // #include #include #include #include #include request_checkin::~request_checkin() { } request_checkin::request_checkin() { } void request_checkin::run_inner(server_ty *sp, string_ty *) const { size_t j; directory_ty *dp; int ok; if (server_root_required(sp, "ci")) return; if (server_directory_required(sp, "ci")) return; // // Skip the options. // 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; } if (arg->str_text[1] == 'm') ++j; } ok = 1; 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); // // Pass the checkin to the relevant module, one file at a time. // // The CVS client is able to commit files to more than one module // in a single command. This means we have to lookup the module // for every file. // module mp = module::find_trim(server_side); if (!mp->checkin(sp, client_side, server_side)) ok = 0; str_free(client_side); str_free(server_side); if (!ok) break; } if (ok) { server_m ( sp, "ci: now you have to use the \"aegis -develop-end\" command to " "finish the job" ); server_ok(sp); } } const char * request_checkin::name() const { return "ci"; } bool request_checkin::reset() const { return true; }