Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
cff-version: 1.2.0
message: "If you use ptfkit in your research, please cite it using these metadata."
title: "ptfkit: Pedotransfer functions for estimating soil hydraulic properties"
type: software
abstract: >-
ptfkit is a specification-driven collection of pedotransfer functions for
estimating soil hydraulic properties through consistent Python, Rust, C,
and C++ interfaces.
authors:
- family-names: Fomin
given-names: Dmitry
email: "fomin_ds@esoil.ru"
orcid: "https://orcid.org/0000-0003-3733-0284"
- family-names: Shumilin
given-names: Petr
email: "shumpet03@yandex.ru"
- family-names: Tolstygin
given-names: Kirill
email: "tolstygin_kd@esoil.ru"
orcid: "https://orcid.org/0009-0005-1395-3745"
- family-names: Tsymbarovich
given-names: Petr
email: "tpr@esoil.ru"
orcid: "https://orcid.org/0000-0001-8591-2612"
version: 0.2.0
date-released: "2026-08-20"
license: MIT
repository-code: "https://github.com/AgroDT/ptfkit"
url: "https://agrodt.github.io/ptfkit/"
keywords:
- pedotransfer functions
- soil hydraulic properties
- soil science
- scientific software
20 changes: 3 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,6 @@ specification must preserve.

## Citation

### APA

```text
AgroDT lab (2025). ptfkit repository [Computer software]. https://github.com/AgroDT/ptfkit
```

### BibTeX

```bibtex
@misc{ptfkit,
author = {AgroDT lab},
title = {ptfkit repository},
year = {2025},
howpublished = {\url{https://github.com/AgroDT/ptfkit}},
url = {https://github.com/AgroDT/ptfkit}
}
```
If you use ptfkit in research, cite the software using the metadata in
[`CITATION.cff`](./CITATION.cff). On GitHub, select **Cite this repository** in
the repository sidebar to export the citation in APA or BibTeX format.
58 changes: 58 additions & 0 deletions codegen/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ use anyhow::{Context, Result, bail};
const RUST_MANIFEST: &str = "targets/ptfkit-rs/Cargo.toml";
const PYTHON_VERSION: &str = "targets/ptfkit-py/src/ptfkit/_version.py";
const NATIVE_VERSION: &str = "targets/ptfkit-native/cmake/ptfkitVersion.cmake";
const CITATION_FILE: &str = "CITATION.cff";

pub(crate) fn run(root: &Path, version: &str) -> Result<()> {
validate(version)?;
update_rust_manifest(root, version)?;
update_citation_file(root, version)?;
fs::write(
root.join(PYTHON_VERSION),
format!("# @generated by ptfkit-codegen; do not edit.\n__version__ = '{version}'\n"),
Expand Down Expand Up @@ -63,3 +65,59 @@ fn update_rust_manifest(root: &Path, version: &str) -> Result<()> {
fs::write(path, output).with_context(|| format!("writing {RUST_MANIFEST}"))?;
Ok(())
}

fn update_citation_file(root: &Path, version: &str) -> Result<()> {
let path = root.join(CITATION_FILE);
let citation = fs::read_to_string(&path).with_context(|| format!("reading {CITATION_FILE}"))?;
let output = replace_citation_version(&citation, version)?;

fs::write(path, output).with_context(|| format!("writing {CITATION_FILE}"))?;
Ok(())
}

fn replace_citation_version(citation: &str, version: &str) -> Result<String> {
let mut output = String::with_capacity(citation.len());
let mut updated = false;

for line in citation.lines() {
if line.starts_with("version: ") {
output.push_str(&format!("version: {version}\n"));
updated = true;
} else {
output.push_str(line);
output.push('\n');
}
}

if !updated {
bail!("missing version in {CITATION_FILE}")
}

Ok(output)
}

#[cfg(test)]
mod tests {
use super::replace_citation_version;

#[test]
fn replaces_top_level_citation_version() {
let citation = "cff-version: 1.2.0\ntitle: ptfkit\nversion: 0.2.0\n";

let updated = replace_citation_version(citation, "0.3.0").unwrap();

assert_eq!(
updated,
"cff-version: 1.2.0\ntitle: ptfkit\nversion: 0.3.0\n"
);
}

#[test]
fn rejects_citation_without_version() {
let citation = "cff-version: 1.2.0\ntitle: ptfkit\n";

let error = replace_citation_version(citation, "0.3.0").unwrap_err();

assert_eq!(error.to_string(), "missing version in CITATION.cff");
}
}