diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f8de14154..d5704d9355 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog + +## 0.18.3 - 2024-03-18 +[0.18.2...0.18.3](https://github.com/rust-lang/git2-rs/compare/git2-0.18.2...git2-0.18.3) + +### Added + +- Added `opts::` functions to get / set libgit2 mwindow options + [#1035](https://github.com/rust-lang/git2-rs/pull/1035) + + +### Changed + +- Updated examples to use clap instead of structopt + [#1007](https://github.com/rust-lang/git2-rs/pull/1007) + ## 0.18.2 - 2024-02-06 [0.18.1...0.18.2](https://github.com/rust-lang/git2-rs/compare/git2-0.18.1...git2-0.18.2) diff --git a/Cargo.toml b/Cargo.toml index 76c4a62f48..6359ac058c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git2" -version = "0.18.2" +version = "0.18.3" authors = ["Josh Triplett ", "Alex Crichton "] license = "MIT OR Apache-2.0" readme = "README.md" @@ -27,7 +27,7 @@ openssl-sys = { version = "0.9.45", optional = true } openssl-probe = { version = "0.1", optional = true } [dev-dependencies] -structopt = "0.3" +clap = { version = "4.4.13", features = ["derive"] } time = "0.1.39" tempfile = "3.1.0" diff --git a/FUNDING.json b/FUNDING.json new file mode 100644 index 0000000000..480d41540c --- /dev/null +++ b/FUNDING.json @@ -0,0 +1,7 @@ +{ + "drips": { + "ethereum": { + "ownedBy": "0x298f6e7CC02D6aa94E2b135f46F1761da7A44E58" + } + } +} diff --git a/README.md b/README.md index 46b56b022f..70c2247b64 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ libgit2 bindings for Rust. ```toml [dependencies] -git2 = "0.18.2" +git2 = "0.18.3" ``` ## Rust version requirements diff --git a/ci/publish.sh b/ci/publish.sh index 69c2556bca..cfc084699c 100755 --- a/ci/publish.sh +++ b/ci/publish.sh @@ -18,7 +18,7 @@ function publish { # Check crates.io if it is already published set +e - output=`curl --fail --silent --head https://crates.io/api/v1/crates/$crate_name/$version/download` + output=`curl --fail --silent --head --location https://static.crates.io/crates/$crate_name/$version/download` res="$?" set -e case $res in diff --git a/examples/add.rs b/examples/add.rs index 25e972c7aa..57c9bb10a9 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -15,15 +15,15 @@ #![deny(warnings)] #![allow(trivial_casts)] +use clap::Parser; use git2::Repository; use std::path::Path; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "spec")] arg_spec: Vec, - #[structopt(name = "dry_run", short = "n", long)] + #[structopt(name = "dry_run", short = 'n', long)] /// dry run flag_dry_run: bool, #[structopt(name = "verbose", short, long)] @@ -73,7 +73,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/blame.rs b/examples/blame.rs index 7cb1b69470..202989b3f0 100644 --- a/examples/blame.rs +++ b/examples/blame.rs @@ -14,25 +14,25 @@ #![deny(warnings)] +use clap::Parser; use git2::{BlameOptions, Repository}; use std::io::{BufRead, BufReader}; use std::path::Path; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] #[allow(non_snake_case)] struct Args { #[structopt(name = "path")] arg_path: String, #[structopt(name = "spec")] arg_spec: Option, - #[structopt(short = "M")] + #[structopt(short = 'M')] /// find line moves within and across files flag_M: bool, - #[structopt(short = "C")] + #[structopt(short = 'C')] /// find line copies within and across files flag_C: bool, - #[structopt(short = "F")] + #[structopt(short = 'F')] /// follow only the first parent commits flag_F: bool, } @@ -96,7 +96,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/cat-file.rs b/examples/cat-file.rs index 0ce21b34aa..6196b9bb9f 100644 --- a/examples/cat-file.rs +++ b/examples/cat-file.rs @@ -16,23 +16,23 @@ use std::io::{self, Write}; +use clap::Parser; use git2::{Blob, Commit, ObjectType, Repository, Signature, Tag, Tree}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "object")] arg_object: String, - #[structopt(short = "t")] + #[structopt(short = 't')] /// show the object type flag_t: bool, - #[structopt(short = "s")] + #[structopt(short = 's')] /// show the object size flag_s: bool, - #[structopt(short = "e")] + #[structopt(short = 'e')] /// suppress all output flag_e: bool, - #[structopt(short = "p")] + #[structopt(short = 'p')] /// pretty print the contents of the object flag_p: bool, #[structopt(name = "quiet", short, long)] @@ -141,7 +141,7 @@ fn show_sig(header: &str, sig: Option) { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/clone.rs b/examples/clone.rs index 5af73222f0..f6d00b14b6 100644 --- a/examples/clone.rs +++ b/examples/clone.rs @@ -14,14 +14,14 @@ #![deny(warnings)] +use clap::Parser; use git2::build::{CheckoutBuilder, RepoBuilder}; use git2::{FetchOptions, Progress, RemoteCallbacks}; use std::cell::RefCell; use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "url")] arg_url: String, @@ -118,7 +118,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/diff.rs b/examples/diff.rs index 62f165db39..7440149ba0 100644 --- a/examples/diff.rs +++ b/examples/diff.rs @@ -14,12 +14,12 @@ #![deny(warnings)] +use clap::Parser; use git2::{Blob, Diff, DiffOptions, Error, Object, ObjectType, Oid, Repository}; use git2::{DiffDelta, DiffFindOptions, DiffFormat, DiffHunk, DiffLine}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] #[allow(non_snake_case)] struct Args { #[structopt(name = "from_oid")] @@ -56,19 +56,19 @@ struct Args { #[structopt(name = "no-color", long)] /// never use color output flag_no_color: bool, - #[structopt(short = "R")] + #[structopt(short = 'R')] /// swap two inputs flag_R: bool, - #[structopt(name = "text", short = "a", long)] + #[structopt(name = "text", short = 'a', long)] /// treat all files as text flag_text: bool, #[structopt(name = "ignore-space-at-eol", long)] /// ignore changes in whitespace at EOL flag_ignore_space_at_eol: bool, - #[structopt(name = "ignore-space-change", short = "b", long)] + #[structopt(name = "ignore-space-change", short = 'b', long)] /// ignore changes in amount of whitespace flag_ignore_space_change: bool, - #[structopt(name = "ignore-all-space", short = "w", long)] + #[structopt(name = "ignore-all-space", short = 'w', long)] /// ignore whitespace when comparing lines flag_ignore_all_space: bool, #[structopt(name = "ignored", long)] @@ -95,19 +95,19 @@ struct Args { #[structopt(name = "summary", long)] /// output condensed summary of header info flag_summary: bool, - #[structopt(name = "find-renames", short = "M", long)] + #[structopt(name = "find-renames", short = 'M', long)] /// set threshold for finding renames (default 50) flag_find_renames: Option, - #[structopt(name = "find-copies", short = "C", long)] + #[structopt(name = "find-copies", short = 'C', long)] /// set threshold for finding copies (default 50) flag_find_copies: Option, #[structopt(name = "find-copies-harder", long)] /// inspect unmodified files for sources of copies flag_find_copies_harder: bool, - #[structopt(name = "break_rewrites", short = "B", long)] + #[structopt(name = "break_rewrites", short = 'B', long)] /// break complete rewrite changes into pairs flag_break_rewrites: bool, - #[structopt(name = "unified", short = "U", long)] + #[structopt(name = "unified", short = 'U', long)] /// lints of context to show flag_unified: Option, #[structopt(name = "inter-hunk-context", long)] @@ -360,7 +360,7 @@ impl Args { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/fetch.rs b/examples/fetch.rs index 64374a6d48..f3a11dffbd 100644 --- a/examples/fetch.rs +++ b/examples/fetch.rs @@ -14,12 +14,12 @@ #![deny(warnings)] +use clap::Parser; use git2::{AutotagOption, FetchOptions, RemoteCallbacks, Repository}; use std::io::{self, Write}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "remote")] arg_remote: Option, @@ -119,7 +119,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/init.rs b/examples/init.rs index ee827087f1..3ae79082d7 100644 --- a/examples/init.rs +++ b/examples/init.rs @@ -14,11 +14,11 @@ #![deny(warnings)] +use clap::Parser; use git2::{Error, Repository, RepositoryInitMode, RepositoryInitOptions}; use std::path::{Path, PathBuf}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "directory")] arg_directory: String, @@ -137,7 +137,7 @@ fn parse_shared(shared: &str) -> Result { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/log.rs b/examples/log.rs index ad3bb354d0..8e459cc6f3 100644 --- a/examples/log.rs +++ b/examples/log.rs @@ -14,12 +14,12 @@ #![deny(warnings)] +use clap::Parser; use git2::{Commit, DiffOptions, ObjectType, Repository, Signature, Time}; use git2::{DiffFormat, Error, Pathspec}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "topo-order", long)] /// sort commits in topological order @@ -45,7 +45,7 @@ struct Args { #[structopt(name = "skip", long)] /// number of commits to skip flag_skip: Option, - #[structopt(name = "max-count", short = "n", long)] + #[structopt(name = "max-count", short = 'n', long)] /// maximum number of commits to show flag_max_count: Option, #[structopt(name = "merges", long)] @@ -302,7 +302,7 @@ impl Args { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/ls-remote.rs b/examples/ls-remote.rs index 1808459416..f88baaf906 100644 --- a/examples/ls-remote.rs +++ b/examples/ls-remote.rs @@ -14,10 +14,10 @@ #![deny(warnings)] +use clap::Parser; use git2::{Direction, Repository}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "remote")] arg_remote: String, @@ -43,7 +43,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/pull.rs b/examples/pull.rs index 61251b481b..27f461e546 100644 --- a/examples/pull.rs +++ b/examples/pull.rs @@ -12,12 +12,12 @@ * . */ +use clap::Parser; use git2::Repository; use std::io::{self, Write}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { arg_remote: Option, arg_branch: Option, @@ -200,7 +200,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/rev-list.rs b/examples/rev-list.rs index 9b49877283..2eaed78e9a 100644 --- a/examples/rev-list.rs +++ b/examples/rev-list.rs @@ -15,10 +15,10 @@ #![deny(warnings)] +use clap::Parser; use git2::{Error, Oid, Repository, Revwalk}; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "topo-order", long)] /// sort commits in topological order @@ -97,7 +97,7 @@ fn push(revwalk: &mut Revwalk, id: Oid, hide: bool) -> Result<(), Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/rev-parse.rs b/examples/rev-parse.rs index a465f15a4d..8d3934ea8c 100644 --- a/examples/rev-parse.rs +++ b/examples/rev-parse.rs @@ -14,10 +14,10 @@ #![deny(warnings)] +use clap::Parser; use git2::Repository; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { #[structopt(name = "spec")] arg_spec: String, @@ -52,7 +52,7 @@ fn run(args: &Args) -> Result<(), git2::Error> { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/status.rs b/examples/status.rs index 4f7bc791c0..0ed61711c8 100644 --- a/examples/status.rs +++ b/examples/status.rs @@ -14,12 +14,12 @@ #![deny(warnings)] +use clap::Parser; use git2::{Error, ErrorCode, Repository, StatusOptions, SubmoduleIgnore}; use std::str; use std::time::Duration; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { arg_spec: Vec, #[structopt(name = "long", long)] @@ -433,7 +433,7 @@ impl Args { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/examples/tag.rs b/examples/tag.rs index c44c2887d2..5d2af02063 100644 --- a/examples/tag.rs +++ b/examples/tag.rs @@ -14,11 +14,11 @@ #![deny(warnings)] +use clap::Parser; use git2::{Commit, Error, Repository, Tag}; use std::str; -use structopt::StructOpt; -#[derive(StructOpt)] +#[derive(Parser)] struct Args { arg_tagname: Option, arg_object: Option, @@ -119,7 +119,7 @@ fn print_list_lines(message: Option<&str>, args: &Args) { } fn main() { - let args = Args::from_args(); + let args = Args::parse(); match run(&args) { Ok(()) => {} Err(e) => println!("error: {}", e), diff --git a/src/call.rs b/src/call.rs index d9fd234681..95350d2690 100644 --- a/src/call.rs +++ b/src/call.rs @@ -1,5 +1,4 @@ #![macro_use] -use libc; use crate::Error; @@ -54,8 +53,6 @@ mod impls { use std::ffi::CString; use std::ptr; - use libc; - use crate::call::Convert; use crate::{raw, BranchType, ConfigLevel, Direction, ObjectType, ResetType}; use crate::{ diff --git a/src/commit.rs b/src/commit.rs index 4887e927e6..7fef508096 100644 --- a/src/commit.rs +++ b/src/commit.rs @@ -1,4 +1,3 @@ -use libc; use std::iter::FusedIterator; use std::marker; use std::mem; diff --git a/src/config.rs b/src/config.rs index ae5c4ff63a..6f12efc322 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,3 @@ -use libc; use std::ffi::CString; use std::marker; use std::path::{Path, PathBuf}; diff --git a/src/cred.rs b/src/cred.rs index 72d9485e82..fc4af1e4eb 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -5,7 +5,6 @@ use std::mem; use std::path::Path; use std::process::{Command, Stdio}; use std::ptr; -use url; use crate::util::Binding; use crate::{raw, Config, Error, IntoCString}; diff --git a/src/oid.rs b/src/oid.rs index 145458aec0..35516cb181 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -1,4 +1,3 @@ -use libc; use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; diff --git a/src/opts.rs b/src/opts.rs index c709fd0c22..88f4eb74b7 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -233,6 +233,111 @@ where Ok(()) } +/// Get the maximum mmap window size +/// +/// # Safety +/// This function is reading a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_mwindow_size() -> Result { + crate::init(); + + let mut size = 0; + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_SIZE as libc::c_int, + &mut size + )); + + Ok(size) +} + +/// Set the maximum mmap window size +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_mwindow_size(size: libc::size_t) -> Result<(), Error> { + crate::init(); + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_SIZE as libc::c_int, + size + )); + + Ok(()) +} + +/// Get the maximum memory that will be mapped in total by the library +/// +/// # Safety +/// This function is reading a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_mwindow_mapped_limit() -> Result { + crate::init(); + + let mut limit = 0; + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_MAPPED_LIMIT as libc::c_int, + &mut limit + )); + + Ok(limit) +} + +/// Set the maximum amount of memory that can be mapped at any time +/// by the library. +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_mwindow_mapped_limit(limit: libc::size_t) -> Result<(), Error> { + crate::init(); + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_MAPPED_LIMIT as libc::c_int, + limit + )); + + Ok(()) +} + +/// Get the maximum number of files that will be mapped at any time by the +/// library. +/// +/// # Safety +/// This function is reading a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn get_mwindow_file_limit() -> Result { + crate::init(); + + let mut limit = 0; + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_GET_MWINDOW_FILE_LIMIT as libc::c_int, + &mut limit + )); + + Ok(limit) +} + +/// Set the maximum number of files that can be mapped at any time +/// by the library. The default (0) is unlimited. +/// +/// # Safety +/// This function is modifying a C global without synchronization, so it is not +/// thread safe, and should only be called before any thread is spawned. +pub unsafe fn set_mwindow_file_limit(limit: libc::size_t) -> Result<(), Error> { + crate::init(); + + try_call!(raw::git_libgit2_opts( + raw::GIT_OPT_SET_MWINDOW_FILE_LIMIT as libc::c_int, + limit + )); + + Ok(()) +} + #[cfg(test)] mod test { use super::*; @@ -241,4 +346,28 @@ mod test { fn smoke() { strict_hash_verification(false); } + + #[test] + fn mwindow_size() { + unsafe { + assert!(set_mwindow_size(1024).is_ok()); + assert!(get_mwindow_size().unwrap() == 1024); + } + } + + #[test] + fn mwindow_mapped_limit() { + unsafe { + assert!(set_mwindow_mapped_limit(1024).is_ok()); + assert!(get_mwindow_mapped_limit().unwrap() == 1024); + } + } + + #[test] + fn mwindow_file_limit() { + unsafe { + assert!(set_mwindow_file_limit(1024).is_ok()); + assert!(get_mwindow_file_limit().unwrap() == 1024); + } + } } diff --git a/src/pathspec.rs b/src/pathspec.rs index 48174fcc19..16850dc210 100644 --- a/src/pathspec.rs +++ b/src/pathspec.rs @@ -1,5 +1,5 @@ use libc::size_t; -use std::iter::{FusedIterator, IntoIterator}; +use std::iter::FusedIterator; use std::marker; use std::ops::Range; use std::path::Path; diff --git a/src/remote.rs b/src/remote.rs index 807c108e1d..a15a095010 100644 --- a/src/remote.rs +++ b/src/remote.rs @@ -1,4 +1,3 @@ -use libc; use raw::git_strarray; use std::iter::FusedIterator; use std::marker; diff --git a/src/repo.rs b/src/repo.rs index 93176183fb..b41b42480c 100644 --- a/src/repo.rs +++ b/src/repo.rs @@ -1,7 +1,6 @@ use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::env; use std::ffi::{CStr, CString, OsStr}; -use std::iter::IntoIterator; use std::mem; use std::path::{Path, PathBuf}; use std::ptr; diff --git a/src/signature.rs b/src/signature.rs index 83fbbf5935..7c9ffb3933 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -1,4 +1,3 @@ -use libc; use std::ffi::CString; use std::fmt; use std::marker; diff --git a/src/tree.rs b/src/tree.rs index 31170ab5e1..ae8fe3b4c5 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1,4 +1,4 @@ -use libc::{self, c_char, c_int, c_void}; +use libc::{c_char, c_int, c_void}; use std::cmp::Ordering; use std::ffi::{CStr, CString}; use std::iter::FusedIterator; diff --git a/src/util.rs b/src/util.rs index 5f735bc004..4065492f76 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,6 @@ use libc::{c_char, c_int, size_t}; use std::cmp::Ordering; use std::ffi::{CString, OsStr, OsString}; -use std::iter::IntoIterator; use std::path::{Component, Path, PathBuf}; use crate::{raw, Error};