meta: add files
This commit is contained in:
commit
bd20e7d29a
11 changed files with 251 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
4
.idea/encodings.xml
generated
Normal file
4
.idea/encodings.xml
generated
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/sidestepper.iml" filepath="$PROJECT_DIR$/.idea/sidestepper.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
11
.idea/sidestepper.iml
generated
Normal file
11
.idea/sidestepper.iml
generated
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="EMPTY_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sidestepper"
|
||||||
|
version = "5.0.0"
|
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "sidestepper"
|
||||||
|
version = "5.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
14
LICENCE
Normal file
14
LICENCE
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
BSD Zero Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2025 mark joshwel <mark@joshwel.co>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
65
README.md
Normal file
65
README.md
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# sota staircase SideStepper
|
||||||
|
|
||||||
|
a fast .gitignore-respecting large file finder for .git repositories trying to
|
||||||
|
weed out large LFS files
|
||||||
|
|
||||||
|
**this is brain made software**: large language-based code generation has not
|
||||||
|
directly used here. but i'd be lying if i said i didn't ask chatgpt if there
|
||||||
|
was a better way to check a boolean result lol
|
||||||
|
|
||||||
|
## quickstart
|
||||||
|
|
||||||
|
### installing a binary
|
||||||
|
|
||||||
|
**note:** all non-windows builds are statically linked
|
||||||
|
|
||||||
|
- Windows
|
||||||
|
- Linux
|
||||||
|
- macOS universal
|
||||||
|
- macOS amd64
|
||||||
|
- macOS aarch64
|
||||||
|
|
||||||
|
(also available in the 'releases' tab wherever this repository is situated in)
|
||||||
|
|
||||||
|
### build it yourself
|
||||||
|
|
||||||
|
1. [get rust and cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html#install-rust-and-cargo)
|
||||||
|
2. `cargo build release`
|
||||||
|
|
||||||
|
**nix users, rejoice:** `nix run github:markjoshwel/sidestepper` or `nix run git+:https://forge.joshwel.co/mark/sidestepper`
|
||||||
|
|
||||||
|
### running it
|
||||||
|
|
||||||
|
```text
|
||||||
|
./sidestepper
|
||||||
|
```
|
||||||
|
|
||||||
|
or on windows,
|
||||||
|
|
||||||
|
```text
|
||||||
|
./sidestepper.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
it'll find for a `.git` directory in the current or parent directories, if you
|
||||||
|
want to use this not in the context i usually use this for, pass in
|
||||||
|
`--search-here` to treat the current working directory as the 'repository root'
|
||||||
|
|
||||||
|
it'll then make a `.sotaignore` file that i use in my other tooling,
|
||||||
|
but if you want output more friendly for integration in other places,
|
||||||
|
pass in `--plumbing` for it to output encountered large files, line-by-line, to
|
||||||
|
stdout
|
||||||
|
|
||||||
|
## historical changes
|
||||||
|
|
||||||
|
- v5 (i3/a4) - rewritten in rust lol
|
||||||
|
- v4 (i2/a4) - optimised single iod-ttt
|
||||||
|
- v3 (i2/a3) - faster matching by remembering ignored directories (ignore on demand, 'iod')
|
||||||
|
- v2 (i2/a2) - corrected ignored directory matching (named 'trytrytry')
|
||||||
|
- v1 (i1/a1) - original python script, still embedded within ReStepper
|
||||||
|
|
||||||
|
## licence
|
||||||
|
|
||||||
|
with all my heart, copyright (c) 2025 mark joshwel
|
||||||
|
|
||||||
|
the sota staircase SideStepper is permissively licenced, not needing
|
||||||
|
attribution, under the [0BSD licence](LICENCE). go ham.
|
121
src/main.rs
Normal file
121
src/main.rs
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
// sota staircase SideStepper
|
||||||
|
// a fast .gitignore-respecting large file finder
|
||||||
|
//
|
||||||
|
// Copyright (c) 2025 mark joshwel <mark@joshwel.co>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||||
|
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
const SOTA_SIDESTEP_CHUNK_SIZE: u16 = 16;
|
||||||
|
const SOTA_SIDESTEP_MAX_WORKERS: u16 = 4;
|
||||||
|
const SOTA_SIDESTEP_LARGE_FILE_SIZE: u64 = 100000000; // 100mb
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Behaviour {
|
||||||
|
repo_dir_path: PathBuf,
|
||||||
|
repo_sotaignore_path: PathBuf,
|
||||||
|
parallel: bool,
|
||||||
|
chunk_size: u16,
|
||||||
|
max_workers: u16,
|
||||||
|
large_file_size: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cli_get_behaviour() -> Result<Behaviour, Box<dyn Error>> {
|
||||||
|
// get environment variables
|
||||||
|
let chunk_size: u16 = match env::var("SOTA_SIDESTEP_CHUNK_SIZE") {
|
||||||
|
Ok(val) => val.parse::<u16>().unwrap_or(SOTA_SIDESTEP_CHUNK_SIZE),
|
||||||
|
Err(_) => SOTA_SIDESTEP_CHUNK_SIZE,
|
||||||
|
};
|
||||||
|
let max_workers: u16 = match env::var("SOTA_SIDESTEP_MAX_WORKERS") {
|
||||||
|
Ok(val) => val.parse::<u16>().unwrap_or(SOTA_SIDESTEP_MAX_WORKERS),
|
||||||
|
Err(_) => SOTA_SIDESTEP_MAX_WORKERS,
|
||||||
|
};
|
||||||
|
let large_file_size: u64 = match env::var("SOTA_SIDESTEP_LARGE_FILE_SIZE") {
|
||||||
|
Ok(val) => val.parse::<u64>().unwrap_or(SOTA_SIDESTEP_LARGE_FILE_SIZE),
|
||||||
|
Err(_) => SOTA_SIDESTEP_LARGE_FILE_SIZE,
|
||||||
|
};
|
||||||
|
let parallel: bool = 'get_parallel: {
|
||||||
|
// future me move this to a higher block if we ever need args
|
||||||
|
// anywhere else also what the hell, labeled blocks?
|
||||||
|
// huh -- the community seems wishy-washy on it,
|
||||||
|
// but this seems like a harmless use of em
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if env::var("SOTA_SIDESTEP_PARALLEL").is_ok() {
|
||||||
|
break 'get_parallel true;
|
||||||
|
}
|
||||||
|
if args.iter().any(|arg| arg == "--parallel") {
|
||||||
|
break 'get_parallel true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
// find repo dir
|
||||||
|
// go through each parent dir until one of them has a .git directory in it
|
||||||
|
let current_dir = env::current_dir().unwrap();
|
||||||
|
let mut dir = current_dir.as_path();
|
||||||
|
let mut possible_repo_dir_path: Option<&Path> = None;
|
||||||
|
while dir.components().count() > 1 {
|
||||||
|
// check if there's a .git directory nearby
|
||||||
|
if dir.join(".git/").try_exists().ok() == Some(true) {
|
||||||
|
possible_repo_dir_path = Option::from(dir);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate down!
|
||||||
|
if let Some(parent) = dir.parent() {
|
||||||
|
dir = parent;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if possible_repo_dir_path.is_none() {
|
||||||
|
return Err("could not find a .git repository in the current or parent directories".into());
|
||||||
|
}
|
||||||
|
let repo_dir_path = possible_repo_dir_path.unwrap();
|
||||||
|
Ok(Behaviour {
|
||||||
|
repo_dir_path: PathBuf::from(repo_dir_path),
|
||||||
|
repo_sotaignore_path: PathBuf::from(repo_dir_path.join(".sotaignore")),
|
||||||
|
parallel,
|
||||||
|
chunk_size,
|
||||||
|
max_workers,
|
||||||
|
large_file_size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
eprintln!("sota staircase SideStepper v5 (i3/a4)");
|
||||||
|
let behaviour = {
|
||||||
|
let behaviour = cli_get_behaviour();
|
||||||
|
// huh. pattern matching consumes the variable, so we ref (&) it. damn.
|
||||||
|
if let Err(e) = &behaviour {
|
||||||
|
eprintln!("critical error: {}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
behaviour.unwrap()
|
||||||
|
};
|
||||||
|
eprintln!(
|
||||||
|
" repo root : {}\n .sotaignore : {} ({})\n parallel : {}",
|
||||||
|
behaviour.repo_dir_path.to_str().unwrap(),
|
||||||
|
behaviour.repo_sotaignore_path.to_str().unwrap(),
|
||||||
|
{
|
||||||
|
if behaviour.repo_sotaignore_path.try_exists().ok() == Some(true) {
|
||||||
|
"exists"
|
||||||
|
} else {
|
||||||
|
"non-existent"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
behaviour.parallel
|
||||||
|
);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue