##// END OF EJS Templates
rust: introduce Repo and Vfs types for filesystem abstraction...
Simon Sapin -
r46782:8a491439 default
parent child Browse files
Show More
@@ -0,0 +1,92 b''
1 use crate::operations::{find_root, FindRootError};
2 use crate::requirements;
3 use memmap::{Mmap, MmapOptions};
4 use std::path::{Path, PathBuf};
5
6 /// A repository on disk
7 pub struct Repo {
8 working_directory: PathBuf,
9 dot_hg: PathBuf,
10 store: PathBuf,
11 }
12
13 /// Filesystem access abstraction for the contents of a given "base" diretory
14 #[derive(Clone, Copy)]
15 pub(crate) struct Vfs<'a> {
16 base: &'a Path,
17 }
18
19 impl Repo {
20 /// Returns `None` if the given path doesn’t look like a repository
21 /// (doesn’t contain a `.hg` sub-directory).
22 pub fn for_path(root: impl Into<PathBuf>) -> Self {
23 let working_directory = root.into();
24 let dot_hg = working_directory.join(".hg");
25 Self {
26 store: dot_hg.join("store"),
27 dot_hg,
28 working_directory,
29 }
30 }
31
32 pub fn find() -> Result<Self, FindRootError> {
33 find_root().map(Self::for_path)
34 }
35
36 pub fn check_requirements(
37 &self,
38 ) -> Result<(), requirements::RequirementsError> {
39 requirements::check(self)
40 }
41
42 pub fn working_directory_path(&self) -> &Path {
43 &self.working_directory
44 }
45
46 /// For accessing repository files (in `.hg`), except for the store
47 /// (`.hg/store`).
48 pub(crate) fn hg_vfs(&self) -> Vfs<'_> {
49 Vfs { base: &self.dot_hg }
50 }
51
52 /// For accessing repository store files (in `.hg/store`)
53 pub(crate) fn store_vfs(&self) -> Vfs<'_> {
54 Vfs { base: &self.store }
55 }
56
57 /// For accessing the working copy
58
59 // The undescore prefix silences the "never used" warning. Remove before
60 // using.
61 pub(crate) fn _working_directory_vfs(&self) -> Vfs<'_> {
62 Vfs {
63 base: &self.working_directory,
64 }
65 }
66 }
67
68 impl Vfs<'_> {
69 pub(crate) fn read(
70 &self,
71 relative_path: impl AsRef<Path>,
72 ) -> std::io::Result<Vec<u8>> {
73 std::fs::read(self.base.join(relative_path))
74 }
75
76 pub(crate) fn open(
77 &self,
78 relative_path: impl AsRef<Path>,
79 ) -> std::io::Result<std::fs::File> {
80 std::fs::File::open(self.base.join(relative_path))
81 }
82
83 pub(crate) fn mmap_open(
84 &self,
85 relative_path: impl AsRef<Path>,
86 ) -> std::io::Result<Mmap> {
87 let file = self.open(relative_path)?;
88 // TODO: what are the safety requirements here?
89 let mmap = unsafe { MmapOptions::new().map(&file) }?;
90 Ok(mmap)
91 }
92 }
@@ -23,6 +23,7 b' pub use dirstate::{'
23 pub mod copy_tracing;
23 pub mod copy_tracing;
24 mod filepatterns;
24 mod filepatterns;
25 pub mod matchers;
25 pub mod matchers;
26 pub mod repo;
26 pub mod revlog;
27 pub mod revlog;
27 pub use revlog::*;
28 pub use revlog::*;
28 pub mod operations;
29 pub mod operations;
@@ -6,8 +6,9 b''
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 use std::convert::From;
8 use std::convert::From;
9 use std::path::{Path, PathBuf};
9 use std::path::PathBuf;
10
10
11 use crate::repo::Repo;
11 use crate::revlog::changelog::Changelog;
12 use crate::revlog::changelog::Changelog;
12 use crate::revlog::manifest::Manifest;
13 use crate::revlog::manifest::Manifest;
13 use crate::revlog::path_encode::path_encode;
14 use crate::revlog::path_encode::path_encode;
@@ -75,12 +76,12 b' impl From<RevlogError> for CatRevError {'
75 /// * `rev`: The revision to cat the files from.
76 /// * `rev`: The revision to cat the files from.
76 /// * `files`: The files to output.
77 /// * `files`: The files to output.
77 pub fn cat(
78 pub fn cat(
78 root: &Path,
79 repo: &Repo,
79 rev: &str,
80 rev: &str,
80 files: &[HgPathBuf],
81 files: &[HgPathBuf],
81 ) -> Result<Vec<u8>, CatRevError> {
82 ) -> Result<Vec<u8>, CatRevError> {
82 let changelog = Changelog::open(&root)?;
83 let changelog = Changelog::open(repo)?;
83 let manifest = Manifest::open(&root)?;
84 let manifest = Manifest::open(repo)?;
84
85
85 let changelog_entry = match rev.parse::<Revision>() {
86 let changelog_entry = match rev.parse::<Revision>() {
86 Ok(rev) => changelog.get_rev(rev)?,
87 Ok(rev) => changelog.get_rev(rev)?,
@@ -99,10 +100,11 b' pub fn cat('
99 for (manifest_file, node_bytes) in manifest_entry.files_with_nodes() {
100 for (manifest_file, node_bytes) in manifest_entry.files_with_nodes() {
100 for cat_file in files.iter() {
101 for cat_file in files.iter() {
101 if cat_file.as_bytes() == manifest_file.as_bytes() {
102 if cat_file.as_bytes() == manifest_file.as_bytes() {
102 let index_path = store_path(root, manifest_file, b".i");
103 let index_path = store_path(manifest_file, b".i");
103 let data_path = store_path(root, manifest_file, b".d");
104 let data_path = store_path(manifest_file, b".d");
104
105
105 let file_log = Revlog::open(&index_path, Some(&data_path))?;
106 let file_log =
107 Revlog::open(repo, &index_path, Some(&data_path))?;
106 let file_node = Node::from_hex(node_bytes)
108 let file_node = Node::from_hex(node_bytes)
107 .map_err(|_| CatRevErrorKind::CorruptedRevlog)?;
109 .map_err(|_| CatRevErrorKind::CorruptedRevlog)?;
108 let file_rev = file_log.get_node_rev((&file_node).into())?;
110 let file_rev = file_log.get_node_rev((&file_node).into())?;
@@ -126,14 +128,8 b' pub fn cat('
126 Ok(bytes)
128 Ok(bytes)
127 }
129 }
128
130
129 fn store_path(root: &Path, hg_path: &HgPath, suffix: &[u8]) -> PathBuf {
131 fn store_path(hg_path: &HgPath, suffix: &[u8]) -> PathBuf {
130 let encoded_bytes =
132 let encoded_bytes =
131 path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat());
133 path_encode(&[b"data/", hg_path.as_bytes(), suffix].concat());
132 [
134 get_path_from_bytes(&encoded_bytes).into()
133 root,
134 &Path::new(".hg/store/"),
135 get_path_from_bytes(&encoded_bytes),
136 ]
137 .iter()
138 .collect()
139 }
135 }
@@ -5,8 +5,7 b''
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 use std::path::Path;
8 use crate::repo::Repo;
9
10 use crate::revlog::revlog::{Revlog, RevlogError};
9 use crate::revlog::revlog::{Revlog, RevlogError};
11 use crate::revlog::NodePrefix;
10 use crate::revlog::NodePrefix;
12 use crate::revlog::Revision;
11 use crate::revlog::Revision;
@@ -79,15 +78,15 b' impl From<RevlogError> for DebugDataErro'
79
78
80 /// Dump the contents data of a revision.
79 /// Dump the contents data of a revision.
81 pub fn debug_data(
80 pub fn debug_data(
82 root: &Path,
81 repo: &Repo,
83 rev: &str,
82 rev: &str,
84 kind: DebugDataKind,
83 kind: DebugDataKind,
85 ) -> Result<Vec<u8>, DebugDataError> {
84 ) -> Result<Vec<u8>, DebugDataError> {
86 let index_file = match kind {
85 let index_file = match kind {
87 DebugDataKind::Changelog => root.join(".hg/store/00changelog.i"),
86 DebugDataKind::Changelog => "00changelog.i",
88 DebugDataKind::Manifest => root.join(".hg/store/00manifest.i"),
87 DebugDataKind::Manifest => "00manifest.i",
89 };
88 };
90 let revlog = Revlog::open(&index_file, None)?;
89 let revlog = Revlog::open(repo, index_file, None)?;
91
90
92 let data = match rev.parse::<Revision>() {
91 let data = match rev.parse::<Revision>() {
93 Ok(rev) => revlog.get_rev_data(rev)?,
92 Ok(rev) => revlog.get_rev_data(rev)?,
@@ -6,6 +6,7 b''
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 use crate::dirstate::parsers::parse_dirstate;
8 use crate::dirstate::parsers::parse_dirstate;
9 use crate::repo::Repo;
9 use crate::revlog::changelog::Changelog;
10 use crate::revlog::changelog::Changelog;
10 use crate::revlog::manifest::{Manifest, ManifestEntry};
11 use crate::revlog::manifest::{Manifest, ManifestEntry};
11 use crate::revlog::node::{Node, NodePrefix};
12 use crate::revlog::node::{Node, NodePrefix};
@@ -15,8 +16,6 b' use crate::utils::hg_path::HgPath;'
15 use crate::{DirstateParseError, EntryState};
16 use crate::{DirstateParseError, EntryState};
16 use rayon::prelude::*;
17 use rayon::prelude::*;
17 use std::convert::From;
18 use std::convert::From;
18 use std::fs;
19 use std::path::Path;
20
19
21 /// Kind of error encountered by `ListDirstateTrackedFiles`
20 /// Kind of error encountered by `ListDirstateTrackedFiles`
22 #[derive(Debug)]
21 #[derive(Debug)]
@@ -57,9 +56,8 b' pub struct Dirstate {'
57 }
56 }
58
57
59 impl Dirstate {
58 impl Dirstate {
60 pub fn new(root: &Path) -> Result<Self, ListDirstateTrackedFilesError> {
59 pub fn new(repo: &Repo) -> Result<Self, ListDirstateTrackedFilesError> {
61 let dirstate = root.join(".hg/dirstate");
60 let content = repo.hg_vfs().read("dirstate")?;
62 let content = fs::read(&dirstate)?;
63 Ok(Self { content })
61 Ok(Self { content })
64 }
62 }
65
63
@@ -138,11 +136,11 b' impl From<RevlogError> for ListRevTracke'
138
136
139 /// List files under Mercurial control at a given revision.
137 /// List files under Mercurial control at a given revision.
140 pub fn list_rev_tracked_files(
138 pub fn list_rev_tracked_files(
141 root: &Path,
139 repo: &Repo,
142 rev: &str,
140 rev: &str,
143 ) -> Result<FilesForRev, ListRevTrackedFilesError> {
141 ) -> Result<FilesForRev, ListRevTrackedFilesError> {
144 let changelog = Changelog::open(root)?;
142 let changelog = Changelog::open(repo)?;
145 let manifest = Manifest::open(root)?;
143 let manifest = Manifest::open(repo)?;
146
144
147 let changelog_entry = match rev.parse::<Revision>() {
145 let changelog_entry = match rev.parse::<Revision>() {
148 Ok(rev) => changelog.get_rev(rev)?,
146 Ok(rev) => changelog.get_rev(rev)?,
@@ -1,5 +1,5 b''
1 use crate::repo::Repo;
1 use std::io;
2 use std::io;
2 use std::path::Path;
3
3
4 #[derive(Debug)]
4 #[derive(Debug)]
5 pub enum RequirementsError {
5 pub enum RequirementsError {
@@ -33,8 +33,8 b' fn parse(bytes: &[u8]) -> Result<Vec<Str'
33 .collect()
33 .collect()
34 }
34 }
35
35
36 pub fn load(repo_root: &Path) -> Result<Vec<String>, RequirementsError> {
36 pub fn load(repo: &Repo) -> Result<Vec<String>, RequirementsError> {
37 match std::fs::read(repo_root.join(".hg").join("requires")) {
37 match repo.hg_vfs().read("requires") {
38 Ok(bytes) => parse(&bytes).map_err(|()| RequirementsError::Corrupted),
38 Ok(bytes) => parse(&bytes).map_err(|()| RequirementsError::Corrupted),
39
39
40 // Treat a missing file the same as an empty file.
40 // Treat a missing file the same as an empty file.
@@ -52,8 +52,8 b' pub fn load(repo_root: &Path) -> Result<'
52 }
52 }
53 }
53 }
54
54
55 pub fn check(repo_root: &Path) -> Result<(), RequirementsError> {
55 pub fn check(repo: &Repo) -> Result<(), RequirementsError> {
56 for feature in load(repo_root)? {
56 for feature in load(repo)? {
57 if !SUPPORTED.contains(&&*feature) {
57 if !SUPPORTED.contains(&&*feature) {
58 return Err(RequirementsError::Unsupported { feature });
58 return Err(RequirementsError::Unsupported { feature });
59 }
59 }
@@ -1,7 +1,7 b''
1 use crate::repo::Repo;
1 use crate::revlog::revlog::{Revlog, RevlogError};
2 use crate::revlog::revlog::{Revlog, RevlogError};
2 use crate::revlog::NodePrefixRef;
3 use crate::revlog::NodePrefixRef;
3 use crate::revlog::Revision;
4 use crate::revlog::Revision;
4 use std::path::Path;
5
5
6 /// A specialized `Revlog` to work with `changelog` data format.
6 /// A specialized `Revlog` to work with `changelog` data format.
7 pub struct Changelog {
7 pub struct Changelog {
@@ -11,9 +11,8 b' pub struct Changelog {'
11
11
12 impl Changelog {
12 impl Changelog {
13 /// Open the `changelog` of a repository given by its root.
13 /// Open the `changelog` of a repository given by its root.
14 pub fn open(root: &Path) -> Result<Self, RevlogError> {
14 pub fn open(repo: &Repo) -> Result<Self, RevlogError> {
15 let index_file = root.join(".hg/store/00changelog.i");
15 let revlog = Revlog::open(repo, "00changelog.i", None)?;
16 let revlog = Revlog::open(&index_file, None)?;
17 Ok(Self { revlog })
16 Ok(Self { revlog })
18 }
17 }
19
18
@@ -1,8 +1,8 b''
1 use crate::repo::Repo;
1 use crate::revlog::revlog::{Revlog, RevlogError};
2 use crate::revlog::revlog::{Revlog, RevlogError};
2 use crate::revlog::NodePrefixRef;
3 use crate::revlog::NodePrefixRef;
3 use crate::revlog::Revision;
4 use crate::revlog::Revision;
4 use crate::utils::hg_path::HgPath;
5 use crate::utils::hg_path::HgPath;
5 use std::path::Path;
6
6
7 /// A specialized `Revlog` to work with `manifest` data format.
7 /// A specialized `Revlog` to work with `manifest` data format.
8 pub struct Manifest {
8 pub struct Manifest {
@@ -12,9 +12,8 b' pub struct Manifest {'
12
12
13 impl Manifest {
13 impl Manifest {
14 /// Open the `manifest` of a repository given by its root.
14 /// Open the `manifest` of a repository given by its root.
15 pub fn open(root: &Path) -> Result<Self, RevlogError> {
15 pub fn open(repo: &Repo) -> Result<Self, RevlogError> {
16 let index_file = root.join(".hg/store/00manifest.i");
16 let revlog = Revlog::open(repo, "00manifest.i", None)?;
17 let revlog = Revlog::open(&index_file, None)?;
18 Ok(Self { revlog })
17 Ok(Self { revlog })
19 }
18 }
20
19
@@ -2,7 +2,8 b' use memmap::Mmap;'
2 use std::convert::TryInto;
2 use std::convert::TryInto;
3 use std::path::{Path, PathBuf};
3 use std::path::{Path, PathBuf};
4
4
5 use super::revlog::{mmap_open, RevlogError};
5 use super::revlog::RevlogError;
6 use crate::repo::Repo;
6 use crate::utils::strip_suffix;
7 use crate::utils::strip_suffix;
7
8
8 const ONDISK_VERSION: u8 = 1;
9 const ONDISK_VERSION: u8 = 1;
@@ -23,10 +24,11 b' impl NodeMapDocket {'
23 /// * The docket file points to a missing (likely deleted) data file (this
24 /// * The docket file points to a missing (likely deleted) data file (this
24 /// can happen in a rare race condition).
25 /// can happen in a rare race condition).
25 pub fn read_from_file(
26 pub fn read_from_file(
27 repo: &Repo,
26 index_path: &Path,
28 index_path: &Path,
27 ) -> Result<Option<(Self, Mmap)>, RevlogError> {
29 ) -> Result<Option<(Self, Mmap)>, RevlogError> {
28 let docket_path = index_path.with_extension("n");
30 let docket_path = index_path.with_extension("n");
29 let docket_bytes = match std::fs::read(&docket_path) {
31 let docket_bytes = match repo.store_vfs().read(&docket_path) {
30 Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
32 Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
31 return Ok(None)
33 return Ok(None)
32 }
34 }
@@ -60,7 +62,7 b' impl NodeMapDocket {'
60 let data_path = rawdata_path(&docket_path, uid);
62 let data_path = rawdata_path(&docket_path, uid);
61 // TODO: use `std::fs::read` here when the `persistent-nodemap.mmap`
63 // TODO: use `std::fs::read` here when the `persistent-nodemap.mmap`
62 // config is false?
64 // config is false?
63 match mmap_open(&data_path) {
65 match repo.store_vfs().mmap_open(&data_path) {
64 Ok(mmap) => {
66 Ok(mmap) => {
65 if mmap.len() >= data_length {
67 if mmap.len() >= data_length {
66 Ok(Some((docket, mmap)))
68 Ok(Some((docket, mmap)))
@@ -1,5 +1,4 b''
1 use std::borrow::Cow;
1 use std::borrow::Cow;
2 use std::fs::File;
3 use std::io::Read;
2 use std::io::Read;
4 use std::ops::Deref;
3 use std::ops::Deref;
5 use std::path::Path;
4 use std::path::Path;
@@ -8,7 +7,6 b' use byteorder::{BigEndian, ByteOrder};'
8 use crypto::digest::Digest;
7 use crypto::digest::Digest;
9 use crypto::sha1::Sha1;
8 use crypto::sha1::Sha1;
10 use flate2::read::ZlibDecoder;
9 use flate2::read::ZlibDecoder;
11 use memmap::{Mmap, MmapOptions};
12 use micro_timer::timed;
10 use micro_timer::timed;
13 use zstd;
11 use zstd;
14
12
@@ -18,6 +16,7 b' use super::nodemap;'
18 use super::nodemap::NodeMap;
16 use super::nodemap::NodeMap;
19 use super::nodemap_docket::NodeMapDocket;
17 use super::nodemap_docket::NodeMapDocket;
20 use super::patch;
18 use super::patch;
19 use crate::repo::Repo;
21 use crate::revlog::Revision;
20 use crate::revlog::Revision;
22
21
23 pub enum RevlogError {
22 pub enum RevlogError {
@@ -30,12 +29,6 b' pub enum RevlogError {'
30 UnknowDataFormat(u8),
29 UnknowDataFormat(u8),
31 }
30 }
32
31
33 pub(super) fn mmap_open(path: &Path) -> Result<Mmap, std::io::Error> {
34 let file = File::open(path)?;
35 let mmap = unsafe { MmapOptions::new().map(&file) }?;
36 Ok(mmap)
37 }
38
39 /// Read only implementation of revlog.
32 /// Read only implementation of revlog.
40 pub struct Revlog {
33 pub struct Revlog {
41 /// When index and data are not interleaved: bytes of the revlog index.
34 /// When index and data are not interleaved: bytes of the revlog index.
@@ -55,11 +48,15 b' impl Revlog {'
55 /// interleaved.
48 /// interleaved.
56 #[timed]
49 #[timed]
57 pub fn open(
50 pub fn open(
58 index_path: &Path,
51 repo: &Repo,
52 index_path: impl AsRef<Path>,
59 data_path: Option<&Path>,
53 data_path: Option<&Path>,
60 ) -> Result<Self, RevlogError> {
54 ) -> Result<Self, RevlogError> {
61 let index_mmap =
55 let index_path = index_path.as_ref();
62 mmap_open(&index_path).map_err(RevlogError::IoError)?;
56 let index_mmap = repo
57 .store_vfs()
58 .mmap_open(&index_path)
59 .map_err(RevlogError::IoError)?;
63
60
64 let version = get_version(&index_mmap);
61 let version = get_version(&index_mmap);
65 if version != 1 {
62 if version != 1 {
@@ -77,12 +74,14 b' impl Revlog {'
77 None
74 None
78 } else {
75 } else {
79 let data_path = data_path.unwrap_or(&default_data_path);
76 let data_path = data_path.unwrap_or(&default_data_path);
80 let data_mmap =
77 let data_mmap = repo
81 mmap_open(data_path).map_err(RevlogError::IoError)?;
78 .store_vfs()
79 .mmap_open(data_path)
80 .map_err(RevlogError::IoError)?;
82 Some(Box::new(data_mmap))
81 Some(Box::new(data_mmap))
83 };
82 };
84
83
85 let nodemap = NodeMapDocket::read_from_file(index_path)?.map(
84 let nodemap = NodeMapDocket::read_from_file(repo, index_path)?.map(
86 |(docket, data)| {
85 |(docket, data)| {
87 nodemap::NodeTree::load_bytes(
86 nodemap::NodeTree::load_bytes(
88 Box::new(data),
87 Box::new(data),
@@ -2,9 +2,8 b' use crate::commands::Command;'
2 use crate::error::{CommandError, CommandErrorKind};
2 use crate::error::{CommandError, CommandErrorKind};
3 use crate::ui::utf8_to_local;
3 use crate::ui::utf8_to_local;
4 use crate::ui::Ui;
4 use crate::ui::Ui;
5 use hg::operations::find_root;
6 use hg::operations::{cat, CatRevError, CatRevErrorKind};
5 use hg::operations::{cat, CatRevError, CatRevErrorKind};
7 use hg::requirements;
6 use hg::repo::Repo;
8 use hg::utils::hg_path::HgPathBuf;
7 use hg::utils::hg_path::HgPathBuf;
9 use micro_timer::timed;
8 use micro_timer::timed;
10 use std::convert::TryFrom;
9 use std::convert::TryFrom;
@@ -32,8 +31,8 b" impl<'a> CatCommand<'a> {"
32 impl<'a> Command for CatCommand<'a> {
31 impl<'a> Command for CatCommand<'a> {
33 #[timed]
32 #[timed]
34 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
33 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
35 let root = find_root()?;
34 let repo = Repo::find()?;
36 requirements::check(&root)?;
35 repo.check_requirements()?;
37 let cwd = std::env::current_dir()
36 let cwd = std::env::current_dir()
38 .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?;
37 .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?;
39
38
@@ -41,7 +40,7 b" impl<'a> Command for CatCommand<'a> {"
41 for file in self.files.iter() {
40 for file in self.files.iter() {
42 let normalized = cwd.join(&file);
41 let normalized = cwd.join(&file);
43 let stripped = normalized
42 let stripped = normalized
44 .strip_prefix(&root)
43 .strip_prefix(&repo.working_directory_path())
45 .or(Err(CommandErrorKind::Abort(None)))?;
44 .or(Err(CommandErrorKind::Abort(None)))?;
46 let hg_file = HgPathBuf::try_from(stripped.to_path_buf())
45 let hg_file = HgPathBuf::try_from(stripped.to_path_buf())
47 .or(Err(CommandErrorKind::Abort(None)))?;
46 .or(Err(CommandErrorKind::Abort(None)))?;
@@ -50,7 +49,7 b" impl<'a> Command for CatCommand<'a> {"
50
49
51 match self.rev {
50 match self.rev {
52 Some(rev) => {
51 Some(rev) => {
53 let data = cat(&root, rev, &files)
52 let data = cat(&repo, rev, &files)
54 .map_err(|e| map_rev_error(rev, e))?;
53 .map_err(|e| map_rev_error(rev, e))?;
55 self.display(ui, &data)
54 self.display(ui, &data)
56 }
55 }
@@ -2,10 +2,10 b' use crate::commands::Command;'
2 use crate::error::{CommandError, CommandErrorKind};
2 use crate::error::{CommandError, CommandErrorKind};
3 use crate::ui::utf8_to_local;
3 use crate::ui::utf8_to_local;
4 use crate::ui::Ui;
4 use crate::ui::Ui;
5 use hg::operations::find_root;
6 use hg::operations::{
5 use hg::operations::{
7 debug_data, DebugDataError, DebugDataErrorKind, DebugDataKind,
6 debug_data, DebugDataError, DebugDataErrorKind, DebugDataKind,
8 };
7 };
8 use hg::repo::Repo;
9 use micro_timer::timed;
9 use micro_timer::timed;
10
10
11 pub const HELP_TEXT: &str = "
11 pub const HELP_TEXT: &str = "
@@ -26,8 +26,8 b" impl<'a> DebugDataCommand<'a> {"
26 impl<'a> Command for DebugDataCommand<'a> {
26 impl<'a> Command for DebugDataCommand<'a> {
27 #[timed]
27 #[timed]
28 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
28 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
29 let root = find_root()?;
29 let repo = Repo::find()?;
30 let data = debug_data(&root, self.rev, self.kind)
30 let data = debug_data(&repo, self.rev, self.kind)
31 .map_err(|e| to_command_error(self.rev, e))?;
31 .map_err(|e| to_command_error(self.rev, e))?;
32
32
33 let mut stdout = ui.stdout_buffer();
33 let mut stdout = ui.stdout_buffer();
@@ -1,7 +1,7 b''
1 use crate::commands::Command;
1 use crate::commands::Command;
2 use crate::error::CommandError;
2 use crate::error::CommandError;
3 use crate::ui::Ui;
3 use crate::ui::Ui;
4 use hg::operations::find_root;
4 use hg::repo::Repo;
5 use hg::requirements;
5 use hg::requirements;
6
6
7 pub const HELP_TEXT: &str = "
7 pub const HELP_TEXT: &str = "
@@ -18,9 +18,9 b' impl DebugRequirementsCommand {'
18
18
19 impl Command for DebugRequirementsCommand {
19 impl Command for DebugRequirementsCommand {
20 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
20 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
21 let root = find_root()?;
21 let repo = Repo::find()?;
22 let mut output = String::new();
22 let mut output = String::new();
23 for req in requirements::load(&root)? {
23 for req in requirements::load(&repo)? {
24 output.push_str(&req);
24 output.push_str(&req);
25 output.push('\n');
25 output.push('\n');
26 }
26 }
@@ -2,7 +2,6 b' use crate::commands::Command;'
2 use crate::error::{CommandError, CommandErrorKind};
2 use crate::error::{CommandError, CommandErrorKind};
3 use crate::ui::utf8_to_local;
3 use crate::ui::utf8_to_local;
4 use crate::ui::Ui;
4 use crate::ui::Ui;
5 use hg::operations::find_root;
6 use hg::operations::{
5 use hg::operations::{
7 list_rev_tracked_files, ListRevTrackedFilesError,
6 list_rev_tracked_files, ListRevTrackedFilesError,
8 ListRevTrackedFilesErrorKind,
7 ListRevTrackedFilesErrorKind,
@@ -10,10 +9,9 b' use hg::operations::{'
10 use hg::operations::{
9 use hg::operations::{
11 Dirstate, ListDirstateTrackedFilesError, ListDirstateTrackedFilesErrorKind,
10 Dirstate, ListDirstateTrackedFilesError, ListDirstateTrackedFilesErrorKind,
12 };
11 };
13 use hg::requirements;
12 use hg::repo::Repo;
14 use hg::utils::files::{get_bytes_from_path, relativize_path};
13 use hg::utils::files::{get_bytes_from_path, relativize_path};
15 use hg::utils::hg_path::{HgPath, HgPathBuf};
14 use hg::utils::hg_path::{HgPath, HgPathBuf};
16 use std::path::Path;
17
15
18 pub const HELP_TEXT: &str = "
16 pub const HELP_TEXT: &str = "
19 List tracked files.
17 List tracked files.
@@ -33,13 +31,13 b" impl<'a> FilesCommand<'a> {"
33 fn display_files(
31 fn display_files(
34 &self,
32 &self,
35 ui: &Ui,
33 ui: &Ui,
36 root: &Path,
34 repo: &Repo,
37 files: impl IntoIterator<Item = &'a HgPath>,
35 files: impl IntoIterator<Item = &'a HgPath>,
38 ) -> Result<(), CommandError> {
36 ) -> Result<(), CommandError> {
39 let cwd = std::env::current_dir()
37 let cwd = std::env::current_dir()
40 .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?;
38 .or_else(|e| Err(CommandErrorKind::CurrentDirNotFound(e)))?;
41 let rooted_cwd = cwd
39 let rooted_cwd = cwd
42 .strip_prefix(root)
40 .strip_prefix(repo.working_directory_path())
43 .expect("cwd was already checked within the repository");
41 .expect("cwd was already checked within the repository");
44 let rooted_cwd = HgPathBuf::from(get_bytes_from_path(rooted_cwd));
42 let rooted_cwd = HgPathBuf::from(get_bytes_from_path(rooted_cwd));
45
43
@@ -56,16 +54,16 b" impl<'a> FilesCommand<'a> {"
56
54
57 impl<'a> Command for FilesCommand<'a> {
55 impl<'a> Command for FilesCommand<'a> {
58 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
56 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
59 let root = find_root()?;
57 let repo = Repo::find()?;
60 requirements::check(&root)?;
58 repo.check_requirements()?;
61 if let Some(rev) = self.rev {
59 if let Some(rev) = self.rev {
62 let files = list_rev_tracked_files(&root, rev)
60 let files = list_rev_tracked_files(&repo, rev)
63 .map_err(|e| map_rev_error(rev, e))?;
61 .map_err(|e| map_rev_error(rev, e))?;
64 self.display_files(ui, &root, files.iter())
62 self.display_files(ui, &repo, files.iter())
65 } else {
63 } else {
66 let distate = Dirstate::new(&root).map_err(map_dirstate_error)?;
64 let distate = Dirstate::new(&repo).map_err(map_dirstate_error)?;
67 let files = distate.tracked_files().map_err(map_dirstate_error)?;
65 let files = distate.tracked_files().map_err(map_dirstate_error)?;
68 self.display_files(ui, &root, files)
66 self.display_files(ui, &repo, files)
69 }
67 }
70 }
68 }
71 }
69 }
@@ -2,7 +2,7 b' use crate::commands::Command;'
2 use crate::error::CommandError;
2 use crate::error::CommandError;
3 use crate::ui::Ui;
3 use crate::ui::Ui;
4 use format_bytes::format_bytes;
4 use format_bytes::format_bytes;
5 use hg::operations::find_root;
5 use hg::repo::Repo;
6 use hg::utils::files::get_bytes_from_path;
6 use hg::utils::files::get_bytes_from_path;
7
7
8 pub const HELP_TEXT: &str = "
8 pub const HELP_TEXT: &str = "
@@ -21,12 +21,9 b' impl RootCommand {'
21
21
22 impl Command for RootCommand {
22 impl Command for RootCommand {
23 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
23 fn run(&self, ui: &Ui) -> Result<(), CommandError> {
24 let path_buf = find_root()?;
24 let repo = Repo::find()?;
25
25 let bytes = get_bytes_from_path(repo.working_directory_path());
26 let bytes = get_bytes_from_path(path_buf);
27
28 ui.write_stdout(&format_bytes!(b"{}\n", bytes.as_slice()))?;
26 ui.write_stdout(&format_bytes!(b"{}\n", bytes.as_slice()))?;
29
30 Ok(())
27 Ok(())
31 }
28 }
32 }
29 }
General Comments 0
You need to be logged in to leave comments. Login now