//
// aegis - project change supervisor
// Copyright (C) 2004-2006, 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
// .
//
#include // for assert
#include
#include
#include
#include
fstate_src_ty *
project_ty::file_find_by_uuid(string_ty *uuid, view_path_ty as_view_path)
{
//
// Invert the list of sources on the UUID field.
// This makes it an O(1) search instead of an O(n) search.
//
trace(("project_ty::file_find_by_uuid(this = %8.8lX, uuid = \"%s\")\n{\n",
(long)this, uuid->str_text));
//
// Deep down in the call stack via project_file_nth, Aegis may
// sometimes need to invalidate the file_by_uuid cache, so we have
// to call it first, or we will segfault when it gets deleted out
// from under us. The simpest method of doing this is via the
// project_ty::change_get method.
//
// An alternative would be to expose the libaegis/project.cc::
// lock_sync() function for calling. Maybe one day in the distant
// future, when project_ty is a class and not a struct.
//
change_get();
symtab_ty *stp = file_by_uuid[as_view_path];
if (!stp)
{
//
// It would be nice to think that the file appeared exactly once,
// and the first file entry with the correct UUID is the one we
// want. Unfortunately, moves are modeled as a remove and a create,
// so we want the create or modify action in preference to the
// remove action.
//
assert(file_action_create < file_action_remove);
assert(file_action_modify < file_action_remove);
stp = new symtab_ty(5);
file_by_uuid[as_view_path] = stp;
for (size_t j = 0; ; ++j)
{
trace(("j = %d\n", (int)j));
fstate_src_ty *src = file_nth(j, as_view_path);
if (!src)
break;
if (!src->uuid)
continue;
fstate_src_ty *prev = (fstate_src_ty *)stp->query(src->uuid);
if (!prev || src->action < prev->action)
stp->assign(src->uuid, src);
}
}
//
// Look for the UUID in the symbol table.
//
fstate_src_ty *result = (fstate_src_ty *)stp->query(uuid);
if (result)
{
trace(("%s %s \"%s\" %s %s\n", file_usage_ename(result->usage),
file_action_ename(result->action), result->file_name->str_text,
(result->edit_origin && result->edit_origin->revision
? result->edit_origin->revision->str_text : ""),
(result->edit && result->edit->revision
? result->edit->revision->str_text : "")));
}
trace(("return %08lX;\n", (long)result));
trace(("}\n"));
return result;
}