//
// aegis - project change supervisor
// Copyright (C) 1999, 2001-2008, 2011, 2012 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
#include
#include
#include
#include
#include
#include
string_list_ty *
project::file_list_get(view_path_ty as_view_path)
{
trace(("project::file_list_get(this = %p, as_view_path = %s)\n{\n",
this, view_path_ename(as_view_path)));
#ifdef DEBUG
switch (as_view_path)
{
case view_path_none:
case view_path_simple:
case view_path_extreme:
break;
default:
assert(0);
as_view_path = view_path_simple;
break;
}
#endif
if (!file_list[as_view_path])
{
project *ppp;
change::pointer cp;
long j;
fstate_src_ty *fsp;
string_list_ty *wlp;
symtab_iterator *tmpi;
string_ty *key;
void *data;
//
// Drop all the files into a symbol table.
// This has O(1) insertion times.
//
// We are using the symbol table to mimic the actions of the
// project::file_find method, but for every project file in
// parallel. It is essential that this function does exactly
// what the project::file_find method does.
//
symtab_ty *tmp = new symtab_ty(100);
trace(("tmp = %p\n", tmp));
assert(tmp->valid());
for (ppp = this; ppp; ppp = (ppp->is_a_trunk() ? 0 : ppp->parent_get()))
{
trace(("project \"%s\"\n", project_name_get(ppp).c_str()));
cp = ppp->change_get();
trace(("mark\n"));
for (j = 0; ; ++j)
{
trace(("mark\n"));
fsp = change_file_nth(cp, j, view_path_first);
if (!fsp)
break;
trace(("%s \"%s\"\n", file_action_ename(fsp->action),
fsp->file_name->str_text));
//
// If we already have a "hit" for this file, ignore any
// deeper records. This mimics the way project::file_find
// stops as soon as it finds a match.
//
// This has O(1) query times.
//
trace(("tmp = %p\n", tmp));
if (tmp->query(fsp->file_name))
continue;
switch (as_view_path)
{
case view_path_first:
//
// This means that transparent and removed files
// are returned. No project file union, either.
//
break;
case view_path_none:
//
// This means that transparent files are returned
// as transparent, no processing or filtering of
// the list is performed.
//
break;
case view_path_simple:
case view_path_extreme:
switch (fsp->action)
{
case file_action_transparent:
//
// These cases both mean that transparent files
// are resolved (the underlying file is shown).
//
continue;
case file_action_remove:
//
// For now, we keep removed files in the symbol table.
//
break;
case file_action_create:
case file_action_modify:
case file_action_insulate:
#ifndef DEBUG
default:
#endif
// should be file_action_remove
assert(!fsp->deleted_by);
if (fsp->deleted_by)
break;
// should be file_action_transparent
assert(!fsp->about_to_be_created_by);
if (fsp->about_to_be_created_by)
continue;
// should be file_action_transparent
assert(!fsp->about_to_be_copied_by);
if (fsp->about_to_be_copied_by)
continue;
break;
}
break;
}
trace(("tmp = %p\n", tmp));
tmp->assign(fsp->file_name, fsp);
}
if (as_view_path == view_path_first)
{
//
// This means that transparent and removed files
// are returned. No project file union, either.
//
break;
}
}
//
// Walk the symbol table to build the file name list.
// This has O(n) running time.
//
trace(("tmp = %p\n", tmp));
assert(tmp->valid());
tmpi = symtab_iterator_new(tmp);
wlp = new string_list_ty();
while (symtab_iterator_next(tmpi, &key, &data))
{
switch (as_view_path)
{
case view_path_first:
case view_path_none:
case view_path_simple:
break;
case view_path_extreme:
//
// This means that transparent files are resolved (the
// underlying file is shown), but removed files are
// omitted from the result.
//
trace(("tmp = %p\n", tmp));
fsp = (fstate_src_ty *)tmp->query(key);
assert(fsp);
if (!fsp)
break;
switch (fsp->action)
{
case file_action_remove:
continue;
case file_action_create:
case file_action_modify:
case file_action_insulate:
case file_action_transparent:
#ifndef DEBUG
default:
#endif
// should be file_action_remove
assert(!fsp->deleted_by);
if (fsp->deleted_by)
continue;
break;
}
break;
}
wlp->push_back(key);
}
symtab_iterator_delete(tmpi);
trace(("tmp = %p\n", tmp));
assert(tmp->valid());
delete tmp;
//
// Ensure that the file name list is in lexicographical
// order, otherwise the users can see the joins (and it's
// harder to find the files in a listing).
// (C locale)
//
// Overall performance is O(n) for file discovery,
// plus O(n log n) for the qsort, where n is the number
// of files.
//
wlp->sort();
file_list[as_view_path] = wlp;
}
trace(("return %p;\n", file_list[as_view_path]));
trace(("}\n"));
return file_list[as_view_path];
}
// vim: set ts=8 sw=4 et :