Access fish_history from $XDG_DATA_HOME

Add new functions path_get_data and path_create_data which parallel existing
functions path_get_config and path_create_data.  The new functions refer to
XDG_DATA_HOME, if it is defined, or ./local/share if not.

Modify history_filename to use the new function path_get_data.

As a consequence, fish_history will now be located in XDG_DATA_HOME,
not XDG_CONFIG_HOME.

Note that these changes mirror what is already used in
fish-shell/share/tools/create_manpage_completions.py, which stores the
completions in XDG_DATA_HOME

This change matches recommendations in the xdg basedir spec at
http://standards.freedesktop.org/basedir-spec/basedir-spec-0.7.html
($XDG_DATA_HOME defines the base directory relative to which user specific data
files should be stored. If $XDG_DATA_HOME is either not set or empty, a default
equal to $HOME/.local/share should be used.)

It addresses suggestions from the following issues:

1. Don't put history in $XDG_CONFIG_HOME (closes #744)
   https://github.com/fish-shell/fish-shell/issues/744

2. Fish is placing non-config files in $XDG_CONFIG_HOME #1257
   https://github.com/fish-shell/fish-shell/issues/1257

3. Move non-config data out of $XDG_CONFIG_HOME #1669
   https://github.com/fish-shell/fish-shell/issues/1669
This commit is contained in:
Jeff Kowalski 2015-09-16 21:31:08 -07:00 committed by David Adam
parent b776327b9d
commit 2971887bbd
3 changed files with 66 additions and 9 deletions

View file

@ -388,8 +388,8 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
! memcmp(line_start, "---", 3) ||
! memcmp(line_start, "...", 3))
continue;
/* Hackish: fish 1.x rewriting a fish 2.0 history file can produce lines with lots of leading "- cmd: - cmd: - cmd:". Trim all but one leading "- cmd:". */
const char *double_cmd = "- cmd: - cmd: ";
const size_t double_cmd_len = strlen(double_cmd);
@ -398,13 +398,13 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
/* Skip over just one of the - cmd. In the end there will be just one left. */
line_start += strlen("- cmd: ");
}
/* Hackish: fish 1.x rewriting a fish 2.0 history file can produce commands like "when: 123456". Ignore those. */
const char *cmd_when = "- cmd: when:";
const size_t cmd_when_len = strlen(cmd_when);
if (newline - line_start >= cmd_when_len && ! memcmp(line_start, cmd_when, cmd_when_len))
continue;
/* At this point, we know line_start is at the beginning of an item. But maybe we want to skip this item because of timestamps. A 0 cutoff means we don't care; if we do care, then try parsing out a timestamp. */
if (cutoff_timestamp != 0)
@ -733,7 +733,7 @@ history_item_t history_t::item_at_index(size_t idx)
{
resolved_new_item_count -= 1;
}
/* idx=0 corresponds to the last resolved item */
if (idx < resolved_new_item_count)
{
@ -816,7 +816,7 @@ history_item_t history_t::decode_item_fish_2_0(const char *base, size_t len)
size_t indent = 0, cursor = 0;
std::string key, value, line;
/* Read the "- cmd:" line */
size_t advance = read_line(base, cursor, len, line);
trim_leading_spaces(line);
@ -824,7 +824,7 @@ history_item_t history_t::decode_item_fish_2_0(const char *base, size_t len)
{
goto done;
}
cursor += advance;
cmd = str2wcstring(value);
@ -1275,7 +1275,7 @@ static void unescape_yaml(std::string *str)
static wcstring history_filename(const wcstring &name, const wcstring &suffix)
{
wcstring path;
if (! path_get_config(path))
if (! path_get_data(path))
return L"";
wcstring result = path;

View file

@ -276,6 +276,42 @@ static wcstring path_create_config()
return res;
}
static wcstring path_create_data()
{
bool done = false;
wcstring res;
const env_var_t xdg_dir = env_get_string(L"XDG_DATA_HOME");
if (! xdg_dir.missing())
{
res = xdg_dir + L"/fish";
if (!create_directory(res))
{
done = true;
}
}
else
{
const env_var_t home = env_get_string(L"HOME");
if (! home.missing())
{
res = home + L"/.local/share/fish";
if (!create_directory(res))
{
done = true;
}
}
}
if (! done)
{
res.clear();
debug(0, _(L"Unable to create a data directory for fish. Your history will not be saved. Please set the $XDG_DATA_HOME variable to a directory where the current user has write access."));
}
return res;
}
/* Cache the config path */
bool path_get_config(wcstring &path)
{
@ -284,6 +320,14 @@ bool path_get_config(wcstring &path)
return ! result.empty();
}
/* Cache the data path */
bool path_get_data(wcstring &path)
{
static const wcstring result = path_create_data();
path = result;
return ! result.empty();
}
__attribute__((unused))
static void replace_all(wcstring &str, const wchar_t *needle, const wchar_t *replacement)
{

View file

@ -20,13 +20,26 @@
/**
Returns the user configuration directory for fish. If the directory
or one of it's parents doesn't exist, they are first created.
or one of its parents doesn't exist, they are first created.
\param path The directory as an out param
\return whether the directory was returned successfully
*/
bool path_get_config(wcstring &path);
/**
Returns the user data directory for fish. If the directory
or one of its parents doesn't exist, they are first created.
Volatile files presumed to be local to the machine,
such as the fish_history and all the generated_completions,
will be stored in this directory.
\param path The directory as an out param
\return whether the directory was returned successfully
*/
bool path_get_data(wcstring &path);
/**
Finds the full path of an executable. Returns YES if successful.