Skip to content

Commit afbd776

Browse files
authored
Merge pull request #28 from LuisLiraC/feat/refactor-filters
Feat/refactor filters
2 parents 7b1c1f3 + a132728 commit afbd776

File tree

8 files changed

+185
-114
lines changed

8 files changed

+185
-114
lines changed

.github/workflows/prerelease.yaml

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Create Pre Release Binary
2+
3+
on:
4+
pull_request:
5+
types: [labeled]
6+
7+
jobs:
8+
build-artifacts:
9+
if: github.event.label.name == 'prerelease'
10+
runs-on: ubuntu-latest
11+
name: Build Artifacts
12+
env:
13+
binary_name: git-diff
14+
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Cache cargo registry
19+
uses: actions/cache@v4
20+
with:
21+
path: ~/.cargo/registry
22+
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
23+
restore-keys: |
24+
${{ runner.os }}-cargo-registry-
25+
26+
- name: Cache cargo index
27+
uses: actions/cache@v4
28+
with:
29+
path: ~/.cargo/git
30+
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
31+
restore-keys: |
32+
${{ runner.os }}-cargo-index-
33+
34+
- name: Cache cargo build
35+
uses: actions/cache@v4
36+
with:
37+
path: target
38+
key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
39+
restore-keys: |
40+
${{ runner.os }}-cargo-build-
41+
42+
- name: Build
43+
run: cargo build --release
44+
45+
- name: Create Archive Folder
46+
run: mkdir ${{ runner.os }}
47+
48+
- name: Copy Artifact
49+
run: cp target/release/${{ env.binary_name }} ${{ runner.os }}
50+
51+
- name: Create Tar Archive
52+
run: tar -czf ${{ runner.os }}.tgz ${{ runner.os }}
53+
54+
- name: Store Archive
55+
uses: actions/upload-artifact@v4
56+
with:
57+
name: ${{ runner.os }}
58+
path: ${{ runner.os }}.tgz
59+
60+
create-pre-release:
61+
needs: [build-artifacts]
62+
runs-on: ubuntu-latest
63+
name: Create Pre-release
64+
permissions:
65+
contents: write
66+
steps:
67+
- uses: actions/checkout@v4
68+
- uses: actions/download-artifact@v4
69+
- name: Get version
70+
id: get_version
71+
run: |
72+
VERSION=$(cat version | tr -d '\n')
73+
echo "Version: $VERSION"
74+
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
75+
- name: Create Release
76+
uses: ncipollo/release-action@v1
77+
with:
78+
artifacts: "Linux/Linux.tgz"
79+
tag: ${{ steps.get_version.outputs.VERSION }}-prerelease
80+
allowUpdates: true
81+
makeLatest: false
82+
prerelease: true
83+
commit: ${{ github.sha }}

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "git-diff"
3-
version = "0.1.0"
3+
version = "1.0.2"
44
edition = "2021"
55

66
[dependencies]

action.yaml

+2-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ runs:
2020
- name: Get Binary
2121
shell: bash
2222
run: |
23-
BIN_URL=$(curl https://api.github.com/repos/LuisLiraC/git-diff/releases/tags/v1.0.1 | jq -r '.assets[0].browser_download_url')
23+
BIN_URL=$(curl https://api.github.com/repos/LuisLiraC/git-diff/releases/tags/v1.0.2 | jq -r '.assets[0].browser_download_url')
2424
curl -s -L $BIN_URL -o rust-binary.tgz
2525
tar -xzvf rust-binary.tgz
2626
mv ./Linux/git-diff ./git-diff
@@ -29,8 +29,4 @@ runs:
2929
id: get-git-diff
3030
shell: bash
3131
run: |
32-
PATTERNS="${{ inputs.patterns }}"
33-
COMMA_SEPARATED_PATTERNS=$(echo "$PATTERNS" | tr '\n' ',' | sed -e 's/,$//' | sed 's/,$//' | sed 's/ //g')
34-
echo "Files patterns: $COMMA_SEPARATED_PATTERNS"
35-
36-
./git-diff --patterns=$COMMA_SEPARATED_PATTERNS
32+
./git-diff --patterns='${{ inputs.patterns }}'

src/main.rs

+38-33
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use git2::Repository;
2+
use std::collections::HashSet;
23
use std::env;
34
use glob::Pattern;
45
use std::process::Command;
56
use std::time::Instant;
67

7-
#[derive(Clone)]
8+
#[derive(Clone, Debug)]
89
struct PatternFilter {
910
pattern: String,
1011
exclude: bool,
@@ -32,13 +33,18 @@ fn main() {
3233
let duration = start.elapsed();
3334
println!("Getting changed files done in: {:?}", duration);
3435

36+
println!("Changed files: {:?}", changed_files);
37+
3538
let start = Instant::now();
36-
let filtered_files = filter(changed_files, include_patterns_filters, exclude_patterns_filters);
39+
let filtered_files = filter_files(changed_files, include_patterns_filters, exclude_patterns_filters);
3740
let duration = start.elapsed();
3841
println!("Filtering files done in: {:?}", duration);
3942

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

45+
println!("Filtered files: {:?}", filtered_files);
46+
println!("Count: {}", count);
47+
4248
Command::new("sh")
4349
.arg("-c")
4450
.arg(format!("echo \"DIFF_FILES={:?}\" >> $GITHUB_OUTPUT", filtered_files))
@@ -53,10 +59,18 @@ fn main() {
5359
}
5460

5561
fn create_patterns_filters(arg: &str) -> Vec<PatternFilter> {
56-
let patterns = arg
62+
let binding = arg
5763
.split('=')
5864
.last()
5965
.expect("Failed to get patterns")
66+
.replace(" ", "")
67+
.replace("\n", ",")
68+
.replace("\r", "")
69+
.replace(",,", ",")
70+
.trim_end_matches(',')
71+
.to_string();
72+
73+
let patterns = binding
6074
.split(',')
6175
.collect::<Vec<&str>>();
6276

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

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

90105
Command::new("sh")
@@ -119,49 +134,39 @@ fn get_changed_files() -> Vec<String> {
119134
changed_files
120135
}
121136

122-
fn filter(changed_files: Vec<String>, include_patterns_filters: Vec<PatternFilter>, exclude_patterns_filters: Vec<PatternFilter>) -> Vec<String> {
123-
let filtered_files: Vec<String> = include_patterns_filters
124-
.iter()
125-
.flat_map(|pattern| filter_files_by_pattern(pattern, &changed_files, &exclude_patterns_filters))
126-
.collect();
137+
fn filter_files(changed_files: Vec<String>, include_patterns_filters: HashSet<String>, exclude_patterns_filters: HashSet<String>) -> HashSet<String> {
138+
let mut hash_set_filtered_files = HashSet::new();
127139

128-
filtered_files
129-
}
140+
for changed_file in changed_files.iter() {
141+
include_patterns_filters.iter().for_each(|pattern| {
142+
if Pattern::new(pattern).expect("Failed to create pattern").matches(changed_file) {
143+
hash_set_filtered_files.insert(changed_file.to_string());
144+
}
130145

131-
fn filter_files_by_pattern(pattern_filter: &PatternFilter, files: &Vec<String>, exclude_patterns: &Vec<PatternFilter>) -> Vec<String> {
132-
let pattern = Pattern::new(&pattern_filter.pattern).expect("Failed to create pattern");
133-
134-
let mut filtered_files: Vec<String> = files
135-
.iter()
136-
.filter(|file| pattern.matches(file))
137-
.filter(|_| pattern_filter.exclude == false)
138-
.map(|file| file.to_string())
139-
.collect();
140-
141-
for exclude_pattern in exclude_patterns.iter() {
142-
filtered_files = filtered_files
143-
.iter()
144-
.filter(|file| !Pattern::new(&exclude_pattern.pattern).expect("Failed to create pattern").matches(file))
145-
.map(|file| file.to_string())
146-
.collect();
146+
exclude_patterns_filters.iter().for_each(|pattern| {
147+
if Pattern::new(pattern).expect("Failed to create pattern").matches(changed_file) {
148+
hash_set_filtered_files.remove(changed_file);
149+
}
150+
});
151+
});
147152
}
148153

149-
filtered_files
154+
hash_set_filtered_files
150155
}
151156

152-
fn get_count(filtered_files: Vec<String>) -> usize {
157+
fn get_count(filtered_files: HashSet<String>) -> usize {
153158
filtered_files.len()
154159
}
155160

156-
fn categorize_filters(filters: Vec<PatternFilter>) -> (Vec<PatternFilter>, Vec<PatternFilter>) {
157-
let mut exclude_patterns_filters: Vec<PatternFilter> = Vec::new();
158-
let mut include_patterns_filters: Vec<PatternFilter> = Vec::new();
161+
fn categorize_filters(filters: Vec<PatternFilter>) -> (HashSet<String>, HashSet<String>) {
162+
let mut exclude_patterns_filters: HashSet<String> = HashSet::new();
163+
let mut include_patterns_filters: HashSet<String> = HashSet::new();
159164

160165
filters.iter().for_each(|pattern_filter| {
161166
if pattern_filter.exclude {
162-
exclude_patterns_filters.push(pattern_filter.clone());
167+
exclude_patterns_filters.insert(pattern_filter.clone().pattern);
163168
} else {
164-
include_patterns_filters.push(pattern_filter.clone());
169+
include_patterns_filters.insert(pattern_filter.clone().pattern);
165170
}
166171
});
167172

src/tests/integration.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ mod integration {
88
fn test_filter() {
99
let arg = "--patterns=*.rs,!*..txt";
1010
let files = vec![
11-
String::from("main.rs"),
11+
String::from("src/main.rs"),
1212
String::from("lib.rs"),
1313
String::from("test.txt"),
1414
];
@@ -17,14 +17,16 @@ mod integration {
1717

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

20-
let filtered_files = filter(files, include_patterns_filters, exclude_patterns_filters);
20+
let filtered_files = filter_files(files, include_patterns_filters, exclude_patterns_filters);
2121

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

24-
assert_eq!(
25-
filtered_files,
26-
vec![String::from("main.rs"), String::from("lib.rs")]
27-
);
24+
let expected_filtered_files = HashSet::from([
25+
String::from("src/main.rs"),
26+
String::from("lib.rs"),
27+
]);
28+
29+
assert_eq!(filtered_files, expected_filtered_files);
2830
assert_eq!(count, 2);
2931
}
3032
}

0 commit comments

Comments
 (0)