Skip to content

Commit 02c6d9a

Browse files
navn-rfcollonval
andauthored
Git history for a selected file (#864) (#980)
* Add history context menu button in the file browser (#863) * Add --follow option to Git log command (#864) * Display Git history for selected file (#864) * Apply suggestions from code review Co-authored-by: Frédéric Collonval <[email protected]> * Add styling to selected history file item * Add selected file history for modified files * Add 'No History Found' fallback - Covers git-ignored files edge case * Apply suggestions from code review Improve readability Co-authored-by: Frédéric Collonval <[email protected]> * Fix tests for history (#864) * Add single file log test (#864) Co-authored-by: Frédéric Collonval <[email protected]>
1 parent 96bef45 commit 02c6d9a

21 files changed

+883
-176
lines changed

jupyterlab_git/git.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -432,16 +432,24 @@ async def status(self, path):
432432

433433
return data
434434

435-
async def log(self, path, history_count=10):
435+
async def log(self, path, history_count=10, follow_path=None):
436436
"""
437437
Execute git log command & return the result.
438438
"""
439+
is_single_file = follow_path != None
439440
cmd = [
440441
"git",
441442
"log",
442443
"--pretty=format:%H%n%an%n%ar%n%s",
443444
("-%d" % history_count),
444445
]
446+
if is_single_file:
447+
cmd = cmd + [
448+
"--numstat",
449+
"--follow",
450+
"--",
451+
follow_path,
452+
]
445453
code, my_output, my_error = await execute(
446454
cmd,
447455
cwd=path,
@@ -450,30 +458,28 @@ async def log(self, path, history_count=10):
450458
return {"code": code, "command": " ".join(cmd), "message": my_error}
451459

452460
result = []
461+
if is_single_file:
462+
# an extra newline get outputted when --numstat is used
463+
my_output = my_output.replace("\n\n", "\n")
453464
line_array = my_output.splitlines()
454465
i = 0
455-
PREVIOUS_COMMIT_OFFSET = 4
466+
PREVIOUS_COMMIT_OFFSET = 5 if is_single_file else 4
456467
while i < len(line_array):
468+
commit = {
469+
"commit": line_array[i],
470+
"author": line_array[i + 1],
471+
"date": line_array[i + 2],
472+
"commit_msg": line_array[i + 3],
473+
"pre_commit": "",
474+
}
475+
476+
if is_single_file:
477+
commit["is_binary"] = line_array[i + 4].startswith("-\t-\t")
478+
457479
if i + PREVIOUS_COMMIT_OFFSET < len(line_array):
458-
result.append(
459-
{
460-
"commit": line_array[i],
461-
"author": line_array[i + 1],
462-
"date": line_array[i + 2],
463-
"commit_msg": line_array[i + 3],
464-
"pre_commit": line_array[i + PREVIOUS_COMMIT_OFFSET],
465-
}
466-
)
467-
else:
468-
result.append(
469-
{
470-
"commit": line_array[i],
471-
"author": line_array[i + 1],
472-
"date": line_array[i + 2],
473-
"commit_msg": line_array[i + 3],
474-
"pre_commit": "",
475-
}
476-
)
480+
commit["pre_commit"] = line_array[i + PREVIOUS_COMMIT_OFFSET]
481+
482+
result.append(commit)
477483
i += PREVIOUS_COMMIT_OFFSET
478484
return {"code": code, "commits": result}
479485

jupyterlab_git/handlers.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ async def post(self, path: str = ""):
196196

197197
class GitLogHandler(GitHandler):
198198
"""
199-
Handler for 'git log --pretty=format:%H-%an-%ar-%s'.
199+
Handler for 'git log'.
200200
Fetches Commit SHA, Author Name, Commit Date & Commit Message.
201201
"""
202202

@@ -208,7 +208,10 @@ async def post(self, path: str = ""):
208208
"""
209209
body = self.get_json_body()
210210
history_count = body.get("history_count", 25)
211-
result = await self.git.log(self.url2localpath(path), history_count)
211+
follow_path = body.get("follow_path")
212+
result = await self.git.log(
213+
self.url2localpath(path), history_count, follow_path
214+
)
212215

213216
if result["code"] != 0:
214217
self.set_status(500)

jupyterlab_git/tests/test_handlers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ async def test_log_handler(mock_git, jp_fetch, jp_root_dir):
281281
)
282282

283283
# Then
284-
mock_git.log.assert_called_with(str(local_path), 20)
284+
mock_git.log.assert_called_with(str(local_path), 20, None)
285285

286286
assert response.code == 200
287287
payload = json.loads(response.body)
@@ -301,7 +301,7 @@ async def test_log_handler_no_history_count(mock_git, jp_fetch, jp_root_dir):
301301
)
302302

303303
# Then
304-
mock_git.log.assert_called_with(str(local_path), 25)
304+
mock_git.log.assert_called_with(str(local_path), 25, None)
305305

306306
assert response.code == 200
307307
payload = json.loads(response.body)

0 commit comments

Comments
 (0)