Revert 1349d12 and properly fix #213

As suggested by @ridiculousfish, when removing autoloaded functions, add them
to a tombstones set.  These functions will never be autoloaded again in the
current shell, not even when the timestamp changes.

Tested as per comment 1 of #1033.  `~/.config/fish/functions/ls.fish` contains
the function definition.  `function -e ls` removes the redefined `ls` (and
reverts back to the built-in command).  `touch .../ls.fish` does not cause the
function to be reloaded.
This commit is contained in:
Sanne Wouda 2015-03-11 14:14:56 +01:00 committed by ridiculousfish
parent 9f8cec7f9e
commit 73f344f41b
3 changed files with 31 additions and 13 deletions

View File

@ -1565,7 +1565,7 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
{
int i;
for (i=woptind; i<argc; i++)
function_remove_ignore_autoload(argv[i]);
function_remove(argv[i]);
return STATUS_BUILTIN_OK;
}
else if (desc)

View File

@ -43,6 +43,11 @@
typedef std::map<wcstring, function_info_t> function_map_t;
static function_map_t loaded_functions;
/**
Functions that shouldn't be autoloaded (anymore).
*/
static std::set<wcstring> function_tombstones;
/* Lock for functions */
static pthread_mutex_t functions_lock;
@ -61,6 +66,8 @@ function_autoload_t::function_autoload_t() : autoload_t(L"fish_function_path", N
{
}
static bool function_remove_ignore_autoload(const wcstring &name);
/** Callback when an autoloaded function is removed */
void function_autoload_t::command_removed(const wcstring &cmd)
{
@ -84,6 +91,11 @@ static int load(const wcstring &name)
scoped_lock lock(functions_lock);
bool was_autoload = is_autoload;
int res;
bool no_more_autoload = function_tombstones.count(name) == 1;
if (no_more_autoload)
return 0;
function_map_t::iterator iter = loaded_functions.find(name);
if (iter != loaded_functions.end() && !iter->second.is_autoload)
{
@ -225,19 +237,28 @@ int function_exists_no_autoload(const wcstring &cmd, const env_vars_snapshot_t &
return loaded_functions.find(cmd) != loaded_functions.end() || function_autoloader.can_load(cmd, vars);
}
bool function_remove_ignore_autoload(const wcstring &name)
static bool function_remove_ignore_autoload(const wcstring &name)
{
scoped_lock lock(functions_lock);
bool erased = (loaded_functions.erase(name) > 0);
if (erased)
{
event_t ev(EVENT_ANY);
ev.function_name=name;
event_remove(ev);
}
return erased;
function_map_t::iterator iter = loaded_functions.find(name);
// not found. not erasing.
if (iter == loaded_functions.end())
return false;
// removing an auto-loaded function. prevent it from being
// auto-reloaded.
if (iter->second.is_autoload)
function_tombstones.insert(name);
loaded_functions.erase(iter);
event_t ev(EVENT_ANY);
ev.function_name=name;
event_remove(ev);
return true;
}
void function_remove(const wcstring &name)

View File

@ -105,9 +105,6 @@ void function_init();
/** Add a function. definition_line_offset is the line number of the function's definition within its source file */
void function_add(const function_data_t &data, const parser_t &parser, int definition_line_offset = 0);
/** Removes a function from our internal table, returning true if it was found and false if not */
bool function_remove_ignore_autoload(const wcstring &name);
/**
Remove the function with the specified name.
*/