Skip to content

Commit aa8505f

Browse files
Add support for Incrementalist to detect unstaged changes to files (#331)
* updated incrementalist internal rules * added ability to detect unstaged commits
1 parent adfb609 commit aa8505f

File tree

3 files changed

+85
-184
lines changed

3 files changed

+85
-184
lines changed

.cursor/rules/incrementalist.mdc

Lines changed: 37 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
description: Incrementalist-specific rules and guidance
33
globs:
44
---
5-
# Incrementalist Rules
5+
# Incrementalist Rules
66

77
Role Definition:
88
- Build System Expert
@@ -13,184 +13,39 @@ Role Definition:
1313
General:
1414
Description: >
1515
Incrementalist is a command-line tool for computing incremental build steps in large .NET solutions.
16-
These rules ensure consistent development practices, reliable testing, and proper documentation.
17-
18-
# Build System Documentation
19-
20-
## Purpose
21-
Ensure clear documentation for building and running Incrementalist locally.
22-
23-
## Requirements
24-
1. Build instructions in README.md must include:
25-
- Prerequisites (.NET 8.0 SDK, Git)
26-
- Installation via `dotnet tool install --global Incrementalist.Cmd`
27-
- Basic usage examples with common scenarios
28-
29-
2. Build script documentation in `/docs/build.md` must cover:
30-
- Available FAKE build targets and their purposes
31-
- Build configuration options
32-
- Code signing process for NuGet packages
33-
- CI/CD integration guidelines
34-
35-
3. All command-line options must be documented in README.md with:
36-
- Clear descriptions
37-
- Example usage
38-
- Common use cases
39-
40-
# Command Line Interface Documentation
41-
42-
## Purpose
43-
Maintain accurate documentation for Incrementalist's command-line interface.
44-
45-
## Requirements
46-
1. All CLI options must be documented in README.md:
47-
- Required vs optional arguments
48-
- Default values
49-
- Environment variable overrides
50-
51-
2. Common usage patterns must be documented:
52-
- Basic project/folder analysis
53-
- Integration with build systems
54-
- Running commands against affected projects
55-
- Parallel execution options
56-
57-
3. Exit codes must be documented:
58-
- 0: Success
59-
- -1: General error
60-
- -2: Git repository not found
61-
- -3: Repository location error
62-
- -4: Branch not found
63-
- Other specific error codes
64-
65-
# Git Integration
66-
67-
## Purpose
68-
Ensure reliable Git operations across different environments.
69-
70-
## Requirements
71-
1. Git Operations:
72-
- Support both libgit2sharp and command-line git
73-
- Handle repository edge cases (shallow clones, submodules)
74-
- Support common CI/CD platforms (GitHub Actions, Azure DevOps, etc.)
75-
76-
2. Branch Handling:
77-
- Support for remote branches (origin/branch-name)
78-
- Handle detached HEAD states
79-
- Clear error messages for missing branches
80-
81-
3. Performance:
82-
- Efficient diff computation
83-
- Caching of repository info where appropriate
84-
- Proper cleanup of Git resources
85-
86-
# Testing
87-
88-
## Purpose
89-
Maintain comprehensive test coverage for core functionality.
90-
91-
## Requirements
92-
1. Test Coverage:
93-
- Unit tests for core Git operations
94-
- Integration tests for MSBuild analysis
95-
- End-to-end tests for common scenarios
96-
- Performance benchmarks for large solutions
97-
98-
2. Test Organization:
99-
- Unit tests in *.Tests.csproj
100-
- Integration tests in build.fsx
101-
- Performance tests in *.Tests.Performance.csproj
102-
103-
3. Test Data:
104-
- Sample solutions for testing
105-
- Mock Git repositories
106-
- Various project types (C#, F#)
107-
108-
# Performance
109-
110-
## Purpose
111-
Ensure Incrementalist remains fast and efficient for large solutions.
112-
113-
## Requirements
114-
1. Solution Analysis:
115-
- Efficient project dependency graph computation
116-
- Smart caching of MSBuild data
117-
- Parallel processing where beneficial
118-
119-
2. Resource Management:
120-
- Proper disposal of MSBuild workspaces
121-
- Cleanup of temporary files
122-
- Memory usage monitoring
123-
124-
3. Benchmarks:
125-
- Track performance on large solutions
126-
- Compare parallel vs sequential execution
127-
- Monitor memory usage patterns
128-
129-
# Change Verification
130-
131-
## Purpose
132-
Ensure code changes are properly verified through compilation, unit tests, and integration tests before completion.
133-
134-
## Requirements
135-
1. After Code Changes:
136-
- Always run `dotnet build` to verify compilation
137-
- Run `dotnet test` to execute unit tests
138-
- Run integration tests via FAKE build system for changes affecting:
139-
* Git integration
140-
* Project analysis
141-
* Command execution
142-
* Solution loading
143-
144-
2. Build Verification:
145-
```bash
146-
# Basic verification (all platforms)
147-
dotnet build
148-
dotnet test
149-
150-
# Full verification including integration tests
151-
152-
# Windows (PowerShell)
153-
./build.ps1 RunTests
154-
./build.ps1 IntegrationTests
155-
156-
# Linux/macOS (Bash)
157-
./build.sh RunTests
158-
./build.sh IntegrationTests
159-
```
160-
161-
3. Test Coverage:
162-
- Unit tests must be run for all code changes
163-
- Integration tests must be run for changes affecting:
164-
* Project/folder analysis
165-
* Git operations
166-
* MSBuild integration
167-
* Command execution features
168-
169-
4. Verification Order:
170-
1. Compilation (`dotnet build`)
171-
2. Unit tests (`dotnet test`)
172-
3. Integration tests:
173-
- Windows: `./build.ps1 IntegrationTests`
174-
- Linux/macOS: `./build.sh IntegrationTests`
175-
4. Performance tests if relevant:
176-
- Windows: `./build.ps1 NBench`
177-
- Linux/macOS: `./build.sh NBench`
178-
179-
5. Error Handling:
180-
- All build errors must be addressed
181-
- Test failures must be investigated and fixed
182-
- Integration test failures must be thoroughly analyzed
183-
184-
6. CI/CD Alignment:
185-
- Local verification should match CI pipeline steps
186-
- Use same SDK version as CI environment
187-
- Run tests in Release configuration when appropriate
188-
189-
7. Full Build:
190-
```bash
191-
# Windows (PowerShell)
192-
./build.ps1 all # Runs all targets including tests and packaging
193-
194-
# Linux/macOS (Bash)
195-
./build.sh all # Runs all targets including tests and packaging
196-
```
16+
All build, test, and verification procedures are documented in /docs/building.md.
17+
Always refer to this document for the most up-to-date instructions.
18+
19+
# Build and Test Process
20+
21+
## Primary Documentation
22+
All build and test procedures are documented in `/docs/building.md`. This is the source of truth for:
23+
- Building from source
24+
- Running unit tests
25+
- Running integration tests
26+
- Creating and verifying packages
27+
- Publishing releases
28+
29+
## Verification Requirements
30+
1. Always follow the verification process in `/docs/building.md`
31+
2. For any code changes:
32+
- Follow the "Basic Verification" steps
33+
- For changes affecting core functionality, follow the "Full Verification" steps
34+
- For release preparation, follow the "Package Verification" steps
35+
36+
## Integration Testing
37+
1. Integration tests must be run using the scripts and procedures specified in `/docs/building.md`
38+
2. Follow the documented test cases and expected outputs
39+
3. Pay attention to the exit codes and test summaries
40+
41+
## Version Management
42+
Follow the version management procedures in `/docs/building.md` for:
43+
- Updating versions
44+
- Managing release notes
45+
- Package metadata
46+
47+
## Publishing
48+
Follow the publishing procedures in `/docs/building.md` for:
49+
- Creating release packages
50+
- Publishing to NuGet
51+
- Package verification

src/Incrementalist.Tests/Git/GitDiffDetectionSpecs.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,28 @@ public void Should_detect_delete_of_existing_file_in_Repo()
7272
Assert.Equal("fuber.txt", Path.GetFileName(file));
7373
}
7474

75+
[Fact(DisplayName = "Should detect unstaged changes in working directory")]
76+
public void Should_detect_unstaged_changes()
77+
{
78+
// Create and commit a file on master
79+
Repository.WriteFile("committed.txt", "committed")
80+
.Commit("Add committed file");
81+
82+
// Create a branch and add a staged file
83+
Repository.CreateBranch("foo")
84+
.CheckoutBranch("foo")
85+
.WriteFile("staged.txt", "staged");
86+
87+
// Create an unstaged file
88+
var unstagedPath = Path.Combine(Repository.BasePath, "unstaged.txt");
89+
File.WriteAllText(unstagedPath, "unstaged");
90+
91+
var diffedFiles = DiffHelper.ChangedFiles(Repository.Repository, "master").ToList();
92+
Assert.Equal(2, diffedFiles.Count);
93+
Assert.Contains(diffedFiles, f => Path.GetFileName(f) == "staged.txt");
94+
Assert.Contains(diffedFiles, f => Path.GetFileName(f) == "unstaged.txt");
95+
}
96+
7597
[Fact(DisplayName = "Should not detect any changes when none are present")]
7698
public void Should_not_detect_any_changes_when_none_present()
7799
{

src/Incrementalist/Git/DiffHelper.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,32 @@ public static class DiffHelper
1818
{
1919
public static IEnumerable<string> ChangedFiles(Repository repo, string targetBranch)
2020
{
21-
return repo.Diff.Compare<TreeChanges>(repo.Branches[targetBranch].Tip.Tree, DiffTargets.Index)
22-
.Select(x => Path.GetFullPath(Path.Combine(repo.Info.WorkingDirectory, x.Path)));
21+
var targetTree = repo.Branches[targetBranch].Tip.Tree;
22+
var changes = new HashSet<string>();
23+
24+
// Get all changes between target branch and current state (including both staged and unstaged)
25+
var status = repo.RetrieveStatus();
26+
27+
// Add staged changes
28+
foreach (var staged in status.Staged)
29+
{
30+
changes.Add(Path.GetFullPath(Path.Combine(repo.Info.WorkingDirectory, staged.FilePath)));
31+
}
32+
33+
// Add unstaged changes
34+
foreach (var unstaged in status.Modified.Concat(status.Added).Concat(status.Untracked))
35+
{
36+
changes.Add(Path.GetFullPath(Path.Combine(repo.Info.WorkingDirectory, unstaged.FilePath)));
37+
}
38+
39+
// Add changes between target branch and HEAD
40+
var branchDiff = repo.Diff.Compare<TreeChanges>(targetTree, repo.Head.Tip.Tree);
41+
foreach (var change in branchDiff)
42+
{
43+
changes.Add(Path.GetFullPath(Path.Combine(repo.Info.WorkingDirectory, change.Path)));
44+
}
45+
46+
return changes;
2347
}
2448

2549
public static bool HasBranch(Repository repo, string targetBranch)

0 commit comments

Comments
 (0)