Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix files changed and reverting merge commits from the history panel bug #1227

Merged
merged 19 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ jobs:
python-version: ['3.7', '3.8', '3.9', '3.10']
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install node
uses: actions/setup-node@v1
with:
node-version: '14.x'
node-version: '18.x'
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
Expand Down Expand Up @@ -101,11 +101,11 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install node
uses: actions/setup-node@v1
with:
node-version: '14.x'
node-version: '18.x'
- uses: actions/download-artifact@v2
with:
name: extension
Expand Down
2 changes: 1 addition & 1 deletion binder/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies:
- python >=3.8,<3.9.0a0
- jupyterlab >=3,<4.0.0a0
# labextension build dependencies
- nodejs >=14,<15
- nodejs >=16,<17
- pip
- wheel
# additional packages for demos
Expand Down
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ tsOptions['inlineSourceMap'] = true;

const esModules = [
'.*@jupyterlab/',
'@jupyter/ydoc',
'lib0',
'y\\-protocols',
'y\\-websocket',
Expand Down
64 changes: 35 additions & 29 deletions jupyterlab_git/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,13 +567,16 @@ async def log(self, path, history_count=10, follow_path=None):

async def detailed_log(self, selected_hash, path):
"""
Execute git log -1 --numstat --oneline -z command (used to get
Execute git log -m --cc -1 --numstat --oneline -z command (used to get
insertions & deletions per file) & return the result.
"""
cmd = [
"git",
"log",
"--cc",
"-m",
"-1",
"--oneline",
"--numstat",
"--pretty=format:%b%x00",
"-z",
Expand All @@ -596,35 +599,38 @@ async def detailed_log(self, selected_hash, path):
for line in line_iterable:
is_binary = line.startswith("-\t-\t")
previous_file_path = ""
insertions, deletions, file = line.split("\t")
insertions = insertions.replace("-", "0")
deletions = deletions.replace("-", "0")

if file == "":
# file was renamed or moved, we need next two lines of output
from_path = next(line_iterable)
to_path = next(line_iterable)
previous_file_path = from_path
modified_file_name = from_path + " => " + to_path
modified_file_path = to_path
else:
modified_file_name = file.split("/")[-1]
modified_file_path = file

file_info = {
"modified_file_path": modified_file_path,
"modified_file_name": modified_file_name,
"insertion": insertions,
"deletion": deletions,
"is_binary": is_binary,
}
tokens = line.split("\t")

if len(tokens) == 3:
insertions, deletions, file = line.split("\t")
insertions = insertions.replace("-", "0")
deletions = deletions.replace("-", "0")

if file == "":
# file was renamed or moved, we need next two lines of output
from_path = next(line_iterable)
to_path = next(line_iterable)
previous_file_path = from_path
modified_file_name = from_path + " => " + to_path
modified_file_path = to_path
else:
modified_file_name = file.split("/")[-1]
modified_file_path = file

file_info = {
"modified_file_path": modified_file_path,
"modified_file_name": modified_file_name,
"insertion": insertions,
"deletion": deletions,
"is_binary": is_binary,
}

if previous_file_path:
file_info["previous_file_path"] = previous_file_path
if previous_file_path:
file_info["previous_file_path"] = previous_file_path

result.append(file_info)
total_insertions += int(insertions)
total_deletions += int(deletions)
result.append(file_info)
total_insertions += int(insertions)
total_deletions += int(deletions)

modified_file_note = "{num_files} files changed, {insertions} insertions(+), {deletions} deletions(-)".format(
num_files=len(result),
Expand Down Expand Up @@ -930,7 +936,7 @@ async def delete_commit(self, commit_id, path):
"""
Delete a specified commit from the repository.
"""
cmd = ["git", "revert", "--no-commit", commit_id]
cmd = ["git", "revert", "-m", "1", "--no-commit", commit_id]
code, _, error = await execute(cmd, cwd=path)

if code != 0:
Expand Down
2 changes: 1 addition & 1 deletion jupyterlab_git/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ async def post(self, path: str = ""):

class GitDetailedLogHandler(GitHandler):
"""
Handler for 'git log -1 --stat --numstat --oneline' command.
Handler for 'git log -m --cc -1 --stat --numstat --oneline -z' command.
Fetches file names of committed files, Number of insertions &
deletions in that commit.
"""
Expand Down
3 changes: 3 additions & 0 deletions jupyterlab_git/tests/test_detailed_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ async def test_detailed_log():
[
"git",
"log",
"--cc",
"-m",
"-1",
"--oneline",
"--numstat",
"--pretty=format:%b%x00",
"-z",
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@jupyterlab/coreutils": "^5.0.0",
"@jupyterlab/docregistry": "^3.0.0",
"@jupyterlab/filebrowser": "^3.0.0",
"@jupyterlab/galata": "^4.5.2",
"@jupyterlab/mainmenu": "^3.0.0",
"@jupyterlab/nbformat": "^3.0.0",
"@jupyterlab/rendermime": "^3.0.0",
Expand All @@ -74,6 +75,7 @@
"@material-ui/core": "^4.8.2",
"@material-ui/icons": "^4.5.1",
"@material-ui/lab": "^4.0.0-alpha.54",
"@playwright/test": "^1.32.1",
"diff-match-patch": "^1.0.4",
"nbdime": "^6.1.1",
"nbdime-jupyterlab": "^2.1.0",
Expand Down
7 changes: 5 additions & 2 deletions testutils/jest-setup-files.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
global.fetch = require('jest-fetch-mock');
globalThis.fetch = require('jest-fetch-mock');
// Use node crypto for crypto
globalThis.crypto = require('crypto');

require("enzyme").configure({
adapter: new (require('@wojtekmaj/enzyme-adapter-react-17'))
});
});
3 changes: 1 addition & 2 deletions ui-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"test": "playwright test"
},
"devDependencies": {
"@jupyterlab/galata": "^4.1.0",
"@playwright/test": "^1.17.0"
"@jupyterlab/galata": "^4.5.3"
}
}
Binary file not shown.
98 changes: 98 additions & 0 deletions ui-tests/tests/merge-commit.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { test } from '@jupyterlab/galata';
import { expect } from '@playwright/test';
import path from 'path';
import { extractFile } from './utils';

const baseRepositoryPath = 'test-repository-merge-commits.tar.gz';
test.use({ autoGoto: false });

test.describe('Merge commit tests', () => {
test.beforeEach(async ({ baseURL, page, tmpPath }) => {
await extractFile(
baseURL,
path.resolve(__dirname, 'data', baseRepositoryPath),
path.join(tmpPath, 'repository.tar.gz')
);

// URL for merge commit example repository
await page.goto(`tree/${tmpPath}/repository`);

await page.sidebar.openTab('jp-git-sessions');

await page.getByRole('tab', { name: 'History' }).click();
});

test('should correctly display num files changed, insertions, and deletions', async ({
page
}) => {
const mergeCommit = await page.getByText("Merge branch 'sort-names'");

await mergeCommit.click();

const filesChanged = await mergeCommit.getByTitle('# Files Changed');
const insertions = await mergeCommit.getByTitle('# Insertions');
const deletions = await mergeCommit.getByTitle('# Deletions');

await filesChanged.waitFor();

await expect(await filesChanged.innerText()).toBe('3');
await expect(await insertions.innerText()).toBe('18240');
await expect(await deletions.innerText()).toBe('18239');
});

test('should correctly display files changed', async ({ page }) => {
const mergeCommit = await page.getByText("Merge branch 'sort-names'");

await mergeCommit.click();

const helloWorldFile = page.getByRole('listitem', {
name: 'hello-world.py'
});
const namesFile = page.getByRole('listitem', { name: 'names.txt' });
const newFile = page.getByRole('listitem', { name: 'new-file.txt' });

expect(helloWorldFile).toBeTruthy();
expect(namesFile).toBeTruthy();
expect(newFile).toBeTruthy();
});

test('should diff file after clicking', async ({ page }) => {
const mergeCommit = await page.getByText("Merge branch 'sort-names'");

await mergeCommit.click();

const file = page.getByRole('listitem', { name: 'hello-world.py' });
await file.click();

await page
.getByRole('tab', { name: 'hello-world.py' })
.waitFor({ state: 'visible' });

expect(page.waitForSelector('.jp-git-diff-root')).toBeTruthy();
});

test('should revert merge commit', async ({ page }) => {
const mergeCommit = await page.getByText("Merge branch 'sort-names'");

await mergeCommit.click();
await page
.getByRole('button', { name: 'Revert changes introduced by this commit' })
.click();

const dialog = await page.getByRole('dialog');
await dialog.waitFor({ state: 'visible' });

await expect(dialog).toBeTruthy();

await dialog.getByRole('button', { name: 'Submit' }).click();
await dialog.waitFor({ state: 'detached' });

const revertMergeCommit = await page
.locator('#jp-git-sessions')
.getByText("Revert 'Merge branch 'sort-names''");

await revertMergeCommit.waitFor({ state: 'visible' });

expect(revertMergeCommit).toBeTruthy();
});
});
Loading