Commit Graph

37 Commits

Author SHA1 Message Date
Stefan Filip
43fb573c23 types: add explicit conversions from owned paths types to unsized ref
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
2019-03-05 16:12:47 -08:00
Stefan Filip
fcc560357a types: add RepoPathBuf::pop()
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
2019-03-05 16:12:47 -08:00
Stefan Filip
dd2bfc6c04 types: add test for to_owned() on Path types
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
2019-03-05 16:12:47 -08:00
Stefan Filip
f71814f8e2 types: add dedicated iterator type for RepoPath::components()
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
2019-03-05 16:12:47 -08:00
Stefan Filip
27c0d1c991 types: add RepoPath::last_component()
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
2019-03-05 16:12:47 -08:00
Stefan Filip
ed6e6245ad types: add RepoPath::parent()
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
2019-03-05 16:12:47 -08:00
Stefan Filip
736cfe89bd types: add RepoPath::split_last_component()
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
2019-03-05 16:12:47 -08:00
Stefan Filip
68b6897a78 types: Add RepoPath::parents()
Summary:
An iterator for the parent directories of a path.

(Note: this ignores all push blocking failures!)

Differential Revision: D14276646

fbshipit-source-id: 2b580ee8d762db5113110ec9b09ec3a093a1063a
2019-03-05 16:12:47 -08:00
Stefan Filip
ffffdd2a44 types: Add RepoPath::empty()
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
2019-03-05 16:12:47 -08:00
Arun Kulshreshtha
2ab9df3b9d types: implement Display for Key
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
2019-03-04 12:11:23 -08:00
Stefan Filip
d543e91b45 types: order imports in path.rs
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
2019-02-27 10:00:40 -08:00
Stefan Filip
e496e01d8f types: Add as_byte_slice() to RepoPath and PathComponent
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
2019-02-22 15:42:45 -08:00
Stefan Filip
5c04aead8f types: add Arbitrary implementations for RepoPathBuf & PathComponentBuf
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
2019-02-22 15:42:44 -08:00
Stefan Filip
49e7e99131 types: add public constant functions Node::{len, hex_len}
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
2019-02-22 15:42:44 -08:00
Arun Kulshreshtha
09d3ade23a types: use untagged serialization for Parents
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
2019-02-21 16:34:25 -08:00
Arun Kulshreshtha
eb3b97d91a types: implement FromIterator and IntoIterator for Parents
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
2019-02-21 14:39:04 -08:00
Arun Kulshreshtha
3344341ad9 types: split HistoryEntry into two types
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
2019-02-21 14:39:04 -08:00
Arun Kulshreshtha
45a299b82d types: add Parents type representing a node's parents
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
2019-02-21 14:39:04 -08:00
Arun Kulshreshtha
4dfba9862d Add conversions from Mononoke to Mercurial history entries
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
2019-02-20 15:29:22 -08:00
Stefan Filip
a83ec90f88 Fix creation for empty RepoPath
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
2019-02-20 10:33:19 -08:00
Stefan Filip
e7975b4e5e Add documentation for RepoPath and PathComponent
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
2019-02-19 13:52:47 -08:00
Stefan Filip
fc1901e4a4 Add validation for paths
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
2019-02-19 13:23:31 -08:00
Stefan Filip
65604c2a4e Add Component and ComponentBuf
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
2019-02-19 13:23:30 -08:00
Stefan Filip
bba4a5c197 Add Path structures specialized for source control
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
2019-02-19 13:23:30 -08:00
Liubov Dmitrieva
bc43b991a2 fix compilation
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
2019-02-18 04:53:57 -08:00
Arun Kulshreshtha
8864e6a0da types: move edenapi-types into types crate
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
2019-02-15 22:51:04 -08:00
Arun Kulshreshtha
9c6b914a22 types: move Key and NodeInfo out of revisionstore
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
2019-02-15 22:51:04 -08:00
Stefan Filip
63c87a7500 Add test constructor for Node
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
2019-02-14 13:32:05 -08:00
Arun Kulshreshtha
a7a1abae63 types: derive Serialize and Deserialize for Node
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
2019-01-29 04:44:15 -08:00
Arun Kulshreshtha
2540614d3b types: convert to Rust 2018
Summary: title

Reviewed By: singhsrb

Differential Revision: D13858439

fbshipit-source-id: d5b0a1f0870abab9948fccba19c51a72d8a09bfc
2019-01-29 04:44:15 -08:00
Mark Thomas
3b9eb801e1 types: use Fallible
Summary:
Use the `Fallible` type alias provided by `failure` rather than defining our
own.

Differential Revision: D13657313

fbshipit-source-id: ae249bc15037cc2be019ce7ce8a440c153aa31cc
2019-01-15 03:50:47 -08:00
Mark Thomas
1346ff92c4 types: implement Debug for Node
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
2018-12-14 06:43:40 -08:00
Mark Thomas
88ab626e9a types: Add Nodes::random_distinct to randomly generate sets of nodes
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
2018-12-14 06:43:40 -08:00
Mark Thomas
d0c03f6aaf types: Add WriteNodeExt and ReadNodeExt
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
2018-12-14 06:43:40 -08:00
Jun Wu
616306543b codemod: use explicit versions in Cargo.toml
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
2018-11-15 18:54:06 -08:00
Jun Wu
3adc813687 codemod: add copyright headers
Summary: This is just the result of running `./contrib/fix-code.py $(hg files .)`

Reviewed By: ikostia

Differential Revision: D10213075

fbshipit-source-id: 88577c9b9588a5b44fcf1fe6f0082815dfeb363a
2018-10-26 15:09:12 -07:00
Jun Wu
7752e9e81f rustlib: move Node to a separate "types" crate
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
2018-10-03 18:19:27 -07:00