@@ -99,6 +99,43 @@ class GitUtils {
9999 }
100100 }
101101
102+ /// Stashes any uncommitted changes (including untracked files)
103+ /// Returns true if changes were stashed, false if the working tree was clean.
104+ static Future <bool > stashChanges (String ? root) async {
105+ try {
106+ final result = await Process .run (
107+ 'git' ,
108+ ['stash' , 'push' , '--include-untracked' , '-m' , 'mtrust_api_guard_auto_stash' ],
109+ workingDirectory: root,
110+ );
111+ if (result.exitCode != 0 ) {
112+ throw GitException ('Failed to stash changes: ${result .stderr }' );
113+ }
114+ // "No local changes to save" means nothing was stashed
115+ return ! result.stdout.toString ().contains ('No local changes to save' );
116+ } on ProcessException catch (e) {
117+ throw GitException ('Git command not found: ${e .message }' );
118+ }
119+ }
120+
121+ /// Pops the most recent stash entry.
122+ /// Silently succeeds if there is nothing to pop.
123+ static Future <void > popStash (String ? root) async {
124+ try {
125+ final result = await Process .run (
126+ 'git' ,
127+ ['stash' , 'pop' ],
128+ workingDirectory: root,
129+ );
130+ if (result.exitCode != 0 ) {
131+ // Log but don't throw – a pop failure shouldn't crash the tool
132+ logger.err ('Warning: Failed to pop stash: ${result .stderr }' );
133+ }
134+ } on ProcessException catch (e) {
135+ throw GitException ('Git command not found: ${e .message }' );
136+ }
137+ }
138+
102139 /// Checks out a specific git ref
103140 /// Throws [GitException] if the operation fails
104141 static Future <void > checkoutRef (String ref, String ? root) async {
0 commit comments