Skip to content

Feat/refactor filters #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Sep 15, 2024
Merged
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
83 changes: 83 additions & 0 deletions .github/workflows/prerelease.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Create Pre Release Binary

on:
pull_request:
types: [labeled]

jobs:
build-artifacts:
if: github.event.label.name == 'prerelease'
runs-on: ubuntu-latest
name: Build Artifacts
env:
binary_name: git-diff

steps:
- uses: actions/checkout@v4

- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-registry-

- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-index-

- name: Cache cargo build
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-build-

- name: Build
run: cargo build --release

- name: Create Archive Folder
run: mkdir ${{ runner.os }}

- name: Copy Artifact
run: cp target/release/${{ env.binary_name }} ${{ runner.os }}

- name: Create Tar Archive
run: tar -czf ${{ runner.os }}.tgz ${{ runner.os }}

- name: Store Archive
uses: actions/upload-artifact@v4
with:
name: ${{ runner.os }}
path: ${{ runner.os }}.tgz

create-pre-release:
needs: [build-artifacts]
runs-on: ubuntu-latest
name: Create Pre-release
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
- name: Get version
id: get_version
run: |
VERSION=$(cat version | tr -d '\n')
echo "Version: $VERSION"
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
- name: Create Release
uses: ncipollo/release-action@v1
with:
artifacts: "Linux/Linux.tgz"
tag: ${{ steps.get_version.outputs.VERSION }}-prerelease
allowUpdates: true
makeLatest: false
prerelease: true
commit: ${{ github.sha }}
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "git-diff"
version = "0.1.0"
version = "1.0.2"
edition = "2021"

[dependencies]
Expand Down
8 changes: 2 additions & 6 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ runs:
- name: Get Binary
shell: bash
run: |
BIN_URL=$(curl https://api.github.com/repos/LuisLiraC/git-diff/releases/tags/v1.0.1 | jq -r '.assets[0].browser_download_url')
BIN_URL=$(curl https://api.github.com/repos/LuisLiraC/git-diff/releases/tags/v1.0.2 | jq -r '.assets[0].browser_download_url')
curl -s -L $BIN_URL -o rust-binary.tgz
tar -xzvf rust-binary.tgz
mv ./Linux/git-diff ./git-diff
Expand All @@ -29,8 +29,4 @@ runs:
id: get-git-diff
shell: bash
run: |
PATTERNS="${{ inputs.patterns }}"
COMMA_SEPARATED_PATTERNS=$(echo "$PATTERNS" | tr '\n' ',' | sed -e 's/,$//' | sed 's/,$//' | sed 's/ //g')
echo "Files patterns: $COMMA_SEPARATED_PATTERNS"

./git-diff --patterns=$COMMA_SEPARATED_PATTERNS
./git-diff --patterns='${{ inputs.patterns }}'
71 changes: 38 additions & 33 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use git2::Repository;
use std::collections::HashSet;
use std::env;
use glob::Pattern;
use std::process::Command;
use std::time::Instant;

#[derive(Clone)]
#[derive(Clone, Debug)]
struct PatternFilter {
pattern: String,
exclude: bool,
Expand Down Expand Up @@ -32,13 +33,18 @@ fn main() {
let duration = start.elapsed();
println!("Getting changed files done in: {:?}", duration);

println!("Changed files: {:?}", changed_files);

let start = Instant::now();
let filtered_files = filter(changed_files, include_patterns_filters, exclude_patterns_filters);
let filtered_files = filter_files(changed_files, include_patterns_filters, exclude_patterns_filters);
let duration = start.elapsed();
println!("Filtering files done in: {:?}", duration);

let count = get_count(filtered_files.clone());

println!("Filtered files: {:?}", filtered_files);
println!("Count: {}", count);

Command::new("sh")
.arg("-c")
.arg(format!("echo \"DIFF_FILES={:?}\" >> $GITHUB_OUTPUT", filtered_files))
Expand All @@ -53,10 +59,18 @@ fn main() {
}

fn create_patterns_filters(arg: &str) -> Vec<PatternFilter> {
let patterns = arg
let binding = arg
.split('=')
.last()
.expect("Failed to get patterns")
.replace(" ", "")
.replace("\n", ",")
.replace("\r", "")
.replace(",,", ",")
.trim_end_matches(',')
.to_string();

let patterns = binding
.split(',')
.collect::<Vec<&str>>();

Expand Down Expand Up @@ -85,6 +99,7 @@ fn get_changed_files() -> Vec<String> {
let head = repository.head().expect("Failed to get HEAD");
let head_commit = head.peel_to_commit().expect("Failed to peel HEAD to commit");

// Refers to base branch in case of pull request. For example: main
let base_ref_env = env::var("GITHUB_BASE_REF").expect("Failed to get GITHUB_BASE_REF env variable");

Command::new("sh")
Expand Down Expand Up @@ -119,49 +134,39 @@ fn get_changed_files() -> Vec<String> {
changed_files
}

fn filter(changed_files: Vec<String>, include_patterns_filters: Vec<PatternFilter>, exclude_patterns_filters: Vec<PatternFilter>) -> Vec<String> {
let filtered_files: Vec<String> = include_patterns_filters
.iter()
.flat_map(|pattern| filter_files_by_pattern(pattern, &changed_files, &exclude_patterns_filters))
.collect();
fn filter_files(changed_files: Vec<String>, include_patterns_filters: HashSet<String>, exclude_patterns_filters: HashSet<String>) -> HashSet<String> {
let mut hash_set_filtered_files = HashSet::new();

filtered_files
}
for changed_file in changed_files.iter() {
include_patterns_filters.iter().for_each(|pattern| {
if Pattern::new(pattern).expect("Failed to create pattern").matches(changed_file) {
hash_set_filtered_files.insert(changed_file.to_string());
}

fn filter_files_by_pattern(pattern_filter: &PatternFilter, files: &Vec<String>, exclude_patterns: &Vec<PatternFilter>) -> Vec<String> {
let pattern = Pattern::new(&pattern_filter.pattern).expect("Failed to create pattern");

let mut filtered_files: Vec<String> = files
.iter()
.filter(|file| pattern.matches(file))
.filter(|_| pattern_filter.exclude == false)
.map(|file| file.to_string())
.collect();

for exclude_pattern in exclude_patterns.iter() {
filtered_files = filtered_files
.iter()
.filter(|file| !Pattern::new(&exclude_pattern.pattern).expect("Failed to create pattern").matches(file))
.map(|file| file.to_string())
.collect();
exclude_patterns_filters.iter().for_each(|pattern| {
if Pattern::new(pattern).expect("Failed to create pattern").matches(changed_file) {
hash_set_filtered_files.remove(changed_file);
}
});
});
}

filtered_files
hash_set_filtered_files
}

fn get_count(filtered_files: Vec<String>) -> usize {
fn get_count(filtered_files: HashSet<String>) -> usize {
filtered_files.len()
}

fn categorize_filters(filters: Vec<PatternFilter>) -> (Vec<PatternFilter>, Vec<PatternFilter>) {
let mut exclude_patterns_filters: Vec<PatternFilter> = Vec::new();
let mut include_patterns_filters: Vec<PatternFilter> = Vec::new();
fn categorize_filters(filters: Vec<PatternFilter>) -> (HashSet<String>, HashSet<String>) {
let mut exclude_patterns_filters: HashSet<String> = HashSet::new();
let mut include_patterns_filters: HashSet<String> = HashSet::new();

filters.iter().for_each(|pattern_filter| {
if pattern_filter.exclude {
exclude_patterns_filters.push(pattern_filter.clone());
exclude_patterns_filters.insert(pattern_filter.clone().pattern);
} else {
include_patterns_filters.push(pattern_filter.clone());
include_patterns_filters.insert(pattern_filter.clone().pattern);
}
});

Expand Down
14 changes: 8 additions & 6 deletions src/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod integration {
fn test_filter() {
let arg = "--patterns=*.rs,!*..txt";
let files = vec![
String::from("main.rs"),
String::from("src/main.rs"),
String::from("lib.rs"),
String::from("test.txt"),
];
Expand All @@ -17,14 +17,16 @@ mod integration {

let (include_patterns_filters, exclude_patterns_filters) = categorize_filters(filters);

let filtered_files = filter(files, include_patterns_filters, exclude_patterns_filters);
let filtered_files = filter_files(files, include_patterns_filters, exclude_patterns_filters);

let count = get_count(filtered_files.clone());

assert_eq!(
filtered_files,
vec![String::from("main.rs"), String::from("lib.rs")]
);
let expected_filtered_files = HashSet::from([
String::from("src/main.rs"),
String::from("lib.rs"),
]);

assert_eq!(filtered_files, expected_filtered_files);
assert_eq!(count, 2);
}
}
Loading