Show More
@@ -1,112 +1,119 b'' | |||||
1 | use crate::error::CommandError; |
|
1 | use crate::error::CommandError; | |
2 | use crate::ui::Ui; |
|
2 | use crate::ui::{print_narrow_sparse_warnings, Ui}; | |
3 | use crate::utils::path_utils::RelativizePaths; |
|
3 | use crate::utils::path_utils::RelativizePaths; | |
4 | use clap::Arg; |
|
4 | use clap::Arg; | |
|
5 | use hg::narrow; | |||
5 | use hg::operations::list_rev_tracked_files; |
|
6 | use hg::operations::list_rev_tracked_files; | |
6 | use hg::repo::Repo; |
|
7 | use hg::repo::Repo; | |
7 | use hg::utils::filter_map_results; |
|
8 | use hg::utils::filter_map_results; | |
8 | use hg::utils::hg_path::HgPath; |
|
9 | use hg::utils::hg_path::HgPath; | |
9 | use rayon::prelude::*; |
|
10 | use rayon::prelude::*; | |
10 |
|
11 | |||
11 | pub const HELP_TEXT: &str = " |
|
12 | pub const HELP_TEXT: &str = " | |
12 | List tracked files. |
|
13 | List tracked files. | |
13 |
|
14 | |||
14 | Returns 0 on success. |
|
15 | Returns 0 on success. | |
15 | "; |
|
16 | "; | |
16 |
|
17 | |||
17 | pub fn args() -> clap::Command { |
|
18 | pub fn args() -> clap::Command { | |
18 | clap::command!("files") |
|
19 | clap::command!("files") | |
19 | .arg( |
|
20 | .arg( | |
20 | Arg::new("rev") |
|
21 | Arg::new("rev") | |
21 | .help("search the repository as it is in REV") |
|
22 | .help("search the repository as it is in REV") | |
22 | .short('r') |
|
23 | .short('r') | |
23 | .long("revision") |
|
24 | .long("revision") | |
24 | .value_name("REV"), |
|
25 | .value_name("REV"), | |
25 | ) |
|
26 | ) | |
26 | .about(HELP_TEXT) |
|
27 | .about(HELP_TEXT) | |
27 | } |
|
28 | } | |
28 |
|
29 | |||
29 | pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { |
|
30 | pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { | |
30 | let relative = invocation.config.get(b"ui", b"relative-paths"); |
|
31 | let relative = invocation.config.get(b"ui", b"relative-paths"); | |
31 | if relative.is_some() { |
|
32 | if relative.is_some() { | |
32 | return Err(CommandError::unsupported( |
|
33 | return Err(CommandError::unsupported( | |
33 | "non-default ui.relative-paths", |
|
34 | "non-default ui.relative-paths", | |
34 | )); |
|
35 | )); | |
35 | } |
|
36 | } | |
36 |
|
37 | |||
37 | let rev = invocation.subcommand_args.get_one::<String>("rev"); |
|
38 | let rev = invocation.subcommand_args.get_one::<String>("rev"); | |
38 |
|
39 | |||
39 | let repo = invocation.repo?; |
|
40 | let repo = invocation.repo?; | |
40 |
|
41 | |||
41 | // It seems better if this check is removed: this would correspond to |
|
42 | // It seems better if this check is removed: this would correspond to | |
42 | // automatically enabling the extension if the repo requires it. |
|
43 | // automatically enabling the extension if the repo requires it. | |
43 | // However we need this check to be in sync with vanilla hg so hg tests |
|
44 | // However we need this check to be in sync with vanilla hg so hg tests | |
44 | // pass. |
|
45 | // pass. | |
45 | if repo.has_sparse() |
|
46 | if repo.has_sparse() | |
46 | && invocation.config.get(b"extensions", b"sparse").is_none() |
|
47 | && invocation.config.get(b"extensions", b"sparse").is_none() | |
47 | { |
|
48 | { | |
48 | return Err(CommandError::unsupported( |
|
49 | return Err(CommandError::unsupported( | |
49 | "repo is using sparse, but sparse extension is not enabled", |
|
50 | "repo is using sparse, but sparse extension is not enabled", | |
50 | )); |
|
51 | )); | |
51 | } |
|
52 | } | |
52 |
|
53 | |||
53 | if let Some(rev) = rev { |
|
54 | if let Some(rev) = rev { | |
54 | if repo.has_narrow() { |
|
55 | if repo.has_narrow() { | |
55 | return Err(CommandError::unsupported( |
|
56 | return Err(CommandError::unsupported( | |
56 | "rhg files -r <rev> is not supported in narrow clones", |
|
57 | "rhg files -r <rev> is not supported in narrow clones", | |
57 | )); |
|
58 | )); | |
58 | } |
|
59 | } | |
59 | let files = list_rev_tracked_files(repo, rev) |
|
60 | let files = list_rev_tracked_files(repo, rev) | |
60 | .map_err(|e| (e, rev.as_ref()))?; |
|
61 | .map_err(|e| (e, rev.as_ref()))?; | |
61 | display_files(invocation.ui, repo, files.iter()) |
|
62 | display_files(invocation.ui, repo, files.iter()) | |
62 | } else { |
|
63 | } else { | |
63 |
// The dirstate always reflects the sparse narrowspec |
|
64 | // The dirstate always reflects the sparse narrowspec. | |
64 | // we only have sparse without narrow all is fine. |
|
65 | let (narrow_matcher, narrow_warnings) = narrow::matcher(repo)?; | |
65 | // If we have narrow, then [hg files] needs to check if |
|
66 | print_narrow_sparse_warnings( | |
66 | // the store narrowspec is in sync with the one of the dirstate, |
|
67 | &narrow_warnings, | |
67 | // so we can't support that without explicit code. |
|
68 | &[], | |
68 | if repo.has_narrow() { |
|
69 | invocation.ui, | |
69 | return Err(CommandError::unsupported( |
|
70 | repo, | |
70 | "rhg files is not supported in narrow clones", |
|
71 | )?; | |
71 | )); |
|
|||
72 | } |
|
|||
73 | let dirstate = repo.dirstate_map()?; |
|
72 | let dirstate = repo.dirstate_map()?; | |
74 | let files_res: Result<Vec<_>, _> = |
|
73 | let files_res: Result<Vec<_>, _> = | |
75 | filter_map_results(dirstate.iter(), |(path, entry)| { |
|
74 | filter_map_results(dirstate.iter(), |(path, entry)| { | |
76 |
Ok(if entry.tracked() |
|
75 | Ok(if entry.tracked() && narrow_matcher.matches(path) { | |
|
76 | Some(path) | |||
|
77 | } else { | |||
|
78 | None | |||
|
79 | }) | |||
77 | }) |
|
80 | }) | |
78 | .collect(); |
|
81 | .collect(); | |
79 |
|
82 | |||
80 | let mut files = files_res?; |
|
83 | let mut files = files_res?; | |
81 | files.par_sort_unstable(); |
|
84 | files.par_sort_unstable(); | |
82 |
|
85 | |||
83 | display_files(invocation.ui, repo, files.into_iter().map(Ok)) |
|
86 | display_files( | |
|
87 | invocation.ui, | |||
|
88 | repo, | |||
|
89 | files.into_iter().map::<Result<_, CommandError>, _>(Ok), | |||
|
90 | ) | |||
84 | } |
|
91 | } | |
85 | } |
|
92 | } | |
86 |
|
93 | |||
87 | fn display_files<'a, E>( |
|
94 | fn display_files<'a, E>( | |
88 | ui: &Ui, |
|
95 | ui: &Ui, | |
89 | repo: &Repo, |
|
96 | repo: &Repo, | |
90 | files: impl IntoIterator<Item = Result<&'a HgPath, E>>, |
|
97 | files: impl IntoIterator<Item = Result<&'a HgPath, E>>, | |
91 | ) -> Result<(), CommandError> |
|
98 | ) -> Result<(), CommandError> | |
92 | where |
|
99 | where | |
93 | CommandError: From<E>, |
|
100 | CommandError: From<E>, | |
94 | { |
|
101 | { | |
95 | let mut stdout = ui.stdout_buffer(); |
|
102 | let mut stdout = ui.stdout_buffer(); | |
96 | let mut any = false; |
|
103 | let mut any = false; | |
97 |
|
104 | |||
98 | let relativize = RelativizePaths::new(repo)?; |
|
105 | let relativize = RelativizePaths::new(repo)?; | |
99 | for result in files { |
|
106 | for result in files { | |
100 | let path = result?; |
|
107 | let path = result?; | |
101 | stdout.write_all(&relativize.relativize(path))?; |
|
108 | stdout.write_all(&relativize.relativize(path))?; | |
102 | stdout.write_all(b"\n")?; |
|
109 | stdout.write_all(b"\n")?; | |
103 | any = true; |
|
110 | any = true; | |
104 | } |
|
111 | } | |
105 |
|
112 | |||
106 | stdout.flush()?; |
|
113 | stdout.flush()?; | |
107 | if any { |
|
114 | if any { | |
108 | Ok(()) |
|
115 | Ok(()) | |
109 | } else { |
|
116 | } else { | |
110 | Err(CommandError::Unsuccessful) |
|
117 | Err(CommandError::Unsuccessful) | |
111 | } |
|
118 | } | |
112 | } |
|
119 | } |
@@ -1,112 +1,121 b'' | |||||
1 | #require rhg |
|
1 | #require rhg | |
2 |
|
2 | |||
3 | $ NO_FALLBACK="env RHG_ON_UNSUPPORTED=abort" |
|
3 | $ NO_FALLBACK="env RHG_ON_UNSUPPORTED=abort" | |
4 |
|
4 | |||
5 | Rhg works well when sparse working copy is enabled. |
|
5 | Rhg works well when sparse working copy is enabled. | |
6 |
|
6 | |||
7 | $ cd "$TESTTMP" |
|
7 | $ cd "$TESTTMP" | |
8 | $ hg init repo-sparse |
|
8 | $ hg init repo-sparse | |
9 | $ cd repo-sparse |
|
9 | $ cd repo-sparse | |
10 | $ cat > .hg/hgrc <<EOF |
|
10 | $ cat > .hg/hgrc <<EOF | |
11 | > [extensions] |
|
11 | > [extensions] | |
12 | > sparse= |
|
12 | > sparse= | |
13 | > EOF |
|
13 | > EOF | |
14 |
|
14 | |||
15 | $ echo a > show |
|
15 | $ echo a > show | |
16 | $ echo x > hide |
|
16 | $ echo x > hide | |
17 | $ mkdir dir1 dir2 |
|
17 | $ mkdir dir1 dir2 | |
18 | $ echo x > dir1/x |
|
18 | $ echo x > dir1/x | |
19 | $ echo y > dir1/y |
|
19 | $ echo y > dir1/y | |
20 | $ echo z > dir2/z |
|
20 | $ echo z > dir2/z | |
21 |
|
21 | |||
22 | $ hg ci -Aqm 'initial' |
|
22 | $ hg ci -Aqm 'initial' | |
23 | $ hg debugsparse --include 'show' |
|
23 | $ hg debugsparse --include 'show' | |
24 | $ ls -A |
|
24 | $ ls -A | |
25 | .hg |
|
25 | .hg | |
26 | show |
|
26 | show | |
27 |
|
27 | |||
28 | $ tip=$(hg log -r . --template '{node}') |
|
28 | $ tip=$(hg log -r . --template '{node}') | |
29 | $ $NO_FALLBACK rhg files -r "$tip" |
|
29 | $ $NO_FALLBACK rhg files -r "$tip" | |
30 | dir1/x |
|
30 | dir1/x | |
31 | dir1/y |
|
31 | dir1/y | |
32 | dir2/z |
|
32 | dir2/z | |
33 | hide |
|
33 | hide | |
34 | show |
|
34 | show | |
35 | $ $NO_FALLBACK rhg files |
|
35 | $ $NO_FALLBACK rhg files | |
36 | show |
|
36 | show | |
37 |
|
37 | |||
38 | $ $NO_FALLBACK rhg cat -r "$tip" hide |
|
38 | $ $NO_FALLBACK rhg cat -r "$tip" hide | |
39 | x |
|
39 | x | |
40 |
|
40 | |||
41 | $ cd .. |
|
41 | $ cd .. | |
42 |
|
42 | |||
43 | We support most things when narrow is enabled, too, with a couple of caveats. |
|
43 | We support most things when narrow is enabled, too, with a couple of caveats. | |
44 |
|
44 | |||
45 | $ . "$TESTDIR/narrow-library.sh" |
|
45 | $ . "$TESTDIR/narrow-library.sh" | |
46 | $ real_hg=$RHG_FALLBACK_EXECUTABLE |
|
46 | $ real_hg=$RHG_FALLBACK_EXECUTABLE | |
47 |
|
47 | |||
48 | $ cat >> $HGRCPATH <<EOF |
|
48 | $ cat >> $HGRCPATH <<EOF | |
49 | > [extensions] |
|
49 | > [extensions] | |
50 | > narrow= |
|
50 | > narrow= | |
51 | > EOF |
|
51 | > EOF | |
52 |
|
52 | |||
53 | $ hg clone --narrow ./repo-sparse repo-narrow --include dir1 |
|
53 | $ hg clone --narrow ./repo-sparse repo-narrow --include dir1 | |
54 | requesting all changes |
|
54 | requesting all changes | |
55 | adding changesets |
|
55 | adding changesets | |
56 | adding manifests |
|
56 | adding manifests | |
57 | adding file changes |
|
57 | adding file changes | |
58 | added 1 changesets with 2 changes to 2 files |
|
58 | added 1 changesets with 2 changes to 2 files | |
59 | new changesets 6d714a4a2998 |
|
59 | new changesets 6d714a4a2998 | |
60 | updating to branch default |
|
60 | updating to branch default | |
61 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
|
61 | 2 files updated, 0 files merged, 0 files removed, 0 files unresolved | |
62 |
|
62 | |||
63 | $ cd repo-narrow |
|
63 | $ cd repo-narrow | |
64 |
|
64 | |||
65 | $ $NO_FALLBACK rhg cat -r "$tip" dir1/x |
|
65 | $ $NO_FALLBACK rhg cat -r "$tip" dir1/x | |
66 | x |
|
66 | x | |
67 | $ "$real_hg" cat -r "$tip" dir1/x |
|
67 | $ "$real_hg" cat -r "$tip" dir1/x | |
68 | x |
|
68 | x | |
69 |
|
69 | |||
70 | TODO: bad error message |
|
70 | TODO: bad error message | |
71 |
|
71 | |||
72 | $ $NO_FALLBACK rhg cat -r "$tip" hide |
|
72 | $ $NO_FALLBACK rhg cat -r "$tip" hide | |
73 | abort: invalid revision identifier: 6d714a4a2998cbfd0620db44da58b749f6565d63 |
|
73 | abort: invalid revision identifier: 6d714a4a2998cbfd0620db44da58b749f6565d63 | |
74 | [255] |
|
74 | [255] | |
75 | $ "$real_hg" cat -r "$tip" hide |
|
75 | $ "$real_hg" cat -r "$tip" hide | |
76 | [1] |
|
76 | [1] | |
77 |
|
77 | |||
78 | A naive implementation of [rhg files] leaks the paths that are supposed to be |
|
78 | A naive implementation of [rhg files] leaks the paths that are supposed to be | |
79 | hidden by narrow, so we just fall back to hg. |
|
79 | hidden by narrow, so we just fall back to hg when accessing a revision. | |
80 |
|
80 | |||
81 | $ $NO_FALLBACK rhg files -r "$tip" |
|
81 | $ $NO_FALLBACK rhg files -r "$tip" | |
82 | unsupported feature: rhg files -r <rev> is not supported in narrow clones |
|
82 | unsupported feature: rhg files -r <rev> is not supported in narrow clones | |
83 | [252] |
|
83 | [252] | |
84 | $ "$real_hg" files -r "$tip" |
|
84 | $ "$real_hg" files -r "$tip" | |
85 | dir1/x |
|
85 | dir1/x | |
86 | dir1/y |
|
86 | dir1/y | |
87 |
|
87 | |||
|
88 | The working copy version works with narrow correctly | |||
|
89 | ||||
|
90 | $ $NO_FALLBACK rhg files | |||
|
91 | dir1/x | |||
|
92 | dir1/y | |||
|
93 | $ "$real_hg" files | |||
|
94 | dir1/x | |||
|
95 | dir1/y | |||
|
96 | ||||
88 | Hg status needs to do some filtering based on narrow spec |
|
97 | Hg status needs to do some filtering based on narrow spec | |
89 |
|
98 | |||
90 | $ mkdir dir2 |
|
99 | $ mkdir dir2 | |
91 | $ touch dir2/q |
|
100 | $ touch dir2/q | |
92 | $ "$real_hg" status |
|
101 | $ "$real_hg" status | |
93 | $ $NO_FALLBACK rhg --config rhg.status=true status |
|
102 | $ $NO_FALLBACK rhg --config rhg.status=true status | |
94 |
|
103 | |||
95 | Adding "orphaned" index files: |
|
104 | Adding "orphaned" index files: | |
96 |
|
105 | |||
97 | $ (cd ..; cp repo-sparse/.hg/store/data/hide.i repo-narrow/.hg/store/data/hide.i) |
|
106 | $ (cd ..; cp repo-sparse/.hg/store/data/hide.i repo-narrow/.hg/store/data/hide.i) | |
98 | $ (cd ..; mkdir repo-narrow/.hg/store/data/dir2; cp repo-sparse/.hg/store/data/dir2/z.i repo-narrow/.hg/store/data/dir2/z.i) |
|
107 | $ (cd ..; mkdir repo-narrow/.hg/store/data/dir2; cp repo-sparse/.hg/store/data/dir2/z.i repo-narrow/.hg/store/data/dir2/z.i) | |
99 | $ "$real_hg" verify -q |
|
108 | $ "$real_hg" verify -q | |
100 |
|
109 | |||
101 | $ "$real_hg" files -r "$tip" |
|
110 | $ "$real_hg" files -r "$tip" | |
102 | dir1/x |
|
111 | dir1/x | |
103 | dir1/y |
|
112 | dir1/y | |
104 |
|
113 | |||
105 | # TODO: even though [hg files] hides the orphaned dir2/z, [hg cat] still shows it. |
|
114 | # TODO: even though [hg files] hides the orphaned dir2/z, [hg cat] still shows it. | |
106 | # rhg has the same issue, but at least it's not specific to rhg. |
|
115 | # rhg has the same issue, but at least it's not specific to rhg. | |
107 | # This is despite [hg verify] succeeding above. |
|
116 | # This is despite [hg verify] succeeding above. | |
108 |
|
117 | |||
109 | $ $NO_FALLBACK rhg cat -r "$tip" dir2/z |
|
118 | $ $NO_FALLBACK rhg cat -r "$tip" dir2/z | |
110 | z |
|
119 | z | |
111 | $ "$real_hg" cat -r "$tip" dir2/z |
|
120 | $ "$real_hg" cat -r "$tip" dir2/z | |
112 | z |
|
121 | z |
General Comments 0
You need to be logged in to leave comments.
Login now