Unified · Split
| @@ -1228,10 +1228,12 @@ dependencies = [ · 1227 unmodified lines | |||
| 1228 | name = "git-index" | 1228 | name = "git-index" |
| 1229 | version = "0.0.0" | 1229 | version = "0.0.0" |
| 1230 | dependencies = [ | 1230 | dependencies = [ |
| 1231 | "filetime", | ||
| 1231 | "git-hash 0.8.0", | 1232 | "git-hash 0.8.0", |
| 1232 | "git-testtools", | 1233 | "git-testtools", |
| 1233 | "memmap2", | 1234 | "memmap2", |
| 1234 | "quick-error", | 1235 | "quick-error", |
| 1236 | "serde", | ||
| 1235 | ] | 1237 | ] |
| 1236 | 1238 | ||
| 1237 | [[package]] | 1239 | [[package]] |
| @@ -82,6 +82,7 @@ check: ## Build all code in suitable configurations · 81 unmodified lines | |||
| 82 | && cargo check | 82 | && cargo check |
| 83 | cd git-object && cargo check --all-features \ | 83 | cd git-object && cargo check --all-features \ |
| 84 | && cargo check --features verbose-object-parsing-errors | 84 | && cargo check --features verbose-object-parsing-errors |
| 85 | cd git-index && cargo check --features serde1 | ||
| 85 | cd git-actor && cargo check --features serde1 | 86 | cd git-actor && cargo check --features serde1 |
| 86 | cd git-pack && cargo check --features serde1 \ | 87 | cd git-pack && cargo check --features serde1 \ |
| 87 | && cargo check --features pack-cache-lru-static \ | 88 | && cargo check --features pack-cache-lru-static \ |
| @@ -10,6 +10,9 @@ edition = "2018" · 9 unmodified lines | |||
| 10 | [lib] | 10 | [lib] |
| 11 | doctest = false | 11 | doctest = false |
| 12 | 12 | ||
| 13 | [features] | ||
| 14 | serde1 = ["serde"] | ||
| 15 | |||
| 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | 16 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
| 14 | 17 | ||
| 15 | [dependencies] | 18 | [dependencies] |
| @@ -17,6 +20,9 @@ git-hash = { version ="^0.8.0", path = "../git-hash" } · 1 unmodified line | |||
| 17 | 20 | ||
| 18 | quick-error = "2.0.0" | 21 | quick-error = "2.0.0" |
| 19 | memmap2 = "0.5.0" | 22 | memmap2 = "0.5.0" |
| 23 | filetime = "0.2.15" | ||
| 24 | |||
| 25 | serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] } | ||
| 20 | 26 | ||
| 21 | [dev-dependencies] | 27 | [dev-dependencies] |
| 22 | git-testtools = { path = "../tests/tools"} | 28 | git-testtools = { path = "../tests/tools"} |
| @@ -1,8 +1,8 @@ | |||
| 1 | pub mod init { | 1 | pub mod init { |
| 2 | #![allow(unused)] | 2 | #![allow(unused)] |
| 3 | use crate::File; | 3 | use crate::{File, State}; |
| 4 | use memmap2::Mmap; | 4 | use memmap2::Mmap; |
| 5 | use std::path::Path; | 5 | use std::path::{Path, PathBuf}; |
| 6 | 6 | ||
| 7 | mod error { | 7 | mod error { |
| 8 | use quick_error::quick_error; | 8 | use quick_error::quick_error; |
| @@ -11,7 +11,7 @@ pub mod init { · 2 unmodified lines | |||
| 11 | #[derive(Debug)] | 11 | #[derive(Debug)] |
| 12 | pub enum Error { | 12 | pub enum Error { |
| 13 | Io(err: std::io::Error) { | 13 | Io(err: std::io::Error) { |
| 14 | display("An IO error occurred while reading the index") | 14 | display("An IO error occurred while opening the index") |
| 15 | source(err) | 15 | source(err) |
| 16 | from() | 16 | from() |
| 17 | } | 17 | } |
| @@ -21,12 +21,44 @@ pub mod init { · 3 unmodified lines | |||
| 21 | pub use error::Error; | 21 | pub use error::Error; |
| 22 | 22 | ||
| 23 | impl File { | 23 | impl File { |
| 24 | pub fn at(path: impl AsRef<Path>, object_hash: git_hash::Kind) -> Result<Self, Error> { | 24 | pub fn at(path: impl Into<PathBuf>, object_hash: git_hash::Kind) -> Result<Self, Error> { |
| 25 | // SAFETY: we have to take the risk of somebody changing the file underneath. Git never writes into the same file. | 25 | let path = path.into(); |
| 26 | #[allow(unsafe_code)] | 26 | let (data, mtime) = { |
| 27 | let data = unsafe { Mmap::map(&std::fs::File::open(path)?)? }; | 27 | // SAFETY: we have to take the risk of somebody changing the file underneath. Git never writes into the same file. |
| 28 | let file = std::fs::File::open(&path)?; | ||
| 29 | #[allow(unsafe_code)] | ||
| 30 | let data = unsafe { Mmap::map(&file)? }; | ||
| 31 | (data, filetime::FileTime::from_last_modification_time(&file.metadata()?)) | ||
| 32 | }; | ||
| 28 | 33 | ||
| 29 | todo!("read file") | 34 | Ok(File { |
| 35 | state: State { timestamp: mtime }, | ||
| 36 | path, | ||
| 37 | }) | ||
| 30 | } | 38 | } |
| 31 | } | 39 | } |
| 32 | } | 40 | } |
| 41 | |||
| 42 | pub mod decode { | ||
| 43 | pub mod header { | ||
| 44 | mod error { | ||
| 45 | use quick_error::quick_error; | ||
| 46 | |||
| 47 | quick_error! { | ||
| 48 | #[derive(Debug)] | ||
| 49 | pub enum Error { | ||
| 50 | Io(err: std::io::Error) { | ||
| 51 | display("An IO error occurred while opening the index") | ||
| 52 | source(err) | ||
| 53 | from() | ||
| 54 | } | ||
| 55 | } | ||
| 56 | } | ||
| 57 | } | ||
| 58 | pub use error::Error; | ||
| 59 | } | ||
| 60 | |||
| 61 | fn header(data: &[u8]) -> Result<(crate::Version, &[u8]), header::Error> { | ||
| 62 | todo!("header parsing") | ||
| 63 | } | ||
| 64 | } | ||
| @@ -1,18 +1,22 @@ | |||
| 1 | #![deny(unsafe_code, missing_docs, rust_2018_idioms)] | 1 | #![deny(unsafe_code, missing_docs, rust_2018_idioms)] |
| 2 | #![allow(missing_docs)] | 2 | #![allow(missing_docs, unused)] |
| 3 | 3 | ||
| 4 | use filetime::FileTime; | ||
| 4 | use std::path::PathBuf; | 5 | use std::path::PathBuf; |
| 5 | 6 | ||
| 6 | pub mod file; | 7 | pub mod file; |
| 7 | 8 | ||
| 8 | pub mod init { | 9 | pub mod init { |
| 9 | use crate::State; | 10 | use crate::State; |
| 11 | use filetime::FileTime; | ||
| 10 | 12 | ||
| 11 | impl State { | 13 | impl State { |
| 12 | /// Returns an empty state. | 14 | /// Returns an empty state. |
| 13 | /// TODO: figure out if it needs to know some configuration | 15 | /// TODO: figure out if it needs to know some configuration, and if this would actually be used somewhere |
| 14 | pub fn new() -> Self { | 16 | fn new() -> Self { |
| 15 | State | 17 | State { |
| 18 | timestamp: FileTime::from_system_time(std::time::SystemTime::UNIX_EPOCH), | ||
| 19 | } | ||
| 16 | } | 20 | } |
| 17 | } | 21 | } |
| 18 | 22 | ||
| @@ -23,6 +27,16 @@ pub mod init { · 4 unmodified lines | |||
| 23 | } | 27 | } |
| 24 | } | 28 | } |
| 25 | 29 | ||
| 30 | /// All known versions of a git index file. | ||
| 31 | #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] | ||
| 32 | #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] | ||
| 33 | #[allow(missing_docs)] | ||
| 34 | pub enum Version { | ||
| 35 | V2 = 2, | ||
| 36 | V3 = 3, | ||
| 37 | V4 = 4, | ||
| 38 | } | ||
| 39 | |||
| 26 | /// An index file whose state was read from a file on disk. | 40 | /// An index file whose state was read from a file on disk. |
| 27 | pub struct File { | 41 | pub struct File { |
| 28 | pub state: State, | 42 | pub state: State, |
| @@ -33,4 +47,10 @@ pub struct File { · 4 unmodified lines | |||
| 33 | /// | 47 | /// |
| 34 | /// As opposed to a snapshot, it's meant to be altered and eventually be written back to disk or converted into a tree. | 48 | /// As opposed to a snapshot, it's meant to be altered and eventually be written back to disk or converted into a tree. |
| 35 | /// We treat index and its state synonymous. | 49 | /// We treat index and its state synonymous. |
| 36 | pub struct State; | 50 | pub struct State { |
| 51 | /// The time at which the state was created, indicating its freshness compared to other files on disk. | ||
| 52 | /// | ||
| 53 | /// Note that on platforms that only have a precisions of a second for this time, we will treat all entries with the | ||
| 54 | /// same timestamp as this as potentially changed, checking more thoroughly if a change actually happened. | ||
| 55 | timestamp: FileTime, | ||
| 56 | } | ||
| @@ -4,7 +4,6 @@ mod init { · 3 unmodified lines | |||
| 4 | } | 4 | } |
| 5 | 5 | ||
| 6 | #[test] | 6 | #[test] |
| 7 | #[ignore] | ||
| 8 | fn read_v2() { | 7 | fn read_v2() { |
| 9 | let _file = file("v2"); | 8 | let _file = file("v2"); |
| 10 | } | 9 | } |