Skip to content

Commit 69c0db1

Browse files
committed
[feature] Search for hash in the repository.
1 parent 13208ab commit 69c0db1

File tree

6 files changed

+175
-17
lines changed

6 files changed

+175
-17
lines changed

TODO.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@
55
. Handle passwords for pushing
66
. Create a modal showing quick actions/shortcuts like pull, commit, push, fetch, simple rebase, squash, etc.
77
. Checkout remote branch // git checkout -B "master" "origin/master"
8+
. Checkout commit
89
. Select multiple files while staging, unstaging, rebase modal, etc.
910
. Prevent CSRF attacks.
1011
. Handle CRLF errors.
1112
. Implement searching for commits/hashes/authors/commit messages
12-
. Implelemt copy path for all paths (file-selector)
13+
. Implement copy path for all paths (file-selector)
1314
. Modularize file selectors
1415
. Git bisect
1516
. In the push modal, show which commits/files that are gonna be pushed.
1617
. Show popover on the commit, push buttons about details on the numbers.
1718
. Refactor code.
1819
. Use angular-ui
20+
. Make common components
1921
. Move service into different file
2022
. Move modals into their own files
2123
. Convert all get requests to post

modules/git_functions.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,17 @@ let git = {
3636
removeFile,
3737
mergeIntoCurrent,
3838
abortMerge,
39-
testGit
39+
testGit,
40+
searchForHash
4041
};
4142

43+
function searchForHash({req, res, repo}) {
44+
return logRepo({req, res, repo, options: {
45+
searchFor: 'hash',
46+
searchTerm: req.body.hash
47+
}});
48+
}
49+
4250
function testGit({req, res}) {
4351
const child = spawnGitProcess();
4452
redirectIO(child, req, res);
@@ -540,7 +548,7 @@ function logRepo3({repo, req, res}) {
540548
redirectIO(child, req, res);
541549
}
542550

543-
function logRepo(repo, req, res) {
551+
function logRepo({req, res, repo, options}) {
544552
/*
545553
C:\E\projects\webgit-server\git-checkouts\d3>git log --all --graph --decorate --pretty=oneline --abbrev-commit
546554
*/
@@ -560,15 +568,32 @@ git log -n 100 --format=format:'<commit><hash>%H</hash><author_name>%an</author_
560568
log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
561569
562570
*/
563-
571+
let term = null;
572+
if(options) {
573+
switch(options.searchFor) {
574+
case 'hash': {
575+
term = {}
576+
break;
577+
}
578+
}
579+
}
564580
let randomSeperator = utils.getRandomSeparator();
565581
// let logFormat = `--format=format:%H${randomSeperator}%an${randomSeperator}%ae${randomSeperator}%aD${randomSeperator}%s${randomSeperator}%P`;
566582

567583
let logFormat = `--format=format:%d%n%H%n%an%n%ae%n%aD%n%P%n%s%n${randomSeperator}`;
568584

569-
let logArgs = ['log', '-n 100', logFormat, '--branches', '--tags'];
585+
let logArgs = ['log', logFormat];
586+
587+
if(options) {
588+
if(options.searchFor == 'hash') {
589+
logArgs.push('-1', options.searchTerm);
590+
}
591+
}
592+
else {
593+
logArgs.push('-n 100', '--branches', '--tags');
594+
}
570595

571-
let page = req.query.page || 1;
596+
let page = req.query && req.query.page ? req.query.page : 1;
572597

573598
if(page > 1) {
574599
logArgs.push('--skip=' + ((page - 1) * 100));

public/js/app/webgit-home/repo-detail/repo-detail.component.js

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
var $responseModal = $('#response-modal');
1212
var $responseModalTitle = $responseModal.find('#response-title');
1313
var $responseModalBody = $responseModal.find('#response-body');
14-
var $logRowsContainer = null;
1514
var $conflictModal = null;
1615

1716
var $sce = null;
@@ -40,8 +39,6 @@
4039
var $mainLogContainer = $('#main-log-container');
4140
var $mainLogLoadingIndicator = $('#main-log-loading-indicator');
4241

43-
$logRowsContainer = $('#log-rows-container');
44-
4542
$commitModal = $('#commit-modal');
4643
$pullModal = $('#pull-modal');
4744
$pushModal = $('#push-modal');
@@ -90,6 +87,7 @@
9087
vm.continueMerge = continueMerge;
9188
vm.abortMerge = abortMerge;
9289
vm.mergeConflictCommitMessage = '';
90+
vm.mainSearch = mainSearch;
9391

9492
vm.commitMessage = '';
9593
vm.remote = null;
@@ -113,6 +111,10 @@
113111

114112
vm.diffOnConflictModal = null;
115113

114+
var commitsBackup = null;
115+
var commitMapBackup = null;
116+
var graphBackup = null;
117+
116118
$scope.$on('windowfocus', function() {
117119
if(($commitModal.data('bs.modal') || {})._isShown) {
118120
// do not refresh when the modal window is open. use the refresh button instead.
@@ -140,6 +142,79 @@
140142

141143
return;
142144

145+
function mainSearch() {
146+
console.log(vm.mainSearchInp);
147+
148+
var searchText = vm.mainSearchInp;
149+
150+
if(typeof searchText == 'undefined' || searchText.length == 0 || (searchText = searchText.trim()).length == 0) {
151+
restoreCommits();
152+
return;
153+
}
154+
155+
var shaRegex = /\b[0-9a-f]{5,40}\b/;
156+
157+
if(shaRegex.test(searchText)) {
158+
// it is probably an SHA.
159+
repoDetailService.searchForHash(searchText).then(function(commits) {
160+
vm.commitDetails = null;
161+
parseCommits(commits);
162+
vm.commits = commits;
163+
resetCommitMap();
164+
if(commits.length > 0) {
165+
$timeout(loadGraph);
166+
}
167+
return vm.commits;
168+
});
169+
}
170+
}
171+
172+
/**
173+
* Stores commits in `commitsBackup` and `commitMapBackup`. Restore using `restoreCommits`
174+
*/
175+
function backupCommits() {
176+
commitsBackup = vm.commits;
177+
commitMapBackup = vm.commitMap;
178+
}
179+
180+
/**
181+
* Restores commits backed up using `backupCommits`
182+
*/
183+
function restoreCommits() {
184+
vm.commits = commitsBackup;
185+
vm.commitMap = commitMapBackup;
186+
$timeout(restoreGraph);
187+
}
188+
189+
function backupGraph() {
190+
var canvas = document.getElementById('log-graph');
191+
192+
graphBackup = null;
193+
graphBackup = new Image();
194+
graphBackup.src = canvas.toDataURL("image/png");
195+
// graphBackup = document.createElement('canvas');
196+
// graphBackup.width = canvas.width;
197+
// graphBackup.height = canvas.height;
198+
199+
//var graphBackupCtx = graphBackup.getContext('2D');
200+
//graphBackupCtx.drawImage(canvas, 0, 0);
201+
}
202+
203+
function restoreGraph() {
204+
// $('#graph-container').append('<canvas id="log-graph"></canvas>');
205+
var canvas = document.getElementById('log-graph');
206+
canvas.width = graphBackup.width;
207+
canvas.height = graphBackup.height;
208+
209+
var varWidth = canvas.width.toString() + 'px';
210+
var ctx = canvas.getContext('2d');
211+
212+
$('#graph-container').css('flex', '0 0 ' + varWidth);
213+
$('#log-rows-container').css('width', 'calc(100% - '+ varWidth +')');
214+
215+
ctx.drawImage(graphBackup, 0, 0);
216+
}
217+
143218
function abortMerge() {
144219
return repoDetailService.abortMerge().then(function(d) {
145220
if(!d.errorCode) {
@@ -382,10 +457,15 @@
382457
function loadGraph() {
383458
setGraphInfo();
384459
var $graphContainer = $('#graph-container');
460+
var $logRowsContainer = $('#log-rows-container');
385461
var varWidth = (((vm.maxX + 1) * logGraphDefaults.distanceBetweenBranches) + logGraphDefaults.distanceBetweenBranches).toString() + 'px';
386462
$graphContainer.css('flex', '0 0 ' + varWidth);
387463
$logRowsContainer.css('width', 'calc(100% - '+ varWidth +')');
388-
$graphContainer.empty().append('<canvas id="log-graph" height="'+ $graphContainer.height() +'" width="'+ $graphContainer.width() +'"></canvas>');
464+
// $graphContainer.empty().append('<canvas id="log-graph" height="'+ $graphContainer.height() +'" width="'+ $graphContainer.width() +'"></canvas>');
465+
var $canvas = $('#log-graph').attr({
466+
width: $graphContainer.width(),
467+
height: $graphContainer.height()
468+
});
389469

390470
var graph = document.getElementById('log-graph');
391471
var ctx = graph.getContext("2d");
@@ -785,7 +865,9 @@
785865
noMoreCommits = true;
786866
}
787867
else {
788-
$timeout(loadGraph);
868+
$timeout(loadGraph).then(function() {
869+
backupGraph();
870+
});
789871
}
790872
});
791873
}
@@ -804,7 +886,10 @@
804886
parseCommits(commits);
805887
vm.commits = commits;
806888
resetCommitMap();
807-
$timeout(loadGraph);
889+
backupCommits();
890+
$timeout(loadGraph).then(function() {
891+
backupGraph();
892+
});
808893
return vm.commits;
809894
});
810895
}
@@ -822,6 +907,9 @@
822907
Array.prototype.push.apply(vm.commits, commits);
823908

824909
resetCommitMap();
910+
911+
backupCommits();
912+
825913
return vm.commits;
826914
});
827915
}
@@ -894,6 +982,11 @@
894982

895983
function setGraphInfo() {
896984
var commits = vm.commits;
985+
986+
if(commits.length == 0) {
987+
return;
988+
}
989+
897990
var openBranches = [];
898991
var branchLevel = 0;
899992

@@ -1213,9 +1306,16 @@
12131306
this.skipRebase = skipRebase;
12141307
this.mergeIntoCurrent = mergeIntoCurrent;
12151308
this.abortMerge = abortMerge;
1309+
this.searchForHash = searchForHash;
12161310

12171311
return;
12181312

1313+
function searchForHash(hash) {
1314+
return $http.post('/repo/' + repoName + '/searchforhash', {hash: hash}).then(function(res) {
1315+
return res.data;
1316+
});
1317+
}
1318+
12191319
function abortMerge() {
12201320
return $http.post('/repo/' + repoName + '/abortmerge').then(function(res) {
12211321
return res.data;

public/js/app/webgit-home/repo-detail/repo-detail.css

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,6 @@
166166
}
167167

168168
.diff-files-list .list-item-selector, .stash-files-list .list-item-selector, .unstaged-files-list .list-item-selector, .staged-files-list .list-item-selector {
169-
display: inline-block;
170169
white-space: nowrap;
171170
}
172171

@@ -397,4 +396,17 @@
397396
.label-heading {
398397
font-weight: bold;
399398
font-size: 25px;
399+
}
400+
401+
#log-rows-container {
402+
background: #fff;
403+
}
404+
405+
.no-commits-msg {
406+
height: calc(100% - 37px);
407+
background: #fff;
408+
display: flex;
409+
flex-direction: column;
410+
justify-content: center;
411+
align-items: center;
400412
}

public/js/app/webgit-home/repo-detail/repo-detail.html

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,27 @@
77
<button class="btn btn-secondary" title="Open Push Dialog" ng-click="vm.showPushDialog()"><i class="fa fa-arrow-up" aria-hidden="true"></i> Push...</button>
88
<button class="btn btn-secondary" title="Open Stash Dialog" ng-click="vm.showStashDialog()"><i class="fa fa-database"></i> Stash...</button>
99

10+
<div id="log-search-container" class="pull-right">
11+
<div class="input-group">
12+
<div class="input-group-prepend">
13+
<div class="input-group-text"><i class="fa fa-search" aria-hidden="true"></i></div>
14+
</div>
15+
<input type="text" class="form-control" id="main-search-inp" ng-model-options='{ debounce: 800 }' ng-model="vm.mainSearchInp" ng-change="vm.mainSearch()" placeholder="Search anything">
16+
</div>
17+
</div>
1018
<button class="btn btn-danger pull-right" ng-show="vm.progress" ng-click="vm.showModalToHandleConflict()">{{ vm.progress.message }}</button>
1119
</div>
1220
<div id="main-log-context-menu" style="display: none;"></div>
1321
<div id="main-log-container" class="commit-container container-fluid" ng-class="{'details-visible': vm.commitDetails}" data-page-num="1">
1422
<div class="row">
1523
<div class="col-12">
16-
<span class="label-heading">Repository log</span> <span class="label-caption"> - Select a commit to view details.</span>
24+
<span class="label-heading">Repository log</span> <span class="label-caption"> - Select a commit to view details or right click on a commit for more.</span>
1725
</div>
1826
</div>
19-
<div class="row">
20-
<div id="graph-container" class="col"></div>
27+
<div class="row" ng-if="vm.commits.length > 0">
28+
<div id="graph-container" class="col">
29+
<canvas id="log-graph" width="1" height="1"></canvas>
30+
</div>
2131
<div class="col" id="log-rows-container">
2232
<div class="row commit list-item-selector" id="{{commit.hash}}" ng-repeat="commit in vm.commits | filter:{ isTemp:'!true'}" ng-click="vm.selectCommit(commit)" ng-class="{'selected': vm.selectedCommit === commit.hash}" data-commit-hash="{{commit.hash}}">
2333
<div class="col-sm-7 log-commit-message-container">
@@ -39,6 +49,9 @@
3949
<div id="main-log-loading-indicator">Loading next batch of commits...</div>
4050
</div>
4151
</div>
52+
<div class="no-commits-msg" ng-if="vm.commits.length == 0">
53+
There's no commits here
54+
</div>
4255
</div>
4356
<div class="details-container" ng-show="vm.commitDetails">
4457
<ul class="nav nav-tabs details-tabs" role="tablist">

routes/repo.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ router.get('/:id', function(req, res) {
2323
router.get('/:id/getrepolog', function(req, res) {
2424
// get all commits in that repo.
2525
let repo = req.params.id;
26-
git.logRepo(repo, req, res);
26+
git.logRepo({req, res, repo});
2727
});
2828

2929
router.get('/:id/getcommit/:commitHash', function(req, res) {
@@ -211,4 +211,10 @@ router.post('/:id/abortmerge', (req, res) => {
211211
git.abortMerge({repo, req, res});
212212
});
213213

214+
router.post('/:id/searchforhash', (req, res) => {
215+
let repo = req.params.id;
216+
217+
git.searchForHash({repo, req, res});
218+
});
219+
214220
module.exports = router;

0 commit comments

Comments
 (0)