Skip to content

Commit 8ea5e4b

Browse files
committed
Hide diff icon for binary files
1 parent 43b74f3 commit 8ea5e4b

File tree

7 files changed

+76
-40
lines changed

7 files changed

+76
-40
lines changed

jupyterlab_git/git.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,15 +255,36 @@ async def status(self, current_path):
255255
"message": my_error,
256256
}
257257

258+
# Add attribute `is_binary`
259+
command = [ # Compare stage to an empty tree see `_is_binary`
260+
"git",
261+
"diff",
262+
"--numstat",
263+
"-z",
264+
"--cached",
265+
"4b825dc642cb6eb9a060e54bf8d69288fbee4904"
266+
]
267+
text_code, text_output, _ = await execute(
268+
command, cwd=os.path.join(self.root_dir, current_path),
269+
)
270+
271+
are_binary = dict()
272+
if text_code == 0:
273+
for line in filter(lambda l: len(l) > 0, strip_and_split(text_output)):
274+
diff, name = line.rsplit(maxsplit=1)
275+
are_binary[name] = diff.startswith("-\t-")
276+
258277
result = []
259278
line_iterable = (line for line in strip_and_split(my_output) if line)
260279
for line in line_iterable:
280+
name = line[3:]
261281
result.append({
262282
"x": line[0],
263283
"y": line[1],
264-
"to": line[3:],
284+
"to": name,
265285
# if file was renamed, next line contains original path
266-
"from": next(line_iterable) if line[0]=='R' else line[3:]
286+
"from": next(line_iterable) if line[0]=='R' else name,
287+
"is_binary": are_binary.get(name, None)
267288
})
268289
return {"code": code, "files": result}
269290

@@ -324,6 +345,18 @@ async def detailed_log(self, selected_hash, current_path):
324345
if code != 0:
325346
return {"code": code, "command": " ".join(cmd), "message": my_error}
326347

348+
# Test for binary file
349+
command = ["git", "diff", "--numstat", "-z", "4b825dc642cb6eb9a060e54bf8d69288fbee4904", selected_hash]
350+
text_code, text_output, _ = await execute(
351+
command,
352+
cwd=os.path.join(self.root_dir, current_path),
353+
)
354+
are_binary = dict()
355+
if text_code == 0:
356+
for line in filter(lambda l: len(l) > 0, strip_and_split(text_output)):
357+
diff, name = line.rsplit(maxsplit=1)
358+
are_binary[name] = diff.startswith("-\t-")
359+
327360
total_insertions = 0
328361
total_deletions = 0
329362
result = []
@@ -339,15 +372,18 @@ async def detailed_log(self, selected_hash, current_path):
339372
to_path = next(line_iterable)
340373
modified_file_name = from_path + " => " + to_path
341374
modified_file_path = to_path
375+
is_binary = are_binary.get(to_path, None)
342376
else:
343377
modified_file_name = file.split("/")[-1]
344378
modified_file_path = file
379+
is_binary = are_binary.get(file, None)
345380

346381
result.append({
347-
"modified_file_path": modified_file_path,
348-
"modified_file_name": modified_file_name,
349-
"insertion": insertions,
350-
"deletion": deletions,
382+
"modified_file_path": modified_file_path,
383+
"modified_file_name": modified_file_name,
384+
"insertion": insertions,
385+
"deletion": deletions,
386+
"is_binary": is_binary
351387
})
352388
total_insertions += int(insertions)
353389
total_deletions += int(deletions)

src/components/FileList.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ export class FileList extends React.Component<IFileListProps, IFileListState> {
7171
currentRef: { specialRef: 'WORKING' },
7272
previousRef: { gitRef: 'HEAD' }
7373
},
74-
this.props.renderMime
74+
this.props.renderMime,
75+
!this.state.selectedFile.is_binary
7576
);
7677
}
7778
});
@@ -89,7 +90,8 @@ export class FileList extends React.Component<IFileListProps, IFileListState> {
8990
currentRef: { specialRef: 'INDEX' },
9091
previousRef: { gitRef: 'HEAD' }
9192
},
92-
this.props.renderMime
93+
this.props.renderMime,
94+
!this.state.selectedFile.is_binary
9395
);
9496
}
9597
});
@@ -342,7 +344,7 @@ export class FileList extends React.Component<IFileListProps, IFileListState> {
342344
key={file.to}
343345
actions={
344346
<React.Fragment>
345-
{this._createDiffButton(file.to, 'INDEX')}
347+
{this._createDiffButton(file, 'INDEX')}
346348
<ActionButton
347349
className={hiddenButtonStyle}
348350
iconName={'git-remove'}
@@ -405,7 +407,7 @@ export class FileList extends React.Component<IFileListProps, IFileListState> {
405407
this.discardChanges(file.to);
406408
}}
407409
/>
408-
{this._createDiffButton(file.to, 'WORKING')}
410+
{this._createDiffButton(file, 'WORKING')}
409411
<ActionButton
410412
className={hiddenButtonStyle}
411413
iconName={'git-add'}
@@ -498,11 +500,11 @@ export class FileList extends React.Component<IFileListProps, IFileListState> {
498500
this.discardChanges(file.to);
499501
}}
500502
/>
501-
{this._createDiffButton(file.to, 'WORKING')}
503+
{this._createDiffButton(file, 'WORKING')}
502504
</React.Fragment>
503505
);
504506
} else if (file.status === 'staged') {
505-
actions = this._createDiffButton(file.to, 'INDEX');
507+
actions = this._createDiffButton(file, 'INDEX');
506508
}
507509

508510
return (
@@ -526,28 +528,31 @@ export class FileList extends React.Component<IFileListProps, IFileListState> {
526528
* @param currentRef the ref to diff against the git 'HEAD' ref
527529
*/
528530
private _createDiffButton(
529-
path: string,
531+
file: Git.IStatusFile,
530532
currentRef: ISpecialRef['specialRef']
531533
): JSX.Element {
532534
return (
533-
isDiffSupported(path) && (
535+
(isDiffSupported(file.to) || !file.is_binary) && (
534536
<ActionButton
535537
className={hiddenButtonStyle}
536538
iconName={'git-diff'}
537539
title={'Diff this file'}
538540
onClick={async () => {
539541
try {
540542
await openDiffView(
541-
path,
543+
file.to,
542544
this.props.model,
543545
{
544546
previousRef: { gitRef: 'HEAD' },
545547
currentRef: { specialRef: currentRef }
546548
},
547-
this.props.renderMime
549+
this.props.renderMime,
550+
!file.is_binary
548551
);
549552
} catch (reason) {
550-
console.error(`Fail to open diff view for ${path}.\n${reason}`);
553+
console.error(
554+
`Fail to open diff view for ${file.to}.\n${reason}`
555+
);
551556
}
552557
}}
553558
/>

src/components/SinglePastCommitInfo.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ export class SinglePastCommitInfo extends React.Component<
230230
*/
231231
private _renderFile(file: Git.ICommitModifiedFile): React.ReactElement {
232232
const path = file.modified_file_path;
233-
const flg = isDiffSupported(path);
233+
const flg = isDiffSupported(path) || !file.is_binary;
234234
return (
235235
<li
236236
className={commitDetailFileClass}
@@ -330,7 +330,8 @@ export class SinglePastCommitInfo extends React.Component<
330330
gitRef: self.props.commit.commit
331331
}
332332
},
333-
self.props.renderMime
333+
self.props.renderMime,
334+
bool
334335
);
335336
} catch (err) {
336337
console.error(`Failed to open diff view for ${fpath}.\n${err}`);

src/components/diff/Diff.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
33
import * as React from 'react';
44
import { IDiffContext } from './model';
55
import { NBDiff } from './NbDiff';
6-
import { isText, PlainTextDiff } from './PlainTextDiff';
6+
import { PlainTextDiff } from './PlainTextDiff';
77

88
/**
99
* A registry which maintains mappings of file extension to diff provider components.
@@ -18,10 +18,7 @@ const DIFF_PROVIDER_REGISTRY: { [key: string]: typeof React.Component } = {
1818
* @param path the file path
1919
*/
2020
export function isDiffSupported(path: string): boolean {
21-
return (
22-
PathExt.extname(path).toLocaleLowerCase() in DIFF_PROVIDER_REGISTRY ||
23-
isText(path)
24-
);
21+
return PathExt.extname(path).toLocaleLowerCase() in DIFF_PROVIDER_REGISTRY;
2522
}
2623

2724
/** Diff component properties */
@@ -51,11 +48,14 @@ export function Diff(props: IDiffProps) {
5148
if (fileExtension in DIFF_PROVIDER_REGISTRY) {
5249
const DiffProvider = DIFF_PROVIDER_REGISTRY[fileExtension];
5350
return <DiffProvider {...props} />;
54-
} else if (isText(props.path)) {
55-
return <PlainTextDiff {...props} />;
5651
} else {
57-
console.log(`Diff is not supported for ${fileExtension} files`);
58-
return null;
52+
// Fallback to plain text diff
53+
try {
54+
return <PlainTextDiff {...props} />;
55+
} catch (error) {
56+
console.log(`Unable to render diff view for ${props.path}:\n${error}`);
57+
return null;
58+
}
5959
}
6060
}
6161

src/components/diff/DiffWidget.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@ import { GitExtension } from '../../model';
1515
* @param shell The JupyterLab shell instance
1616
* @param diffContext the context in which the diff is being requested
1717
* @param renderMime the renderMime registry instance from the
18-
* @param topRepoPath the Git repo root path.
18+
* @param isText Is the file of textual type?
1919
*/
2020
export async function openDiffView(
2121
filePath: string,
2222
model: GitExtension,
2323
diffContext: IDiffContext,
24-
renderMime: IRenderMimeRegistry
24+
renderMime: IRenderMimeRegistry,
25+
isText = false
2526
) {
26-
if (isDiffSupported(filePath)) {
27+
if (isDiffSupported(filePath) || isText) {
2728
const id = `nbdiff-${filePath}-${getRefValue(diffContext.currentRef)}`;
2829
let mainAreaItems = model.shell.widgets('main');
2930
let mainAreaItem = mainAreaItems.next();

src/components/diff/PlainTextDiff.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,3 @@ export class PlainTextDiff extends React.Component<
138138

139139
private _mergeViewRef: React.RefObject<HTMLDivElement>;
140140
}
141-
142-
/**
143-
* Checks if a given path is supported language
144-
*
145-
* @param path the path of the file
146-
*/
147-
export function isText(path: string): boolean {
148-
return Mode.findBest(path) !== undefined;
149-
}

src/tokens.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ export namespace Git {
374374
y: string;
375375
to: string;
376376
from: string;
377+
is_binary: boolean | null;
377378
}
378379

379380
/**
@@ -410,6 +411,7 @@ export namespace Git {
410411
modified_file_name: string;
411412
insertion: string;
412413
deletion: string;
414+
is_binary: boolean | null;
413415
}
414416

415417
/** Interface for GitDetailedLog request result,

0 commit comments

Comments
 (0)