Summary:
There are scenarios where an &PathComponentBuf or a &RepoPath will show up.
An example when using get from a HashMap. These are not the references that we
are looking for. We want &PathComponent and &RepoPath respectively. Adding
explicit conversions.
(Note: this ignores all push blocking failures!)
Reviewed By: quark-zju
Differential Revision: D14292711
fbshipit-source-id: 29f4de25c2ffebf7f009e4f2515e0ba8f0371ae0
Summary:
The practical aspect of this method comes when iterating over a tree and having
to maintain the current path. When going deep we will be pushing path
components and when coming back we will be poping path components.
I am not sure if it makes sense to return the path component or not. However I
believe that we should return some sort of error when RepoPath is empty.
(Note: this ignores all push blocking failures!)
Reviewed By: quark-zju
Differential Revision: D14292715
fbshipit-source-id: 4ef1e10de7a60775340063b5baa317d3d626bc64
Summary:
I had an issue where I incorrectly ended up with a &&RepoPath. While debugging
I added this tests to validate my sanity. I think that keeping these tests is
useful for the future.
(Note: this ignores all push blocking failures!)
Differential Revision: D14276640
fbshipit-source-id: d7e1cedc80b3a0ecb97e5a0c80fc4eea110e943f
Summary:
The current implementation has some gotchas that are related to how the `split`
method is implemented for `&str`. The new implementation is more clear for how
we construct path components
(Note: this ignores all push blocking failures!)
Differential Revision: D14276639
fbshipit-source-id: 1a22c177ba570915b7952eee78ed9191f7b72976
Summary:
Return the last component of the path. The empty path, `RepoPath::empty()`
does not have any components so `None` is returned in that case.
(Note: this ignores all push blocking failures!)
Differential Revision: D14276643
fbshipit-source-id: 9c4caf455891e77d03f22d81b39e3a34ae61ffcc
Summary:
`RepoPath::parent` returns the parent of the path. The empty path,
`RepoPath::empty()` does not have a parent so `None` is returned in that case.
(Note: this ignores all push blocking failures!)
Differential Revision: D14276641
fbshipit-source-id: fc60da9750dc76e4f598dd483a63adc180135cb4
Summary:
Tries to split the current `RepoPath` in a parent path and a component. If the
current path is empty then None is returned. If the current path contains only
one component then the pair that is returned is the empty repo path and a path
component that will match the contents `self`.
(Note: this ignores all push blocking failures!)
Differential Revision: D14276644
fbshipit-source-id: e85a22f65cc267e48f12af6bf6b40c7673b7eaaa
Summary:
An iterator for the parent directories of a path.
(Note: this ignores all push blocking failures!)
Differential Revision: D14276646
fbshipit-source-id: 2b580ee8d762db5113110ec9b09ec3a093a1063a
Summary:
This diff defines the empty `RepoPath`. This path is equivalent with the root
of the repository.
Also adding a method to check whether a `RepoPath` matches this special path.
(Note: this ignores all push blocking failures!)
Differential Revision: D14276647
fbshipit-source-id: 6e9ad5957ad39a711a1680bd084f448bb9d73f87
Summary: Implement the `Display` trait for `Key`. This is important for human-readable output for debugging since both filenode and path inside the `Key` are stored as byte arrays, which are just printed out as numbers by the derived `Debug` implementation.
Differential Revision: D14294970
fbshipit-source-id: a601dc9a0c23ac40894ec27135171928f5635507
Summary:
The order of imports we're trying to follow is: std, remote crates
(ie: crates.io), local crates (ie: fbcode crates), and crate local. A new line
in between each group can be used to prevent rustfmt from re-ordering them.
Reviewed By: singhsrb
Differential Revision: D14243163
fbshipit-source-id: fbbb07693af14b13ae6b3f4e788972d99193fd64
Summary:
`as_bytes` is useful for interacting with code that is written in reference
to a `slice` or when attempting to serialize them. It is fine to serialize
these paths using their underlying representation because we request that they
be normalized.
Reviewed By: quark-zju
Differential Revision: D14178263
fbshipit-source-id: 36529e2ae47580ae4014ae279df98b35eac5484a
Summary:
Implementing these traits allows easy use of `RepoPath` and friends in
quickcheck tests.
It is tricky to implement `PathComponentBuf`. I believe that most strings will
end up being a valid `PathComponent` so I think that it is reasonable to loop
until a valid string is found. To note generating Arbitrary Unicode `char`s is
implemented using a loop where random bytes are validated against the `char`
constructor.
Reviewed By: quark-zju
Differential Revision: D14178262
fbshipit-source-id: 759486a2053b851f8259d7cc03eee1cd69893f9f
Summary:
These constant can be useful for parsing byte streams that we expect to contain
`Node`s. These constant should replace all potential hardcoding of values that
intend to represent the byte lengths for `Node`.
Differential Revision: D14178261
fbshipit-source-id: 34471151b5d253504e32a9e8b039608c1d4943fe
Summary:
Tell serde to use an [untagged representation](https://serde.rs/enum-representations.html#untagged) of this enum. This means that `Parents::None` will map to a null value, `Parents::One` will map to an array representing a `Node`, and a `Parents::Two` will map to an array of 2 arrays representing `Node`.
Using CBOR serialization, this means that these variants are 1 byte, 21 bytes, and 43 bytes respectively.
Differential Revision: D14174309
fbshipit-source-id: 0217a23c4ee5409ab293525d7b6e5ae969b5504d
Summary: Add implementations for `FromIterator` and `IntoIterator` for the `Parents` type to make it more ergonomic to use.
Reviewed By: quark-zju
Differential Revision: D14172511
fbshipit-source-id: 5ba848c1dfbb8cc23ed19c9dc816616f5ed7af5f
Summary:
This changes the way we represent history entries for the Eden API by splitting them into two types and putting them into a new `historyentry` module.
- `PackHistoryEntry` is the same as the old `HistoryEntry`, containing the fields required to add this entry to a `MutableHistoryPack` (namely a `Key` and a `NodeInfo`).
- `LooseHistoryEntry` is a history entry containing the information that would normally be present in a line of the history text in the remotefilelog loose file format.
There are several reasons why it makes sense to have both of these types:
- The existing remotefilelog code in Mononoke uses a type very similar to `LooseHistoryEntry` internally, and as such having a similar type for API calls simplifies code on the server side.
- `PackHistoryEntry` contains redundant information (in particular, the file path may be duplicated up to 3 times). While it's structure is ideal for `revisionstore`'s in-memory data structures, for transmitting data, this redundancy is undesirable, especially since the client already has the file path (it is required to make the request in the first place).
- Conversions between these two representations include some subtle details that are tricky to get right. By putting the conversion in one canonical place, we can avoid having to duplicate this conversion logic in multiple places.
Differential Revision: D14162783
fbshipit-source-id: 63e0a060709916f21613442b75370f4d34a04f04
Summary:
Add a type representing a node's parents. Mercurial nodes can have zero, one, or two parents; this is normally represented as an array of two node hashes, with any absent parents denoted with a null hash. This representation is not particularly Rustic because it allows for invalid combinations (such as a null p1 and non-null p2) to be represented. By using an enum, invalid values are unrepresentable, making code using this type simpler (due to not requiring validation logic).
This type will be used later in the stack to represent parents in history entries.
Reviewed By: quark-zju
Differential Revision: D14162782
fbshipit-source-id: dfff3ecc76dea114e0044839216d080b7f34a506
Summary: Add conversions between the `HgFileHistoryEntry` type produced by Mononoke and the `edenapi_types::HistoryEntry` type shared between Mercurial and Mononoke. The latter can be serialized and sent from the API server to the Mercurial client, and will be used for HTTP history fetching.
Reviewed By: quark-zju
Differential Revision: D14079338
fbshipit-source-id: 2123c88310f633f87d8c92405382d5046874dfee
Summary:
While working on TreeManifest I found that the code does not allow creating an empty `RepoPath`. I did not realize that splitting an empty string always results in an empty string. This is an edge case and we need to handle it appropriately.
Currently adding a hack where the components iterator function will skip empty values. We are going to add more iterators in a future revision and we should revisit this function then.
Reviewed By: quark-zju
Differential Revision: D14142927
fbshipit-source-id: 1be43d61913138e3fa50e02976e81f9ca38a74a7
Summary: I am making this a new diff because the I am documenting failures which only make sense when validation was already added.
Differential Revision: D14097490
fbshipit-source-id: 7eb2c22ebbbc4365f8203d68bc29134176f326f6
Summary:
When introducing `Component` we said that it will not have any slashes (`/`). This diff adds enforcement for that along with enforcing that `Component` is not empty.
`Path` and by extension `Component` also have a set of invalid bytes: `\0`, `\1` and `\n`. I got these checks from the mononoke codebase (mononoke-types/path.rs)
Reviewed By: DurhamG
Differential Revision: D14001106
fbshipit-source-id: 5acbdf66214e54f1034fd89d90e88c3e904d7f9b
Summary:
`Component` and `ComponentBuf` are specializations of `RelativePath` and `RelativePathBuf` that do not have any separators: `/`. The main operation that is done on paths is iterating over its components. The components are generally directory names and occasionally file names.
For the path: `foo/bar/baz.txt` we have 3 components: `foo`, `bar` and `baz.txt`.
A lot of algorithms used in source control management operate on directories so having an abstraction for individual components is going to increase readability in the long run. A clear example for where we may want to use `ComponentBuf` is in the treemanifest logic where all indexing is done using components. The index in those cases must be able to own component. Writing it in terms of `RelativePathBuf` would probably be less readable that writing it in terms of `String`.
This diff also adds the `RelativePath::components` which acts as an iterator over `RelativePath` producing `Component`.
The name `Component` is inspired from `std::path::Component`.
Reviewed By: DurhamG
Differential Revision: D14001108
fbshipit-source-id: 30916d2b78fa89537fc5b30420b3b7c12d1f82c7
Summary:
`RelativePath` and `RelativePathBuf` are types for working with paths specialized for source control internals. They are akin to `str` and `String` in high level behavior. `RelativePath` is an unsized type wrapping a `str` so it can't be instantiated directly. `RelativePathBuf` represents the owned version of a `RelativePath` and wraps a `String`.
RelativePaths are going to be used in all contexts for SCM so flexible and efficient abstractions for dealing with common needs is important.
The inspiration for `RelativePath` and `RelativePathBuf` comes from the `std::path` crate however we know that the internal representation of a path is consistently an array of bytes where directories are delimited by `/` thus our types can have a simpler representation. It is because of the same reason that we can't use the abstractions in `std::path` for internal uses where we need to apply the same algorithm for blobs we get from the server across all systems.
This diff adds a new crate called `vfs`. The recommended use of the types in this crate are `use ...::vfs` followed by `vfs::RelativePath` and `vfs::RelativePathBuf`.
Alternatives for representing the path:
* We could use `String` and `&str` directly however these types are inexpressive and have few guarantees. Rust has a strong type system so we can leverage it to provide more safety.
* Mononoke use `PathElement(Vec<u8>)` and `MPath(Vec<PathElement>)`. One issue is that this type requires more allocations. Having read a buffer it is more difficult to provide views into it as &MRelativePath.
`RelativePath` is Dynamically Sized Type (DST). That means that `mem::transmute` is the practical way of constructing it in Rust right now:
* https://doc.rust-lang.org/nomicon/exotic-sizes.html
* https://github.com/rust-lang/rust/pull/39594#issuecomment-279471476
Basing these types on `String` and `&str` means that the paths that we deal with need to have UTF-8 encodings. In the grand scheme of things a lot of things are simplified when we can make this kind of assumption.
The code right now doesn't have much documentation. I'll add that if this direction makes sense to other people.
Reviewed By: DurhamG
Differential Revision: D14001109
fbshipit-source-id: 1ca399827b1284f32cd83219e7e090d8b2487cee
Summary:
make local / relase are broken on trunk, fix it
in other modules, this code is only for tests. In toml file it is enabled for tests.
Reviewed By: mitrandir77, ikostia
Differential Revision: D14123392
fbshipit-source-id: eceaf17478b8b7e75ee2ba56df69b28ca8374c64
Summary: Move the contents of `edenapi-types` into the `types` crate so all of Mercurial's Rust types are in one place.
Reviewed By: quark-zju
Differential Revision: D14114547
fbshipit-source-id: feb8f9c35f102d30bf00b230df81a86a3893a49b
Summary:
In order to move the types in `edenapi-types` (containing types shared between Mercurial and Mononoke) to the `types` crate, we need to move a few types from the `revisionstore` crate into this crate first, because `revisionstore` depends on `types`, which would create a circular dependency since `edenapi-types` uses types from `revisionstore`.
In particular, this diff moves the `Key` and `NodeInfo` types into their own modules in the `types` crate.
Reviewed By: quark-zju
Differential Revision: D14114166
fbshipit-source-id: 8f9e78d610425faec9dc89ecc9e450651d24177a
Summary:
`Node` is not friendly with plain old unit tests because constructing them is a bit involved. This diff adds a constructor from u8 purely for test puposes.
I picked an u8 for input because it is the most convenient type. When we move past rust 1.31 it might make sense to use an u32 and use https://doc.rust-lang.org/std/primitive.u32.html#method.to_le_bytes
To note that property testing is best used in addition to plain old unit testing.
Reviewed By: DurhamG
Differential Revision: D14016272
fbshipit-source-id: 5b831ab0011ef2575f7e94d158ab4ddf30d1ac06
Summary: Make this type serializable so it can be sent as part of an HTTP request. By using Serde, we can easily support a variety of serialization formats without code changes.
Reviewed By: singhsrb
Differential Revision: D13858443
fbshipit-source-id: b6c83f38eaadbb2a28be6d66faf6a3610ede970f
Summary:
Use the `Fallible` type alias provided by `failure` rather than defining our
own.
Differential Revision: D13657313
fbshipit-source-id: ae249bc15037cc2be019ce7ce8a440c153aa31cc
Summary:
The derived debug for Node prints out each byte as a decimal number. Instead,
make the Debug output for nodes look like `Node("hexstring")`.
Reviewed By: DurhamG
Differential Revision: D12980775
fbshipit-source-id: 042cbf6eade8403759684969e1f69f7f4e335582
Summary:
Add a utility function for tests to generate a vector of random nodes. This
will be used in future tests.
Reviewed By: DurhamG
Differential Revision: D12980784
fbshipit-source-id: 73fc8643503e11a46a845671df94c912a5e49d23
Summary:
Add traits that extend `std::io::Read` and `std::io::Write` to implement new
`read_node` and `write_node` methods, allowing simple reading and writing of
binary nodes from and to streams.
Reviewed By: DurhamG
Differential Revision: D12980778
fbshipit-source-id: fc6751cd43a1693a5a5a3ac93aea74aec5fda4fe
Summary:
This is done by running `fix-code.py`. Note that those strings are
semvers so they do not pin down the exact version. An API-compatiable upgrade
is still possible.
Reviewed By: ikostia
Differential Revision: D10213073
fbshipit-source-id: 82f90766fb7e02cdeb6615ae3cb7212d928ed48d
Summary: This is just the result of running `./contrib/fix-code.py $(hg files .)`
Reviewed By: ikostia
Differential Revision: D10213075
fbshipit-source-id: 88577c9b9588a5b44fcf1fe6f0082815dfeb363a
Summary:
The `Node` type will be used in multiple places. Let's move it to a standalone
crate so new libraries depending on it won't need to pull in all of
revisionstore's dependencies.
Note: I'd also like the `types` create to only define clean types. Given the
fact NULL_ID is not a great design in Mercurial (`Option<Node>` is a better
choice in Rust), it probably does not belong to the formal Rust `Node` type.
This diff is merely about moving things with minimal changes. NULL_ID will
be decoupled from `Node` in a follow-up.
Reviewed By: markbt
Differential Revision: D10132047
fbshipit-source-id: 5d05c5e0ac06a2d58556c4db11775503f9495626