Skip to content

Commit 3a9d81e

Browse files
authored
Try #1:
2 parents d7afd44 + 00e4a33 commit 3a9d81e

File tree

8 files changed

+212
-1
lines changed

8 files changed

+212
-1
lines changed

.buildbot.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#! /bin/sh
2+
3+
set -e
4+
5+
export CARGO_HOME="`pwd`/.cargo"
6+
export RUSTUP_HOME="`pwd`/.rustup"
7+
8+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh
9+
sh rustup.sh --default-host x86_64-unknown-linux-gnu --default-toolchain stable -y --no-modify-path
10+
11+
export PATH=`pwd`/.cargo/bin/:$PATH
12+
13+
cargo fmt --all -- --check
14+
cargo test
15+
16+
which cargo-deny | cargo install cargo-deny || true
17+
if [ "X`which cargo-deny`" != "X"]; then
18+
cargo-deny check license
19+
else
20+
echo "Warning: couldn't run cargo-deny" > /dev/stderr
21+
fi

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "depub"
3+
version = "0.1.0"
4+
authors = ["Laurence Tratt <laurie@tratt.net>"]
5+
edition = "2018"
6+
readme = "README.md"
7+
license = "Apache-2.0 OR MIT"
8+
9+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
10+
11+
[dependencies]
12+
getopts = "0.2"
13+
regex = "1.4"

LICENSE-APACHE

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
2+
this file except in compliance with the License. You may obtain a copy of the
3+
License at
4+
5+
http://www.apache.org/licenses/LICENSE-2.0
6+
7+
Unless required by applicable law or agreed to in writing, software distributed
8+
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
9+
CONDITIONS OF ANY KIND, either express or implied. See the License for the
10+
specific language governing permissions and limitations under the License.

LICENSE-MIT

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Permission is hereby granted, free of charge, to any person obtaining a copy of
2+
this software and associated documentation files (the "Software"), to deal in
3+
the Software without restriction, including without limitation the rights to
4+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
5+
of the Software, and to permit persons to whom the Software is furnished to do
6+
so, subject to the following conditions:
7+
8+
The above copyright notice and this permission notice shall be included in all
9+
copies or substantial portions of the Software.
10+
11+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17+
SOFTWARE.

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,21 @@
1-
# depub
1+
# depub: minimise visibility
2+
3+
When working on medium or large sized Rust code bases, it can be hard to know
4+
whether the visibility of functions, structs, and so on are still at the
5+
minimum required. For example, sometimes functions that once needed to be `pub`
6+
now only need to be `pub(crate)`.
7+
8+
`depub` minimises the visibility of such elements in a code base: in essence,
9+
it does a string search for `pub`, replaces it with `pub crate` and sees if a
10+
test command still succeeds. If it does, it keeps that visibility; otherwise it
11+
tries the next in the list. As this suggests, `depub` is destructive: it
12+
overwrites files, so do not run it on source code that you do not want altered!
13+
14+
A standard way to run it is:
15+
16+
```
17+
$ cargo run depub -- -c "cargo check"
18+
```
19+
20+
`depub` informs you of its progress. After it is finished, `diff` your code
21+
base, and accept those of its recommendations you think appropriate.

bors.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
status = ["buildbot/buildbot-build-script"]
2+
3+
timeout_sec = 300 # 10 minutes
4+
5+
# Have bors delete auto-merged branches
6+
delete_merged_branches = true

src/main.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use getopts::Options;
2+
use regex::RegexBuilder;
3+
use std::{
4+
env,
5+
fs::{read_to_string, write},
6+
io::{stdout, Write},
7+
path::Path,
8+
process::{self, Command, Stdio},
9+
};
10+
11+
enum PubKind {
12+
Pub,
13+
Crate,
14+
Super,
15+
Private,
16+
}
17+
18+
fn process(cmd: &str, p: &Path) {
19+
let pub_regex = RegexBuilder::new("pub(?:\\s*\\(\\s*(.*?)\\s*\\))?")
20+
.multi_line(true)
21+
.build()
22+
.unwrap();
23+
let mut cur_txt = read_to_string(p).unwrap();
24+
let mut i = 0;
25+
let mut cl = pub_regex.capture_locations();
26+
while i < cur_txt.len() {
27+
print!(".");
28+
stdout().flush().ok();
29+
let old_txt = cur_txt.clone();
30+
let m = match pub_regex.captures_read_at(&mut cl, &old_txt, i) {
31+
Some(m) => m,
32+
None => break,
33+
};
34+
let mut kind = if let Some((start, end)) = cl.get(1) {
35+
match &cur_txt[start..end] {
36+
"crate" => PubKind::Crate,
37+
"super" => PubKind::Super,
38+
_ => todo!(),
39+
}
40+
} else {
41+
PubKind::Pub
42+
};
43+
let mut next_txt = cur_txt.clone();
44+
loop {
45+
let next_kind = match kind {
46+
PubKind::Pub => PubKind::Crate,
47+
PubKind::Crate => PubKind::Super,
48+
PubKind::Super => PubKind::Private,
49+
PubKind::Private => break,
50+
};
51+
let mut try_txt = cur_txt[..m.start()].to_string();
52+
let pub_txt = match next_kind {
53+
PubKind::Crate => "pub(crate) ",
54+
PubKind::Super => "pub(super) ",
55+
PubKind::Private => "",
56+
_ => unreachable!(),
57+
};
58+
try_txt.push_str(&pub_txt);
59+
try_txt.push_str(&cur_txt[m.end()..]);
60+
write(p, &try_txt).unwrap();
61+
match Command::new("sh")
62+
.arg("-c")
63+
.arg(cmd)
64+
.stderr(Stdio::null())
65+
.stdout(Stdio::null())
66+
.status()
67+
{
68+
Ok(s) if s.success() => {
69+
next_txt = try_txt;
70+
}
71+
_ => break,
72+
}
73+
kind = next_kind;
74+
}
75+
cur_txt = next_txt;
76+
if cur_txt.len() >= old_txt.len() {
77+
i += m.end() + (cur_txt.len() - old_txt.len());
78+
} else {
79+
i += m.end() - (old_txt.len() - cur_txt.len());
80+
}
81+
}
82+
write(p, cur_txt).unwrap();
83+
}
84+
85+
fn progname() -> String {
86+
match env::current_exe() {
87+
Ok(p) => p
88+
.file_name()
89+
.map(|x| x.to_str().unwrap_or("depub"))
90+
.unwrap_or("depub")
91+
.to_owned(),
92+
Err(_) => "depub".to_owned(),
93+
}
94+
}
95+
96+
/// Print out program usage then exit. This function must not be called after daemonisation.
97+
fn usage() -> ! {
98+
eprintln!(
99+
"Usage: {} -c <command> file_1 [... file_n]",
100+
progname = progname()
101+
);
102+
process::exit(1)
103+
}
104+
105+
fn main() {
106+
let matches = Options::new()
107+
.reqopt("c", "command", "Command to execute.", "string")
108+
.optflag("h", "help", "")
109+
.parse(env::args().skip(1))
110+
.unwrap_or_else(|_| usage());
111+
if matches.opt_present("h") || matches.free.is_empty() {
112+
usage();
113+
}
114+
115+
let cmd_str = matches.opt_str("c").unwrap();
116+
for p in matches.free {
117+
print!("{}: ", p);
118+
stdout().flush().ok();
119+
process(cmd_str.as_str(), &Path::new(&p));
120+
println!("");
121+
}
122+
}

0 commit comments

Comments
 (0)