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 @@
1use crate::{graph_file, Graph, GraphFile, MAX_COMMITS};
2use git_object::HashKind;
3use quick_error::quick_error;
4use std::io::{BufRead, BufReader};
5use std::path::{Path, PathBuf};
6
7quick_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
50impl 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