//
// aegis - project change supervisor
// Copyright (C) 1999-2009, 2012, 2014 Peter Miller
// Copyright (C) 2008, 2009 Walter Franzini
//
// 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
// .
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void
change_run_history_create_command(change::pointer cp, fstate_src_ty *src)
{
sub_context_ty *scp;
string_ty *hp;
pconf_ty *pconf_data;
string_ty *the_command;
time_t mtime;
string_ty *name_of_encoded_file;
int unlink_encoded_file;
string_ty *hfn;
string_ty *hfnr;
//
// Create a new history. Only ever executed in the "being
// integrated" state. Current directory will be set to the
// base of the history tree. All of the substitutions described
// in aesub(5) are avaliable. In addition:
//
// ${Input}
// The absolute path of the source file to check-in.
//
// ${History}
// The absolute path of history file.
//
// ${File_Name} (Optional)
// The base relative file name of the file for this check-in.
// Note that the file name can vary over the lifetime of the
// file as it is renamed, but the history file name never does.
// DO NOT use this as the name of the history file.
//
// ${UUID} (Optional)
// The universally unique identifier for this file. This is
// invariant for the lifetime of the file.
// DO NOT use this as the name of the history file.
//
trace(("change_run_history_create_command(cp = %p, "
"filename = \"%s\")\n{\n", cp.get(), src->file_name->str_text));
assert(cp->valid());
//
// Inform the user of what we are doing, just in case they can't
// tell from the file names. For example, with a base-64 encoded
// input file and a UUID history file the user has no way of knowing
// which source file this concerns.
//
scp = sub_context_new();
scp->var_set_string("File_Name", src->file_name);
change_error(cp, scp, i18n("history create $filename"));
sub_context_delete(scp);
scp = 0;
//
// See if the file is binary, and if we need to encode it in any way.
// The return value is the absolute path of the encoded temporary
// file, or the absoulute path of the change file if no encoding
// is required.
//
name_of_encoded_file = change_history_encode(cp, src, &unlink_encoded_file);
//
// Get the path of the source file.
//
trace(("mark\n"));
scp = sub_context_new();
sub_var_set_string(scp, "Input", name_of_encoded_file);
//
// Get the path of the history file.
//
trace(("mark\n"));
hp = cp->project_get()->history_path_get();
hfn = project_history_filename_get(cp->project_get(), src);
sub_var_set_string(scp, "History", hfn);
hfnr = os_below_dir(hp, hfn);
str_free(hfn);
//
// Some optional variables, for history tool meta-data.
//
scp->var_set_string("File_Name", src->file_name);
scp->var_optional("File_Name");
scp->var_set_string
(
"Universally_Unique_IDentifier",
(src->uuid ? src->uuid : src->file_name)
);
scp->var_optional("Universally_Unique_IDentifier");
//
// Make sure the command has been set.
//
trace(("mark\n"));
pconf_data = change_pconf_get(cp, 1);
the_command = pconf_data->history_create_command;
if (!the_command)
{
sub_context_ty *scp2;
assert(pconf_data->errpos);
scp2 = sub_context_new();
sub_var_set_string(scp2, "File_Name", pconf_data->errpos);
sub_var_set_charstar(scp2, "FieLD_Name", "history_create_command");
change_fatal
(
cp,
scp2,
i18n("$filename: contains no \"$field_name\" field")
);
// NOTREACHED
sub_context_delete(scp2);
}
//
// Perform the substitutions and run the command.
//
trace(("mark\n"));
the_command = substitute(scp, cp, the_command);
sub_context_delete(scp);
change_env_set(cp, 0);
project_become(cp->project_get());
os_mkdir_between(hp, hfnr, 02755);
str_free(hfnr);
mtime = os_mtime_actual(name_of_encoded_file);
os_execute(the_command, OS_EXEC_FLAG_NO_INPUT, hp);
//
// Reset the file modification time: many history commands
// gratuitously touch the file.
//
// We can have a problem (thus, errok) if it is a "build" file that
// is a symbolic link to a file we have no permission to modify.
//
trace(("mark\n"));
os_mtime_set_errok(name_of_encoded_file, mtime);
str_free(the_command);
//
// If there was an encoded file, get rid of it.
//
trace(("mark\n"));
assert(src->edit);
if (unlink_encoded_file)
os_unlink(name_of_encoded_file);
project_become_undo(cp->project_get());
str_free(name_of_encoded_file);
//
// Read the head revision from the file.
//
trace(("mark\n"));
src->edit->revision = change_run_history_query_command(cp, src);
//
// Set the edit.uuid field
//
if (!cp->uuid_get().empty())
src->edit->uuid = cp->uuid_get().get_ref_copy();
trace(("}\n"));
}
// vim: set ts=8 sw=4 et :