Skip to content

Commit 9ffa321

Browse files
authored
Merge pull request #8 from akoufoudakis/CHECKOUT_DATE_REF_COMMIT
[CHECKOUT_DATE_REF_COMMIT] - Added methods to checkout from hashes, refs, and before a date
2 parents f85462f + 03164c0 commit 9ffa321

2 files changed

Lines changed: 157 additions & 15 deletions

File tree

src/main/java/edu/appstate/cs/rascalgit/RascalGit.java

Lines changed: 131 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,35 +27,23 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2727

2828
import java.io.File;
2929
import java.io.IOException;
30-
import java.util.ArrayList;
3130
import java.util.HashMap;
3231
import java.util.List;
3332

34-
import org.eclipse.jgit.api.CheckoutCommand;
33+
import io.usethesource.vallang.*;
3534
import org.eclipse.jgit.api.Git;
36-
import org.eclipse.jgit.api.errors.CheckoutConflictException;
3735
import org.eclipse.jgit.api.errors.GitAPIException;
38-
import org.eclipse.jgit.api.errors.InvalidRefNameException;
3936
import org.eclipse.jgit.api.errors.InvalidRemoteException;
40-
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
41-
import org.eclipse.jgit.api.errors.RefNotFoundException;
4237
import org.eclipse.jgit.api.errors.TransportException;
4338
import org.eclipse.jgit.lib.Constants;
39+
import org.eclipse.jgit.lib.ObjectId;
4440
import org.eclipse.jgit.lib.Ref;
4541
import org.eclipse.jgit.lib.Repository;
4642
import org.eclipse.jgit.revwalk.RevCommit;
43+
import org.eclipse.jgit.revwalk.RevSort;
4744
import org.eclipse.jgit.revwalk.RevWalk;
4845
import org.rascalmpl.exceptions.RuntimeExceptionFactory;
4946

50-
import io.usethesource.vallang.IConstructor;
51-
import io.usethesource.vallang.IDateTime;
52-
import io.usethesource.vallang.IInteger;
53-
import io.usethesource.vallang.IList;
54-
import io.usethesource.vallang.IListWriter;
55-
import io.usethesource.vallang.ISourceLocation;
56-
import io.usethesource.vallang.IString;
57-
import io.usethesource.vallang.IValueFactory;
58-
5947
public class RascalGit {
6048
private final IValueFactory values;
6149
private HashMap<ISourceLocation, Repository> repoMap = new HashMap<>();
@@ -150,5 +138,133 @@ public IDateTime getTagCommitDate(ISourceLocation loc, IString tag) {
150138
}
151139
throw RuntimeExceptionFactory.illegalArgument(loc,"Repository not open");
152140
}
141+
142+
public void checkoutByDate(ISourceLocation loc, IDateTime refDate) {
143+
if (repoMap.containsKey(loc)) {
144+
File repoDir = new File(loc.getPath());
145+
try {
146+
Git git = Git.open(repoDir);
147+
Repository repository = git.getRepository();
148+
RevCommit targetCommit = null;
149+
try (RevWalk walk = new RevWalk(repository)) {
150+
151+
RevCommit head = walk.parseCommit(repository.resolve("HEAD"));
152+
walk.markStart(head);
153+
154+
walk.sort(RevSort.COMMIT_TIME_DESC);
155+
156+
for (RevCommit commit : walk) {
157+
158+
long targetMillis = refDate.getInstant();
159+
long commitMillis = commit.getCommitTime() * 1000L;
160+
if (commitMillis <= targetMillis) {
161+
targetCommit = commit;
162+
break;
163+
}
164+
}
165+
if (targetCommit != null) {
166+
git.checkout()
167+
.setName(targetCommit.getId().getName())
168+
.call();
169+
}
170+
}
171+
} catch (GitAPIException ge) {
172+
throw RuntimeExceptionFactory.javaException(ge, null, null);
173+
} catch (IOException e) {
174+
throw RuntimeExceptionFactory.javaException(e, null, null);
175+
}
176+
}
177+
}
178+
179+
public void switchCommit(ISourceLocation loc, IString commitHash) {
180+
if (repoMap.containsKey(loc)) {
181+
Repository repo = repoMap.get(loc);
182+
File repoDir = new File(loc.getPath());
183+
String target = commitHash.getValue();
184+
try {
185+
Git git = Git.open(repoDir);
186+
ObjectId id = repo.resolve(target);
187+
if(id != null) {
188+
git.checkout().setName(target).call();
189+
} else {
190+
throw RuntimeExceptionFactory.illegalArgument(loc, "Invalid hash reference");
191+
}
192+
193+
} catch (GitAPIException ge) {
194+
throw RuntimeExceptionFactory.javaException(ge, null, null);
195+
} catch (IOException e) {
196+
throw RuntimeExceptionFactory.javaException(e, null, null);
197+
}
198+
}
199+
}
200+
201+
public void switchRef(ISourceLocation loc, IString refName) {
202+
if (repoMap.containsKey(loc)) {
203+
Repository repo = repoMap.get(loc);
204+
File repoDir = new File(loc.getPath());
205+
String target = refName.getValue();
206+
try {
207+
Git git = Git.open(repoDir);
208+
String fullRefName = Constants.R_HEADS + refName;
209+
ObjectId id = repo.resolve(fullRefName);
210+
if(id != null) {
211+
git.checkout().setName(fullRefName).setStartPoint(fullRefName).call();
212+
} else {
213+
throw RuntimeExceptionFactory.illegalArgument(loc, "Invalid ref reference");
214+
}
215+
} catch (GitAPIException ge) {
216+
throw RuntimeExceptionFactory.javaException(ge, null, null);
217+
} catch (IOException e) {
218+
throw RuntimeExceptionFactory.javaException(e, null, null);
219+
}
220+
}
221+
}
222+
223+
public IDateTime getCommitDate(ISourceLocation loc, IString commitHash) {
224+
if (repoMap.containsKey(loc)) {
225+
Repository repo = repoMap.get(loc);
226+
try {
227+
ObjectId id = repo.resolve(commitHash.getValue());
228+
if (id == null) {
229+
throw RuntimeExceptionFactory.illegalArgument(loc, "Invalid ref reference");
230+
}
231+
RevWalk revWalk = new RevWalk(repo);
232+
RevCommit commit = revWalk.parseCommit(repo.resolve(commitHash.getValue()));
233+
long instant = 1000L * commit.getCommitTime();
234+
IDateTime commitTime = values.datetime(instant);
235+
return commitTime;
236+
} catch (IOException e) {
237+
throw RuntimeExceptionFactory.javaException(e, null, null);
238+
}
239+
}
240+
throw RuntimeExceptionFactory.illegalArgument(loc,"Repository not open");
241+
}
242+
243+
public IList getCommitLog(ISourceLocation loc, IBool reverse) {
244+
if (repoMap.containsKey(loc)) {
245+
Repository repo = repoMap.get(loc);
246+
IListWriter listWriter = values.listWriter();
247+
try {
248+
RevWalk revWalk = new RevWalk(repo);
249+
RevCommit commit = revWalk.parseCommit(repo.resolve("HEAD"));
250+
revWalk.markStart(commit);
251+
if (reverse.getValue()) {
252+
revWalk.sort(RevSort.REVERSE);
253+
} else {
254+
revWalk.sort(RevSort.NONE);
255+
}
256+
for (RevCommit revCommit : revWalk) {
257+
String hash = revCommit.getId().getName();
258+
long commitMillis = revCommit.getCommitTime() * 1000L;
259+
260+
ITuple commitTuple = values.tuple(values.string(hash), values.datetime(commitMillis));
261+
listWriter.append(commitTuple);
262+
}
263+
return listWriter.done();
264+
} catch (IOException e) {
265+
throw RuntimeExceptionFactory.javaException(e, null, null);
266+
}
267+
} throw RuntimeExceptionFactory.illegalArgument(loc,"Repository not open");
268+
}
153269

154270
}

src/main/rascal/util/git/Git.rsc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,29 @@ java void switchToTag(loc repoPath, str \tag);
5757
@javaClass{edu.appstate.cs.rascalgit.RascalGit}
5858
@synopsis{`git log -1 --format=%ai myTagName`}
5959
java datetime getTagCommitDate(loc repoPath, str \tag);
60+
61+
@javaClass{edu.appstate.cs.rascalgit.RascalGit}
62+
@synopsis{`git checkout `git rev-list -n 1 --before="2023-01-01 12:00:00" HEAD``}
63+
@description{
64+
This will checkout the most recent commit before the given date.
65+
}
66+
java void checkoutByDate(loc repoPath, datetime refDate);
67+
68+
@javaClass{edu.appstate.cs.rascalgit.RascalGit}
69+
@synopsis{`git checkout myfeaturebranch`}
70+
java void switchRef(loc repoPath, str refName);
71+
72+
@javaClass{edu.appstate.cs.rascalgit.RascalGit}
73+
@synopsis{`git checkout commmithash`}
74+
java void switchCommit(loc repoPath, str commitHash);
75+
76+
@javaClass{edu.appstate.cs.rascalgit.RascalGit}
77+
@synopsis{`git show -s --format=%cI commithash`}
78+
java datetime getCommitDate(loc repoPath, str commitHash);
79+
80+
@javaClass{edu.appstate.cs.rascalgit.RascalGit}
81+
@synopsis{`git log [--reverse] --format="%H,%ct"`}
82+
@description{
83+
This will return a list of tuples of the commit hash and the commit date.
84+
}
85+
public java list[tuple[str hash, datetime date]] getCommitLog(loc repoPath, bool reverse);

0 commit comments

Comments
 (0)