## What is this?
This is intended to serve as a reference for developers interested in working on/contributing to Pijul.
## Before submitting a patch
Please run `cargo fmt` to format your changes before submitting a patch. As long as you have cargo fmt installed, you can get pijul to do this for you by adding the following to `.pijul/config`:
```
[hooks]
record = [ "cargo fmt" ]
```
## For contributors using Rust Analyzer (esp. with VScode):
By default, Rust Analyzer runs `cargo check` with the `--test` flag included, which can really slow down editor interactions and feedback. For VScode users, it's recommended to set up a workspace in your local copy of the pijul repository. An example of a basic workspace file can be found below; you would edit the `<your_carg_bin_path>` entry to point to your cargo binary, and place this file in the project root as IE `pijul.code-workspace`. When you open vscode, it will ask you if you want to open the workspace.
Example pijul.code-workspace:
```
{
"folders": [
{
"path": "."
}
],
"settings": {
"rust-analyzer.checkOnSave.overrideCommand": [
"<your_cargo_bin_path>"
"check",
"--workspace",
"--message-format=json",
"--manifest-path",
"./Cargo.toml",
"--lib",
"--bins",
"--examples"
]
}
}
```
For users of other editors, if RA is taking a long time and reporting a large number of errors, this would be the first place to look. If you have a specific workaround for your setup, please submit it as a patch and it will be added to this list.
## Scripting tricks (for tests, automation, etc.)
When testing modifications or debugging issues, it's often the case that you'll want to recreate fairly complex situations and repository states quickly and in a reproducible manner. To that end, it's useful to know how to write scripts that interact with pijul.
### Forcing specific timestamps
`pijul record --timestamp <time>`
### Minimizing interactive editor pop-ups/pager interactions during script execution
#### Record a patch without being prompted for hunk selection/change message
`pijul record --all --message "<msg>"`
#### Push/pull without being prompted for hunk selection
`pijul pull --all <remote>`
`pijul push --all <remote>`
## Logging
Pijul uses [log](https://crates.io/crates/log) and [env_logger](https://crates.io/crates/env_logger) to log messages to stdout; messages are tagged with priority levels (`log` provides the levels error, warn, info, debug, trace). The function that sets up pijul's logging is `pijul::env_logger_init`. You can consult the documentation for `log` and `env_logger` to get more information, but to turn logging on, run pijul with:
```
RUST_LOG=<level> <command>
```
for example:
```
RUST_LOG=warn pijul change
```
A quick and dirty example of how you can add new logging messages with the macros provided by log (which use standard format string syntax):
```
fn some_fun() {
...
log::warn!("I want to see this value: {}", value);
...
}
```
## Important types, API touchstones
### Transactions
The big ticket source of state is a transaction (often these variables are called `txn` in the source code). There are different `_TxnT` traits implemented by different types of transaction, but the basic concrete type for a transaction is `GenericTxn`
### pijul::repository::Repository
Unsurprisingly, this contains a lot of state pertaining to a particular repository.
### pijul::remote::RemoteRepo
`RemoteRepo` is a concrete type frequently used to interact with a Transaction. `RemoteRepo` is an enum, with a variant for each kind of remote; Local, Ssh, Http, LocalChannel, as well as a bookkeeping `None` variant. For clarity, `Local` represents a local repo other than the one the user is currently working within, while `LocalChannel` is a channel within the current repo.
### libpijul::pristine::Hash and libpijul::pristine::Merkle
`Hash` and `SerializedHash` are sequences of bytes which represent changes.
`Merkle` and `SerializedMerkle` are sequences of bytes which represent the state of a repository.
Both `Hash` and `Merkle` appear to users as strings of [base32](https://en.wikipedia.org/wiki/Base32).
You can freely convert between Hash <-> SerializedHash and Merkle <-> SerializedMerkle using the `From` and `Into` traits. Example: `Hash::from(_)` or `my_hash.into()`.
## Common tasks in Pijul's codebase
### Visiting the change log
Use `TxnTExt::reverse_log(..)` (most recent first) or `TxnTExt::log(..)` (oldest first). You'll need a transaction and a `ChannelRef`. An example can be found in `pijul::command::log.rs`.