History

[commitgraph] implement basic, low-level read API

This is just the first pass at ensuring we can read commit-graph files correctly. It does not support anything interesting like reachability, merge-base, or ahead-behind queries.

Conor Davis committed 6 years ago

Commit d1f0e9c1 parent 1b42b3153 files · +1429 −-23Browse files

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

Unified · Split

git-commitgraph/src/graph/init.rs+104−0
@@ -0,0 +1,104 @@
1+use crate::{graph_file, Graph, GraphFile, MAX_COMMITS};
2+use git_object::HashKind;
3+use quick_error::quick_error;
4+use std::io::{BufRead, BufReader};
5+use std::path::{Path, PathBuf};
6+
7+quick_error! {
8+ #[derive(Debug)]
9+ pub enum Error {
10+ Corrupt(msg: String, path: PathBuf) {
11+ display("{}", msg)
12+ }
13+ GraphFile(err: graph_file::Error, path: PathBuf) {
14+ display("{}", path.display())
15+ source(err)
16+ }
17+ HashVersionMismatch(path1: PathBuf, hash1: HashKind, path2: PathBuf, hash2: HashKind) {
18+ display(
19+ "Commit-graph files mismatch: '{}' uses hash {:?}, but '{}' uses hash {:?}",
20+ path1.display(),
21+ hash1,
22+ path2.display(),
23+ hash2,
24+ )
25+ }
26+ Io(err: std::io::Error, path: PathBuf) {
27+ display("Could not open commit-graph graph_file at '{}'", path.display())
28+ source(err)
29+ }
30+ TooManyCommits(num_commits: u64) {
31+ display(
32+ "Commit-graph files contain {} commits altogether, but only {} commits are allowed",
33+ num_commits,
34+ MAX_COMMITS,
35+ )
36+ }
37+ // This might actually be legal...
38+ VersionMismatch(path1: PathBuf, version1: graph_file::Kind, path2: PathBuf, version2: graph_file::Kind) {
39+ display(
40+ "Commit-graph files mismatch: '{}' is version {:?}, but '{}' is version {:?}",
41+ path1.display(),
42+ version1,
43+ path2.display(),
44+ version2,
45+ )
46+ }
47+ }
48+}
49+
50+impl Graph {
51+ pub fn from_object_dir(object_dir: impl AsRef<Path>) -> Result<Self, Error> {
52+ Self::from_single_file(object_dir.as_ref()).or_else(|_| Self::from_split_chain(object_dir.as_ref()))
53+ }
54+
55+ pub fn from_single_file(object_dir: impl AsRef<Path>) -> Result<Self, Error> {
56+ let single_graph_file = object_dir.as_ref().join("info").join("commit-graph");
57+ let file = GraphFile::at(&single_graph_file).map_err(|e| Error::GraphFile(e, single_graph_file.clone()))?;
58+ Self::new(vec![file])
59+ }
60+
61+ pub fn from_split_chain(object_dir: impl AsRef<Path>) -> Result<Self, Error> {
62+ let commit_graphs_dir = object_dir.as_ref().join("info").join("commit-graphs");
63+ let chain_file_path = commit_graphs_dir.join("commit-graph-chain");
64+ let chain_file = std::fs::File::open(&chain_file_path).map_err(|e| Error::Io(e, chain_file_path.clone()))?;
65+ let mut files: Vec<GraphFile> = Vec::new();
66+ for line in BufReader::new(chain_file).lines() {
67+ let line = line.map_err(|e| Error::Io(e, chain_file_path.clone()))?;
68+ let graph_filename = format!("graph-{}.graph", line);
69+ let graph_file_path = commit_graphs_dir.join(graph_filename);
70+ files.push(GraphFile::at(&graph_file_path).map_err(|e| Error::GraphFile(e, graph_file_path.clone()))?);
71+ }
72+ Self::new(files)
73+ }
74+
75+ pub fn new(files: Vec<GraphFile>) -> Result<Self, Error> {
76+ let num_commits: u64 = files.iter().map(|f| f.num_commits() as u64).sum();
77+ if num_commits > MAX_COMMITS as u64 {
78+ return Err(Error::TooManyCommits(num_commits));
79+ }
80+
81+ for window in files.windows(2) {
82+ let f1 = &window[0];
83+ let f2 = &window[1];
84+ if f1.kind() != f2.kind() {
85+ return Err(Error::VersionMismatch(
86+ f1.path().to_owned(),
87+ f1.kind(),
88+ f2.path().to_owned(),
89+ f2.kind(),
90+ ));
91+ }
92+ if f1.hash_kind() != f2.hash_kind() {
93+ return Err(Error::HashVersionMismatch(
94+ f1.path().to_owned(),
95+ f1.hash_kind(),
96+ f2.path().to_owned(),
97+ f2.hash_kind(),
98+ ));
99+ }
100+ }
101+
102+ Ok(Self { files })
103+ }
104+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t