History

[commitgraph] Add `Graph::at` constructor.

This constructor tries to accept as many commit-graph-looking paths as possible, such as `.git/objects/info`, `.git/objects/info/commit-graph`, or `.git/objects/info/commit-graphs`.

Conor Davis committed 6 years ago

Commit a7830521 parent 1b738ac2 files · +44 −16Browse files

Showing the changes to git-commitgraph/src/graph (1 of 2 files). Show all

Unified · Split

git-commitgraph/src/graph/init.rs+42−15
@@ -4,6 +4,7 @@ use crate::{ · 3 unmodified lines
4};4};
5use git_object::HashKind;5use git_object::HashKind;
6use std::{6use std::{
7 convert::TryFrom,
7 io::{BufRead, BufReader},8 io::{BufRead, BufReader},
8 path::{Path, PathBuf},9 path::{Path, PathBuf},
9};10};
@@ -23,7 +24,9 @@ pub enum Error { · 13 unmodified lines
23 path2: PathBuf,24 path2: PathBuf,
24 hash2: HashKind,25 hash2: HashKind,
25 },26 },
26 #[error("Could not open commit-graph file at '{}'", path.display())]27 #[error("Did not find any files that look like commit graphs at '{}'", .0.display())]
28 InvalidPath(PathBuf),
29 #[error("Could not open commit-graph file at '{}'", .path.display())]
27 Io {30 Io {
28 #[source]31 #[source]
29 err: std::io::Error,32 err: std::io::Error,
@@ -38,22 +41,12 @@ pub enum Error { · 8 unmodified lines
38 41
39/// Instantiate a `Graph` from various sources42/// Instantiate a `Graph` from various sources
40impl Graph {43impl Graph {
41 pub fn from_info_dir(info_dir: impl AsRef<Path>) -> Result<Self, Error> {44 pub fn at(path: impl AsRef<Path>) -> Result<Self, Error> {
42 Self::from_single_file(info_dir.as_ref())45 Self::try_from(path.as_ref())
43 .or_else(|_| Self::from_split_chain(info_dir.as_ref().join("commit-graphs")))
44 }
45
46 pub fn from_single_file(info_dir: impl AsRef<Path>) -> Result<Self, Error> {
47 let single_graph_file = info_dir.as_ref().join("commit-graph");
48 let file = File::at(&single_graph_file).map_err(|e| Error::File {
49 err: e,
50 path: single_graph_file.clone(),
51 })?;
52 Self::new(vec![file])
53 }46 }
54 47
55 pub fn from_split_chain(commit_graphs_dir: impl AsRef<Path>) -> Result<Self, Error> {48 pub fn from_commit_graphs_dir(path: impl AsRef<Path>) -> Result<Self, Error> {
56 let commit_graphs_dir = commit_graphs_dir.as_ref();49 let commit_graphs_dir = path.as_ref();
57 let chain_file_path = commit_graphs_dir.join("commit-graph-chain");50 let chain_file_path = commit_graphs_dir.join("commit-graph-chain");
58 let chain_file = std::fs::File::open(&chain_file_path).map_err(|e| Error::Io {51 let chain_file = std::fs::File::open(&chain_file_path).map_err(|e| Error::Io {
59 err: e,52 err: e,
@@ -74,6 +67,20 @@ impl Graph { · 14 unmodified lines
74 Self::new(files)67 Self::new(files)
75 }68 }
76 69
70 pub fn from_file(path: impl AsRef<Path>) -> Result<Self, Error> {
71 let path = path.as_ref();
72 let file = File::at(path).map_err(|e| Error::File {
73 err: e,
74 path: path.to_owned(),
75 })?;
76 Self::new(vec![file])
77 }
78
79 pub fn from_info_dir(info_dir: impl AsRef<Path>) -> Result<Self, Error> {
80 Self::from_file(info_dir.as_ref().join("commit-graph"))
81 .or_else(|_| Self::from_commit_graphs_dir(info_dir.as_ref().join("commit-graphs")))
82 }
83
77 pub fn new(files: Vec<File>) -> Result<Self, Error> {84 pub fn new(files: Vec<File>) -> Result<Self, Error> {
78 let num_commits: u64 = files.iter().map(|f| f.num_commits() as u64).sum();85 let num_commits: u64 = files.iter().map(|f| f.num_commits() as u64).sum();
79 if num_commits > MAX_COMMITS as u64 {86 if num_commits > MAX_COMMITS as u64 {
@@ -96,3 +103,23 @@ impl Graph { · 16 unmodified lines
96 Ok(Self { files })103 Ok(Self { files })
97 }104 }
98}105}
106
107impl TryFrom<&Path> for Graph {
108 type Error = Error;
109
110 fn try_from(path: &Path) -> Result<Self, Self::Error> {
111 if path.is_file() {
112 // Assume we are looking at `.git/objects/info/commit-graph` or
113 // `.git/objects/info/commit-graphs/graph-*.graph`.
114 Self::from_file(path)
115 } else if path.is_dir() {
116 if path.join("commit-graph-chain").is_file() {
117 Self::from_commit_graphs_dir(path)
118 } else {
119 Self::from_info_dir(path)
120 }
121 } else {
122 Err(Error::InvalidPath(path.to_owned()))
123 }
124 }
125}