Add commits page with graph, diff, file browser, and checkout
New features: - Commits list with ASCII graph, hash, message, author, date - Single commit diff view with per-file diffs - File tree browser at any commit - File content viewer at any commit - Checkout entire commit (detached HEAD) - Checkout selected files from a commit New GitService methods: listCommits, getCommitDiff, listFilesAtCommit, getFileContentAtCommit, checkoutCommit, checkoutFilesFromCommit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title th:text="'File - ' + ${filePath}">File</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 th:text="${filePath}">file.txt</h2>
|
||||
|
||||
<p>
|
||||
<a th:href="@{/repo/{name}/tree/{hash}(name=${name}, hash=${hash})}">< Back to tree</a>
|
||||
|
|
||||
<a th:href="@{/repo/{name}/commits(name=${name})}">< Back to commits</a>
|
||||
</p>
|
||||
|
||||
<table border="0" cellpadding="4" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<form method="post" th:action="@{/repo/{name}/checkout-files(name=${name})}">
|
||||
<input type="hidden" name="hash" th:value="${hash}">
|
||||
<input type="hidden" name="files" th:value="${filePath}">
|
||||
<input type="submit" value="Checkout this file">
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Content</h3>
|
||||
<pre th:text="${content}">File content here</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,52 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title th:text="'Commit ' + ${hash}">Commit</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Commit <span th:text="${shortHash}"></span></h2>
|
||||
|
||||
<p><a th:href="@{/repo/{name}/commits(name=${name})}">< Back to commits</a></p>
|
||||
|
||||
<table border="0" cellpadding="4" cellspacing="0">
|
||||
<tr>
|
||||
<td>
|
||||
<form method="post" th:action="@{/repo/{name}/checkout-commit(name=${name})}">
|
||||
<input type="hidden" name="hash" th:value="${hash}">
|
||||
<input type="submit" value="Checkout this commit">
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<a th:href="@{/repo/{name}/tree/{hash}(name=${name}, hash=${hash})}">Browse files</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>Changed Files</h3>
|
||||
|
||||
<form method="post" th:action="@{/repo/{name}/checkout-files(name=${name})}">
|
||||
<input type="hidden" name="hash" th:value="${hash}">
|
||||
<table border="1" cellpadding="4" cellspacing="0">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Change</th>
|
||||
<th>File</th>
|
||||
</tr>
|
||||
<tr th:each="d : ${diffs}">
|
||||
<td><input type="checkbox" name="files" th:value="${d.newPath}"></td>
|
||||
<td th:text="${d.changeType}"></td>
|
||||
<td th:text="${d.changeType == 'DELETE' ? d.oldPath : d.newPath}"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<input type="submit" value="Checkout selected files">
|
||||
</form>
|
||||
|
||||
<h3>Diff</h3>
|
||||
<th:block th:each="d : ${diffs}">
|
||||
<h4 th:text="${d.changeType == 'DELETE' ? d.oldPath : d.newPath}"></h4>
|
||||
<pre th:text="${d.diff}"></pre>
|
||||
</th:block>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title th:text="'Commits - ' + ${name}">Commits</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Commits</h2>
|
||||
|
||||
<table border="1" cellpadding="4" cellspacing="0">
|
||||
<tr>
|
||||
<th>Graph</th>
|
||||
<th>Hash</th>
|
||||
<th>Message</th>
|
||||
<th>Author</th>
|
||||
<th>Date</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr th:each="c : ${commits}">
|
||||
<td><pre th:text="${c.graphLine}" style="margin:0"></pre></td>
|
||||
<td><a th:href="@{/repo/{name}/commit/{hash}(name=${name}, hash=${c.hash})}" th:text="${c.shortHash}"></a></td>
|
||||
<td th:text="${c.message}"></td>
|
||||
<td th:text="${c.author}"></td>
|
||||
<td th:text="${c.date}"></td>
|
||||
<td><a th:href="@{/repo/{name}/tree/{hash}(name=${name}, hash=${c.hash})}">Browse</a></td>
|
||||
<td>
|
||||
<form method="post" th:action="@{/repo/{name}/checkout-commit(name=${name})}">
|
||||
<input type="hidden" name="hash" th:value="${c.hash}">
|
||||
<input type="submit" value="Checkout">
|
||||
</form>
|
||||
</td>
|
||||
<td><a th:href="@{/repo/{name}/commit/{hash}(name=${name}, hash=${c.hash})}">Diff</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p th:if="${commits.isEmpty()}">No commits yet.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -20,6 +20,7 @@
|
||||
<hr>
|
||||
<b th:text="${selectedRepo}"></b><br>
|
||||
<a th:href="@{/repo/{name}/changes(name=${selectedRepo})}" target="content">Staging</a><br>
|
||||
<a th:href="@{/repo/{name}/commits(name=${selectedRepo})}" target="content">Commits</a><br>
|
||||
<a th:href="@{/repo/{name}/branches(name=${selectedRepo})}" target="content">Branches</a><br>
|
||||
<a th:href="@{/repo/{name}/remote(name=${selectedRepo})}" target="content">Remote</a><br>
|
||||
<a th:href="@{/repo/{name}/manage(name=${selectedRepo})}" target="content">Manage</a><br>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<title th:text="'Browse - ' + ${shortHash}">Browse</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Browse <span th:text="${shortHash}"></span></h2>
|
||||
|
||||
<p><a th:href="@{/repo/{name}/commits(name=${name})}">< Back to commits</a></p>
|
||||
|
||||
<p th:if="${!path.isEmpty()}">
|
||||
Path: <b th:text="${path}"></b>
|
||||
<br>
|
||||
<a th:href="@{/repo/{name}/tree/{hash}(name=${name}, hash=${hash}, path=${path.contains('/') ? path.substring(0, path.lastIndexOf('/')) : ''})}">< Parent directory</a>
|
||||
</p>
|
||||
|
||||
<table border="1" cellpadding="4" cellspacing="0">
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
<tr th:each="f : ${files}">
|
||||
<td th:text="${f.type}"></td>
|
||||
<td>
|
||||
<a th:if="${f.type == 'tree'}" th:href="@{/repo/{name}/tree/{hash}(name=${name}, hash=${hash}, path=${f.path})}" th:text="${f.path.contains('/') ? f.path.substring(f.path.lastIndexOf('/') + 1) : f.path}"></a>
|
||||
<a th:if="${f.type == 'blob'}" th:href="@{'/repo/' + ${name} + '/blob/' + ${hash} + '/' + ${f.path}}" th:text="${f.path.contains('/') ? f.path.substring(f.path.lastIndexOf('/') + 1) : f.path}"></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p th:if="${files.isEmpty()}">Empty directory.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user