Skip to content
Draft
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
54 changes: 53 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
# Changelog

## Unreleased
## 0.6.0

### Features

#### `pks rm` removes a pack

`pks rm packs/foo` deletes the pack's directory, after removing every mention of
it from other packs: their `dependencies`, `ignored_dependencies` and
`visible_to` lists, and the violations their `package_todo.yml` files record on
it. A todo file with nothing left in it is deleted. The lists are edited in
place, so the rest of each `package.yml`, comments and key order included, is
unchanged.

By default it won't remove a pack that other packs may still use. It first
looks for references from other packs to the pack's constants and lists any it
finds, because once the pack is gone `pks check` can no longer see them. It also
won't remove a pack with Ruby files under `lib/` that are outside the autoload
roots, since pks can't see references to the constants those files define. The
experimental parser reads definitions from every file, so with
`--experimental-parser` that check is skipped. `--force` removes the pack anyway
and leaves any remaining references for you to fix.

The root pack can't be removed. Neither can a pack with other packs inside it,
until those are removed.

### Fixes

Expand Down Expand Up @@ -83,6 +106,35 @@ longer found, so `pks check` reports it as stale until you run `pks update`. For
the same reason, `check-unused-dependencies` may now report a dependency that
only such an association used. packwerk still reports these references.

#### `check-unused-dependencies --auto-correct` keeps comments in `package.yml`

Auto-correct used to rewrite every `package.yml` it touched from scratch, which
deleted all of its comments and reordered its keys. It now removes the unused
entries from the `dependencies:` list and leaves the rest of the file as it
was, line endings included. A comment directly above a removed entry is
removed with it. If no dependencies remain, the `dependencies:` key is
removed too, as before.

If a list is written in a form that cannot be edited this way, such as
`dependencies: [packs/a, packs/b]`, the file is rewritten as before and a
warning is printed saying its comments were not preserved.

### Performance

#### A warm `pks check` skips reading files that haven't changed

The cache now records each file's modification time and size along with its
digest, and serves a file whose time and size both still match without reading
it. On a 51,000-file application this made a warm `pks check` 1.43 times as
fast. When either has changed, pks reads the file and compares digests as
before. On a filesystem that records times only to the second, where a
same-size edit within a second can keep both, it never takes the shortcut.

A tool that restores file times, such as `rsync -t`, `tar -p` or `cp -p`, can
put back different contents with the same size and time, and pks then serves
the old cached result. `touch` the file, or run with `--no-cache`, to check it
again.

## 0.5.0

### Breaking Changes
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[package]
name = "pks"
version = "0.5.0"
version = "0.6.0"
edition = "2021"
description = "Welcome! Please see https://github.com/rubyatscale/pks for more information!"
license = "MIT"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Usage: pks [OPTIONS] <COMMAND>
Commands:
greet Just saying hi
create Create a new pack
rm Delete a pack and remove references to it from other packs
check Look for violations in the codebase
check-contents Check file contents piped to stdin
update Update package_todo.yml files with the current violations
Expand Down
10 changes: 10 additions & 0 deletions src/packs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ pub(crate) mod ignored;
pub(crate) mod json;
pub(crate) mod monkey_patch_detection;
pub(crate) mod pack;
pub(crate) mod pack_list;
pub(crate) mod parsing;
pub(crate) mod raw_configuration;
pub(crate) mod remover;
pub(crate) mod template;
pub(crate) mod text;
pub mod walk_directory;
Expand Down Expand Up @@ -75,6 +77,14 @@ pub fn create(
Ok(())
}

pub fn remove(
configuration: &Configuration,
name: String,
force: bool,
) -> anyhow::Result<()> {
remover::remove(configuration, &name, force)
}

/// Determine whether to use colors based on the color choice
fn color_mode_for(color: ColorChoice) -> text::ColorMode {
match color {
Expand Down
25 changes: 7 additions & 18 deletions src/packs/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ mod visibility;

use crate::packs::checker_configuration::CheckerType;
// Internal imports
use crate::packs::pack::write_pack_to_disk;
use crate::packs::pack::Pack;
use crate::packs::pack_list::{self, PackList};
use crate::packs::package_todo;
use crate::packs::Configuration;
use crate::packs::SourceLocation;
Expand Down Expand Up @@ -451,7 +451,7 @@ pub(crate) fn update(configuration: &Configuration) -> anyhow::Result<()> {
configuration,
violations,
recorded_violations,
);
)?;
println!("Successfully updated package_todo.yml files!");

Ok(())
Expand All @@ -462,7 +462,11 @@ pub(crate) fn remove_unnecessary_dependencies(
) -> anyhow::Result<()> {
let unnecessary_dependencies = get_unnecessary_dependencies(configuration)?;
for (pack, dependency_names) in unnecessary_dependencies.iter() {
remove_reference_to_dependency(pack, dependency_names)?;
pack_list::remove_from_package_yml(
pack,
&[PackList::Dependencies],
dependency_names,
)?;
}
Ok(())
}
Expand Down Expand Up @@ -602,20 +606,5 @@ fn get_checkers(
]
}

fn remove_reference_to_dependency(
pack: &Pack,
dependency_names: &[String],
) -> anyhow::Result<()> {
let without_dependency = pack
.dependencies
.iter()
.filter(|dependency| !dependency_names.contains(dependency));
let updated_pack = Pack {
dependencies: without_dependency.cloned().collect(),
..pack.clone()
};
write_pack_to_disk(&updated_pack)?;
Ok(())
}
// Note: Display impl was removed from CheckAllResult. Use write_text() directly with Configuration.
// Tests for text formatting are in text.rs
15 changes: 15 additions & 0 deletions src/packs/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,18 @@ enum Command {
#[clap(about = "Create a new pack")]
Create { name: String },

#[clap(
about = "Delete a pack and remove references to it from other packs"
)]
Rm {
/// The pack to delete
pack: String,

/// Delete the pack even if other packs may still use its constants
#[arg(short, long)]
force: bool,
},

#[clap(about = "Look for violations in the codebase")]
Check {
/// Ignore recorded violations when reporting violations
Expand Down Expand Up @@ -334,5 +346,8 @@ pub fn run() -> anyhow::Result<()> {
packs::lint_package_yml_files(&configuration)
}
Command::Create { name } => packs::create(&configuration, name),
Command::Rm { pack, force } => {
packs::remove(&configuration, pack, force)
}
}
}
Loading
Loading