mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
Make wildcards beginning with dots not match . and ..
https://github.com/fish-shell/fish-shell/issues/270
This commit is contained in:
parent
3d5a3f03fa
commit
833abc27cc
5 changed files with 59 additions and 26 deletions
|
@ -512,7 +512,7 @@ bool contains_internal( const wchar_t *a, ... )
|
|||
{
|
||||
const wchar_t *arg;
|
||||
va_list va;
|
||||
int res = 0;
|
||||
bool res = false;
|
||||
|
||||
CHECK( a, 0 );
|
||||
|
||||
|
@ -521,7 +521,7 @@ bool contains_internal( const wchar_t *a, ... )
|
|||
{
|
||||
if( wcscmp( a,arg) == 0 )
|
||||
{
|
||||
res=1;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
2
common.h
2
common.h
|
@ -175,7 +175,7 @@ extern const wchar_t *program_name;
|
|||
#define N_(wstr) wstr
|
||||
|
||||
/**
|
||||
Check if the specified stringelement is a part of the specified string list
|
||||
Check if the specified string element is a part of the specified string list
|
||||
*/
|
||||
#define contains( str,... ) contains_internal( str, __VA_ARGS__, NULL )
|
||||
|
||||
|
|
|
@ -527,7 +527,13 @@ static int expand_test( const wchar_t *in, int flags, ... )
|
|||
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
for (size_t idx=0; idx < output.size(); idx++)
|
||||
{
|
||||
printf("%ls\n", output.at(idx).completion.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
va_start( va, flags );
|
||||
|
||||
while( (arg=va_arg(va, wchar_t *) )!= 0 )
|
||||
|
@ -573,7 +579,22 @@ static void test_expand()
|
|||
{
|
||||
err( L"Cannot skip wildcard expansion" );
|
||||
}
|
||||
|
||||
|
||||
if (system("mkdir -p /tmp/fish_expand_test/")) err(L"mkdir failed");
|
||||
if (system("touch /tmp/fish_expand_test/.foo")) err(L"touch failed");
|
||||
if (system("touch /tmp/fish_expand_test/bar")) err(L"touch failed");
|
||||
|
||||
// This is checking that .* does NOT match . and .. (https://github.com/fish-shell/fish-shell/issues/270). But it does have to match literal components (e.g. "./*" has to match the same as "*"
|
||||
if (! expand_test( L"/tmp/fish_expand_test/.*", 0, L"/tmp/fish_expand_test/.foo", 0 ))
|
||||
{
|
||||
err( L"Expansion not correctly handling dotfiles" );
|
||||
}
|
||||
if (! expand_test( L"/tmp/fish_expand_test/./.*", 0, L"/tmp/fish_expand_test/.foo", 0 ))
|
||||
{
|
||||
err( L"Expansion not correctly handling literal path components in dotfiles" );
|
||||
}
|
||||
|
||||
//system("rm -Rf /tmp/fish_expand_test");
|
||||
}
|
||||
|
||||
/** Test path functions */
|
||||
|
|
52
wildcard.cpp
52
wildcard.cpp
|
@ -143,29 +143,36 @@ int wildcard_has( const wchar_t *str, int internal )
|
|||
\param wc The wildcard.
|
||||
\param is_first Whether files beginning with dots should not be matched against wildcards.
|
||||
*/
|
||||
static int wildcard_match2( const wchar_t *str,
|
||||
static bool wildcard_match2(const wchar_t *str,
|
||||
const wchar_t *wc,
|
||||
int is_first )
|
||||
bool is_first )
|
||||
{
|
||||
if( *str == 0 && *wc==0 )
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
/* Hackish fix for https://github.com/fish-shell/fish-shell/issues/270. Prevent wildcards from matching . or .., but we must still allow literal matches. */
|
||||
if (is_first && contains(str, L".", L".."))
|
||||
{
|
||||
/* The string is '.' or '..'. Return true if the wildcard exactly matches. */
|
||||
return ! wcscmp(str, wc);
|
||||
}
|
||||
|
||||
if( *wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE)
|
||||
{
|
||||
/* Ignore hidden file */
|
||||
if( is_first && *str == L'.' )
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Try all submatches */
|
||||
do
|
||||
{
|
||||
if( wildcard_match2( str, wc+1, 0 ) )
|
||||
return 1;
|
||||
if( wildcard_match2( str, wc+1, false ) )
|
||||
return true;
|
||||
}
|
||||
while( *(str++) != 0 );
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
else if( *str == 0 )
|
||||
{
|
||||
|
@ -173,23 +180,23 @@ static int wildcard_match2( const wchar_t *str,
|
|||
End of string, but not end of wildcard, and the next wildcard
|
||||
element is not a '*', so this is not a match.
|
||||
*/
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( *wc == ANY_CHAR )
|
||||
{
|
||||
if( is_first && *str == L'.' )
|
||||
{
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return wildcard_match2( str+1, wc+1, 0 );
|
||||
return wildcard_match2( str+1, wc+1, false );
|
||||
}
|
||||
|
||||
if( *wc == *str )
|
||||
return wildcard_match2( str+1, wc+1, 0 );
|
||||
return wildcard_match2( str+1, wc+1, false );
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -303,9 +310,9 @@ bool wildcard_complete(const wcstring &str,
|
|||
}
|
||||
|
||||
|
||||
int wildcard_match( const wcstring &str, const wcstring &wc )
|
||||
bool wildcard_match( const wcstring &str, const wcstring &wc )
|
||||
{
|
||||
return wildcard_match2( str.c_str(), wc.c_str(), 1 );
|
||||
return wildcard_match2( str.c_str(), wc.c_str(), true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -684,7 +691,11 @@ typedef std::pair<dev_t, ino_t> file_id_t;
|
|||
|
||||
This function traverses the relevant directory tree looking for
|
||||
matches, and recurses when needed to handle wildcrards spanning
|
||||
multiple components and recursive wildcards.
|
||||
multiple components and recursive wildcards.
|
||||
|
||||
Because this function calls itself recursively with substrings,
|
||||
it's important that the parameters be raw pointers instead of wcstring,
|
||||
which would be too expensive to construct for all substrings.
|
||||
*/
|
||||
static int wildcard_expand_internal( const wchar_t *wc,
|
||||
const wchar_t *base_dir,
|
||||
|
@ -709,7 +720,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
|
|||
|
||||
/* Variables for testing for presense of recursive wildcards */
|
||||
const wchar_t *wc_recursive;
|
||||
int is_recursive;
|
||||
bool is_recursive;
|
||||
|
||||
/* Slightly mangled version of base_dir */
|
||||
const wchar_t *dir_string;
|
||||
|
@ -843,7 +854,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
|
|||
}
|
||||
else
|
||||
{
|
||||
if( wildcard_match2( name, wc, 1 ) )
|
||||
if( wildcard_match2( name, wc, true ) )
|
||||
{
|
||||
const wcstring long_name = make_path(base_dir, next);
|
||||
int skip = 0;
|
||||
|
@ -938,7 +949,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
|
|||
Test if the file/directory name matches the whole
|
||||
wildcard element, i.e. regular matching.
|
||||
*/
|
||||
int whole_match = wildcard_match2( name, wc_str, 1 );
|
||||
int whole_match = wildcard_match2( name, wc_str, true );
|
||||
int partial_match = 0;
|
||||
|
||||
/*
|
||||
|
@ -951,7 +962,7 @@ static int wildcard_expand_internal( const wchar_t *wc,
|
|||
{
|
||||
const wchar_t *end = wcschr( wc, ANY_STRING_RECURSIVE );
|
||||
wchar_t *wc_sub = wcsndup( wc, end-wc+1);
|
||||
partial_match = wildcard_match2( name, wc_sub, 1 );
|
||||
partial_match = wildcard_match2( name, wc_sub, true );
|
||||
free( wc_sub );
|
||||
}
|
||||
|
||||
|
@ -974,8 +985,9 @@ static int wildcard_expand_internal( const wchar_t *wc,
|
|||
{
|
||||
// Insert a "file ID" into visited_files
|
||||
// If the insertion fails, we've already visited this file (i.e. a symlink loop)
|
||||
// If we're not recursive, insert anyways (in case we loop back around in a future recursive segment), but continue on; the idea being that literal path components should still work
|
||||
const file_id_t file_id(buf.st_dev, buf.st_ino);
|
||||
if( S_ISDIR(buf.st_mode) && visited_files.insert(file_id).second)
|
||||
if( S_ISDIR(buf.st_mode) && (visited_files.insert(file_id).second || ! is_recursive))
|
||||
{
|
||||
size_t new_len = wcslen( new_dir );
|
||||
new_dir[new_len] = L'/';
|
||||
|
|
|
@ -75,7 +75,7 @@ int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, expand_
|
|||
\param wc The wildcard to test against
|
||||
\return true if the wildcard matched
|
||||
*/
|
||||
int wildcard_match( const wcstring &str, const wcstring &wc );
|
||||
bool wildcard_match( const wcstring &str, const wcstring &wc );
|
||||
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue