Skip to content

Commit

Permalink
Fix JSON output for created / deleted empty files (#4)
Browse files Browse the repository at this point in the history
* Fix JSON output for created / deleted empty files

* Changed vs Unchanged

* fmt

* Remove println

* Fix UT

* fmt
  • Loading branch information
nimrodkor authored Jul 31, 2024
1 parent a2ed4c3 commit 07ab1c5
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 44 deletions.
39 changes: 38 additions & 1 deletion src/display/json.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use lazy_static::lazy_static;
use line_numbers::LineNumber;
use regex::Regex;
use serde::{ser::SerializeStruct, Serialize, Serializer};

use crate::display::side_by_side::lines_with_novel;
use crate::parse::syntax::NON_EXISTENT_PERMISSIONS;
use crate::{
display::{
context::{all_matched_lines_filled, opposite_positions},
Expand All @@ -10,7 +14,11 @@ use crate::{
parse::syntax::{self, MatchedPos, StringKind},
summary::{DiffResult, FileContent, FileFormat},
};
use crate::display::side_by_side::lines_with_novel;

lazy_static! {
static ref FILE_PERMS_RE: Regex =
Regex::new("^File permissions changed from (\\d+) to (\\d+).$").unwrap();
}

#[derive(Debug, Serialize, PartialEq)]
#[serde(rename_all = "lowercase")]
Expand Down Expand Up @@ -62,6 +70,23 @@ impl<'f> File<'f> {
}
}

fn extract_status(extra_info: &'f Option<String>) -> Option<(String, String)> {
let temp = extra_info.clone().unwrap_or_default();
let line = temp.lines().last();
match line {
None => None,
Some(s) => {
if let Some(captures) = crate::display::json::FILE_PERMS_RE.captures(s) {
let from = captures[1].to_string();
let to = captures[2].to_string();
Some((from, to))
} else {
None
}
}
}
}

fn with_status(
language: &'f FileFormat,
path: &'f str,
Expand Down Expand Up @@ -99,6 +124,18 @@ impl<'f> From<&'f DiffResult> for File<'f> {
if hunks.is_empty() {
let status = if File::extract_old_path(&summary.extra_info).is_some() {
Status::Renamed
} else if let Some((from, to)) = File::extract_status(&summary.extra_info) {
match (from.as_str(), to.as_str()) {
(NON_EXISTENT_PERMISSIONS, _) => Status::Created,
(_, NON_EXISTENT_PERMISSIONS) => Status::Deleted,
_ => {
if from == to {
Status::Unchanged
} else {
Status::Changed
}
}
}
} else {
Status::Unchanged
};
Expand Down
69 changes: 33 additions & 36 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,29 @@
#![warn(clippy::todo)]
#![warn(clippy::dbg_macro)]

mod conflicts;
mod constants;
mod diff;
mod display;
mod exit_codes;
mod files;
mod hash;
mod line_parser;
mod lines;
mod options;
mod parse;
mod summary;
mod version;
mod words;

#[macro_use]
extern crate log;
extern crate pretty_env_logger;
use std::path::Path;
use std::{env, thread};

use display::style::print_warning;
use humansize::{format_size, BINARY};
use log::info;
use mimalloc::MiMalloc;
use owo_colors::OwoColorize;
use rayon::prelude::*;
use strum::IntoEnumIterator;
use typed_arena::Arena;

use display::style::print_warning;
use options::FilePermissions;
use options::USAGE;

use crate::conflicts::apply_conflict_markers;
use crate::conflicts::START_LHS_MARKER;
use crate::diff::changes::ChangeMap;
use crate::diff::dijkstra::ExceededGraphLimit;
use crate::diff::sliders::fix_all_sliders;
use crate::diff::{dijkstra, unchanged};
use crate::display::context::opposite_positions;
use crate::display::hunks::{matched_pos_to_hunks, merge_adjacent};
Expand All @@ -64,36 +59,38 @@ use crate::files::{
guess_content, read_file_or_die, read_files_or_die, read_or_die, relative_paths_in_either,
ProbableFileKind,
};
use crate::options::{DiffOptions, DisplayMode, DisplayOptions, FileArgument, Mode};
use crate::parse::guess_language::language_globs;
use crate::parse::guess_language::{guess, language_name, Language, LanguageOverride};
use crate::parse::syntax;

/// The global allocator used by difftastic.
///
/// Diffing allocates a large amount of memory, and `MiMalloc` performs
/// better.
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;

use std::path::Path;
use std::{env, thread};

use humansize::{format_size, BINARY};
use owo_colors::OwoColorize;
use rayon::prelude::*;
use strum::IntoEnumIterator;
use typed_arena::Arena;

use crate::diff::sliders::fix_all_sliders;
use crate::options::{DiffOptions, DisplayMode, DisplayOptions, FileArgument, Mode};
use crate::summary::{DiffResult, FileContent, FileFormat};
use crate::syntax::init_next_prev;
use crate::{
dijkstra::mark_syntax, lines::MaxLine, parse::syntax::init_all_info,
parse::tree_sitter_parser as tsp,
};

extern crate pretty_env_logger;
mod conflicts;
mod constants;
mod diff;
mod display;
mod exit_codes;
mod files;
mod hash;
mod line_parser;
mod lines;
mod options;
mod parse;
mod summary;
mod version;
mod words;

/// The global allocator used by difftastic.
///
/// Diffing allocates a large amount of memory, and `MiMalloc` performs
/// better.
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;

/// Terminate the process if we get SIGPIPE.
#[cfg(unix)]
Expand Down
11 changes: 5 additions & 6 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use const_format::formatcp;
use crossterm::tty::IsTty;
use itertools::Itertools;

use crate::parse::syntax::NON_EXISTENT_PERMISSIONS;
use crate::{
display::style::BackgroundColor,
exit_codes::EXIT_BAD_ARGUMENTS,
Expand Down Expand Up @@ -357,14 +358,12 @@ impl Display for FilePermissions {
}
}

impl TryFrom<&OsStr> for FilePermissions {
type Error = ();

fn try_from(s: &OsStr) -> Result<Self, Self::Error> {
impl From<&OsStr> for FilePermissions {
fn from(s: &OsStr) -> Self {
if s == "." {
Err(())
Self(NON_EXISTENT_PERMISSIONS.to_owned())
} else {
Ok(Self(s.to_string_lossy().into_owned()))
Self(s.to_string_lossy().into_owned())
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/parse/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use crate::{
lines::is_all_whitespace,
};

pub const NON_EXISTENT_PERMISSIONS: &'static str = "0000000";

/// A Debug implementation that does not recurse into the
/// corresponding node mentioned for Unchanged. Otherwise we will
/// infinitely loop on unchanged nodes, which both point to the other.
Expand Down
2 changes: 1 addition & 1 deletion tests/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ fn git_style_arguments_new_file() {
.arg("sample_files/simple_1.txt")
.arg("abcdef1234")
.arg("100644");
let predicate_fn = predicate::str::contains("File permissions changed").not();
let predicate_fn = predicate::str::contains("File permissions changed");
cmd.assert().stdout(predicate_fn);
}

Expand Down

0 comments on commit 07ab1c5

Please sign in to comment.