mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 08:18:15 +03:00
e6737d409d
Summary: We need to introduce a new `includeDotfiles` option to `glob()`. [As we have done for all of our Thrift API, to date], rather than define `glob()` so that it takes a single struct, we specified the parameters individually, so we can no longer add new params to `glob()`. In particular, we need to support `includeDotfiles` because we often configure Buck to use Watchman to implement `glob()` in `BUCK` files, and when Watchman is used in Eden, it leverages Eden's Thrift API to implement `glob()`. Because Buck's `glob()` has an `include_dotfiles` option, we must be able to honor it and pass it all the way through to Eden's `glob()` implementation. Rather than name the new API `glob2()`, I'm electing to go with `globFiles()`. (Perhaps once we eliminate all known users of `glob()` in the wild, which requires turning over the current version of Watchman we have deployed, we can redefine `glob()` in `eden.thrift` to be the same as `globFiles()` and then update everyone to use `glob()` again so it has the more intuitive name.) Reviewed By: wez Differential Revision: D7748870 fbshipit-source-id: 92438f9c41e4fbdbd6cdccca5fce0e41cc3e9b07
137 lines
4.9 KiB
Python
137 lines
4.9 KiB
Python
#!/usr/bin/env python3
|
|
#
|
|
# Copyright (c) 2016-present, Facebook, Inc.
|
|
# All rights reserved.
|
|
#
|
|
# This source code is licensed under the BSD-style license found in the
|
|
# LICENSE file in the root directory of this source tree. An additional grant
|
|
# of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
from facebook.eden.ttypes import EdenError, GlobParams
|
|
from .lib import testcase
|
|
from typing import List, Optional
|
|
|
|
|
|
@testcase.eden_repo_test
|
|
class GlobTest(testcase.EdenRepoTest):
|
|
def populate_repo(self) -> None:
|
|
self.repo.write_file('hello', 'hola\n')
|
|
self.repo.write_file('adir/file', 'foo!\n')
|
|
self.repo.write_file('bdir/file', 'bar!\n')
|
|
self.repo.write_file('bdir/otherfile', 'foo!\n')
|
|
self.repo.symlink('slink', 'hello')
|
|
self.repo.write_file('cdir/subdir/new.txt', 'and improved')
|
|
self.repo.write_file('ddir/notdotfile', '')
|
|
self.repo.write_file('ddir/subdir/notdotfile', '')
|
|
self.repo.write_file('ddir/subdir/.dotfile', '')
|
|
|
|
self.repo.write_file('java/com/example/package.html', '')
|
|
self.repo.write_file('java/com/example/Example.java', '')
|
|
self.repo.write_file('java/com/example/foo/Foo.java', '')
|
|
self.repo.write_file('java/com/example/foo/bar/Bar.java', '')
|
|
self.repo.write_file('java/com/example/foo/bar/baz/Baz.java', '')
|
|
|
|
self.repo.commit('Commit 1.')
|
|
|
|
def setUp(self) -> None:
|
|
super().setUp()
|
|
self.client = self.get_thrift_client()
|
|
self.client.open()
|
|
self.addCleanup(self.client.close)
|
|
|
|
def test_exact_path_component_match(self) -> None:
|
|
self.assert_glob(['hello'], ['hello'])
|
|
self.assert_glob(['ddir/subdir/.dotfile'], ['ddir/subdir/.dotfile'])
|
|
|
|
def test_wildcard_path_component_match(self) -> None:
|
|
self.assert_glob(['hel*'], ['hello'])
|
|
self.assert_glob(['ad*'], ['adir'])
|
|
self.assert_glob(['a*/file'], ['adir/file'])
|
|
|
|
def test_no_accidental_substring_match(self) -> None:
|
|
self.assert_glob(['hell'], [], msg='No accidental substring match')
|
|
|
|
def test_match_all_files_in_directory(self) -> None:
|
|
self.assert_glob(['bdir/*'], ['bdir/file', 'bdir/otherfile'])
|
|
|
|
def test_match_all_files_in_directory_with_dotfile(self) -> None:
|
|
self.assert_glob(['ddir/subdir/*'], ['ddir/subdir/notdotfile'])
|
|
|
|
def test_overlapping_globs(self) -> None:
|
|
self.assert_glob(
|
|
['adir/*', '**/file'], ['adir/file', 'bdir/file'],
|
|
msg='De-duplicate results from multiple globs'
|
|
)
|
|
|
|
def test_recursive_wildcard_prefix(self) -> None:
|
|
self.assert_glob(['**/file'], ['adir/file', 'bdir/file'])
|
|
|
|
def test_recursive_wildcard_suffix(self) -> None:
|
|
self.assert_glob(['adir/**'], ['adir/file'])
|
|
self.assert_glob(['adir/**/*'], ['adir/file'])
|
|
|
|
def test_recursive_wildcard_suffix_with_dotfile(self) -> None:
|
|
self.assert_glob(
|
|
['ddir/**'],
|
|
['ddir/notdotfile', 'ddir/subdir', 'ddir/subdir/notdotfile']
|
|
)
|
|
self.assert_glob(
|
|
['ddir/**'], [
|
|
'ddir/subdir', 'ddir/subdir/.dotfile', 'ddir/notdotfile',
|
|
'ddir/subdir/notdotfile'
|
|
],
|
|
include_dotfiles=True
|
|
)
|
|
|
|
self.assert_glob(
|
|
['ddir/**/*'],
|
|
['ddir/notdotfile', 'ddir/subdir', 'ddir/subdir/notdotfile'],
|
|
)
|
|
self.assert_glob(
|
|
['ddir/**/*'], [
|
|
'ddir/subdir', 'ddir/subdir/.dotfile', 'ddir/notdotfile',
|
|
'ddir/subdir/notdotfile'
|
|
],
|
|
include_dotfiles=True
|
|
)
|
|
|
|
def test_qualified_recursive_wildcard(self) -> None:
|
|
self.assert_glob(
|
|
['java/com/**/*.java'], [
|
|
'java/com/example/Example.java',
|
|
'java/com/example/foo/Foo.java',
|
|
'java/com/example/foo/bar/Bar.java',
|
|
'java/com/example/foo/bar/baz/Baz.java',
|
|
]
|
|
)
|
|
self.assert_glob(
|
|
['java/com/example/*/*.java'], [
|
|
'java/com/example/foo/Foo.java',
|
|
]
|
|
)
|
|
|
|
def test_malformed_query(self) -> None:
|
|
with self.assertRaises(EdenError) as ctx:
|
|
self.client.glob(self.mount, ['adir['])
|
|
self.assertIn('unterminated bracket sequence', str(ctx.exception))
|
|
|
|
def assert_glob(
|
|
self,
|
|
globs: List[str],
|
|
expected_matches: List[str],
|
|
include_dotfiles: bool = False,
|
|
msg: Optional[str] = None
|
|
) -> None:
|
|
params = GlobParams(self.mount, globs, include_dotfiles)
|
|
self.assertCountEqual(
|
|
expected_matches,
|
|
self.client.globFiles(params).matchingFiles,
|
|
msg=msg
|
|
)
|
|
|
|
# Also verify behavior of legacy Thrift API.
|
|
if include_dotfiles:
|
|
self.assertCountEqual(
|
|
expected_matches, self.client.glob(self.mount, globs), msg=msg
|
|
)
|