mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
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:
parent
9f8cec7f9e
commit
73f344f41b
3 changed files with 31 additions and 13 deletions
|
@ -1565,7 +1565,7 @@ static int builtin_functions(parser_t &parser, wchar_t **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i=woptind; i<argc; i++)
|
for (i=woptind; i<argc; i++)
|
||||||
function_remove_ignore_autoload(argv[i]);
|
function_remove(argv[i]);
|
||||||
return STATUS_BUILTIN_OK;
|
return STATUS_BUILTIN_OK;
|
||||||
}
|
}
|
||||||
else if (desc)
|
else if (desc)
|
||||||
|
|
39
function.cpp
39
function.cpp
|
@ -43,6 +43,11 @@
|
||||||
typedef std::map<wcstring, function_info_t> function_map_t;
|
typedef std::map<wcstring, function_info_t> function_map_t;
|
||||||
static function_map_t loaded_functions;
|
static function_map_t loaded_functions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Functions that shouldn't be autoloaded (anymore).
|
||||||
|
*/
|
||||||
|
static std::set<wcstring> function_tombstones;
|
||||||
|
|
||||||
/* Lock for functions */
|
/* Lock for functions */
|
||||||
static pthread_mutex_t functions_lock;
|
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 */
|
/** Callback when an autoloaded function is removed */
|
||||||
void function_autoload_t::command_removed(const wcstring &cmd)
|
void function_autoload_t::command_removed(const wcstring &cmd)
|
||||||
{
|
{
|
||||||
|
@ -84,6 +91,11 @@ static int load(const wcstring &name)
|
||||||
scoped_lock lock(functions_lock);
|
scoped_lock lock(functions_lock);
|
||||||
bool was_autoload = is_autoload;
|
bool was_autoload = is_autoload;
|
||||||
int res;
|
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);
|
function_map_t::iterator iter = loaded_functions.find(name);
|
||||||
if (iter != loaded_functions.end() && !iter->second.is_autoload)
|
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);
|
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);
|
scoped_lock lock(functions_lock);
|
||||||
bool erased = (loaded_functions.erase(name) > 0);
|
|
||||||
|
|
||||||
if (erased)
|
function_map_t::iterator iter = loaded_functions.find(name);
|
||||||
{
|
|
||||||
event_t ev(EVENT_ANY);
|
|
||||||
ev.function_name=name;
|
|
||||||
event_remove(ev);
|
|
||||||
}
|
|
||||||
return erased;
|
|
||||||
|
|
||||||
|
// 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)
|
void function_remove(const wcstring &name)
|
||||||
|
|
|
@ -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 */
|
/** 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);
|
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.
|
Remove the function with the specified name.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue