Skip to content

Commit 5404175

Browse files
bobfloatsroot
authored and
root
committed
Fixed bugs
Handle merge conflicts better
1 parent b6a70db commit 5404175

File tree

15 files changed

+889
-394
lines changed

15 files changed

+889
-394
lines changed

composer.lock

Lines changed: 233 additions & 223 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/VersionControl/GitCommandBundle/GitCommands/Command/GitDiffCommand.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,16 @@ public function getPreviousCommitHash($commitHash = 'HEAD', $fileName = false)
123123

124124
return $previousCommitHash;
125125
}
126+
127+
/**
128+
* Get array of conflict file names
129+
* @return array of conflict file names
130+
*/
131+
public function getConflictFileNames(){
132+
133+
$command = " git diff --name-only --diff-filter=U";
134+
$response = $this->command->runCommand($command);
135+
return$this->splitOnNewLine($response);
136+
}
126137

127138
}

src/VersionControl/GitCommandBundle/GitCommands/Command/GitUndoCommand.php

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,86 @@ public function checkoutCommit($commitHash = 'HEAD')
6767
*
6868
* @return string
6969
*/
70-
public function checkoutFile($file, $commitHash = 'HEAD')
70+
public function checkoutFile($file, $commitHash = 'HEAD', $triggerGitAlterFilesEvent = true)
7171
{
7272
$response = $this->command->runCommand(sprintf('git checkout %s %s', escapeshellarg($commitHash), escapeshellarg($file)));
7373

74+
//Trigger file alter Event
75+
if($triggerGitAlterFilesEvent === true){
76+
$this->triggerGitAlterFilesEvent();
77+
}
78+
79+
return $response;
80+
}
81+
82+
/**
83+
* Check out a file from merge
84+
*
85+
* @param string $file
86+
*
87+
* @return string
88+
*/
89+
public function checkoutTheirFile($file)
90+
{
91+
$this->command->runCommand(sprintf('git checkout --theirs %s', escapeshellarg($file)));
92+
$this->command->runCommand(sprintf('git add %s', escapeshellarg($file)));
93+
$response = 'Using their merged in file for "'.$file.'"';
94+
95+
//Trigger file alter Event
96+
$this->triggerGitAlterFilesEvent();
97+
98+
return $response;
99+
}
100+
101+
/**
102+
* Check out a file from merge conflict
103+
*
104+
* @param string $file
105+
*
106+
* @return string
107+
*/
108+
public function checkoutOurFile($file)
109+
{
110+
$this->command->runCommand(sprintf('git checkout --ours %s', escapeshellarg($file)));
111+
$this->command->runCommand(sprintf('git add %s', escapeshellarg($file)));
112+
$response = 'Using original file from current branch for "'.$file.'"';
113+
114+
//Trigger file alter Event
115+
$this->triggerGitAlterFilesEvent();
116+
117+
return $response;
118+
}
119+
120+
/**
121+
* Check out a file from merge conflict
122+
*
123+
* @param string $file
124+
*
125+
* @return string
126+
*/
127+
public function addFile($file)
128+
{
129+
$this->command->runCommand(sprintf('git add %s', escapeshellarg($file)));
130+
$response = 'Manually fixed file "'.$file.'"';
131+
132+
//Trigger file alter Event
133+
$this->triggerGitAlterFilesEvent();
134+
135+
return $response;
136+
}
137+
138+
/**
139+
* Check out a file from merge conflict
140+
*
141+
* @param string $file
142+
*
143+
* @return string
144+
*/
145+
public function deleteFile($file)
146+
{
147+
$this->command->runCommand(sprintf('git rm %s', escapeshellarg($file)));
148+
$response = 'Delete file "'.$file.'"';
149+
74150
//Trigger file alter Event
75151
$this->triggerGitAlterFilesEvent();
76152

src/VersionControl/GitControlBundle/Controller/ProjectCommitController.php

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ class ProjectCommitController extends BaseProjectController
7272
public function listAction($id)
7373
{
7474
$files = $this->gitCommitCommand->getFilesToCommit();
75+
76+
//Get merge conflicts
77+
$conflictFileNames = $this->gitCommands->command('diff')->getConflictFileNames();
78+
79+
$files = $this->filterConflicts($files,$conflictFileNames);
7580

7681
$commitEntity = new Commit();
7782
$commitEntity->setProject($this->project);
@@ -86,6 +91,7 @@ public function listAction($id)
8691

8792
return array_merge($this->viewVariables, array(
8893
'files' => $files,
94+
'conflictFileNames' => $conflictFileNames,
8995
'commit_form' => $commitForm->createView(),
9096
'issueCount' => $this->issuesCount,
9197
));
@@ -102,6 +108,10 @@ public function listAction($id)
102108
public function commitAction(Request $request)
103109
{
104110
$files = $this->gitCommitCommand->getFilesToCommit();
111+
112+
//Get merge conflicts
113+
$conflictFileNames = $this->gitCommands->command('diff')->getConflictFileNames();
114+
$files = $this->filterConflicts($files,$conflictFileNames);
105115

106116
$commitEntity = new Commit();
107117
$commitEntity->setProject($this->project);
@@ -156,6 +166,7 @@ public function commitAction(Request $request)
156166

157167
return array_merge($this->viewVariables, array(
158168
'files' => $files,
169+
'conflictFileNames' => $conflictFileNames,
159170
'commit_form' => $commitForm->createView(),
160171
'issueCount' => $this->issuesCount,
161172
));
@@ -288,9 +299,45 @@ public function fileDiffAction($id, $difffile)
288299
'diffs' => $gitDiffs,
289300
));
290301
}
302+
303+
/**
304+
* Filter conflicted files. Following is list of conflicted states
305+
* -------------------------------------------------
306+
* D D unmerged, both deleted
307+
* A U unmerged, added by us
308+
* U D unmerged, deleted by them
309+
* U A unmerged, added by them
310+
* D U unmerged, deleted by us
311+
* A A unmerged, both added
312+
* U U unmerged, both modified
313+
* -------------------------------------------------
314+
*
315+
* @param array $files
316+
* @param array $conflictedFiles
317+
* @return type
318+
*/
319+
public function filterConflicts($files,$conflictedFiles){
320+
321+
//Get merge conflicts
322+
$conflictFileNames = $this->gitCommands->command('diff')->getConflictFileNames();
323+
if(count($conflictFileNames) > 0){
324+
$conflictedFiles = array();
325+
foreach($files as $file){
326+
if(($file->getIndexStatus() == 'U' || $file->getWorkTreeStatus() == 'U')
327+
|| ($file->getIndexStatus() == 'D' && $file->getWorkTreeStatus() == 'D')
328+
|| ($file->getIndexStatus() == 'A' && $file->getWorkTreeStatus() == 'A')
329+
){
330+
$conflictedFiles[] = $file;
331+
}
332+
}
333+
$files = $conflictedFiles;
334+
}
335+
336+
return $files;
337+
}
291338

292339
/**
293-
* Reset a File bakc to head.
340+
* Reset a File back to head.
294341
*
295342
* @Route("/reset-file/{filePath}", name="project_reset_file")
296343
* @Method("GET")
@@ -301,7 +348,7 @@ public function resetFileAction($filePath)
301348
try {
302349
$gitUndoCommand = $this->gitCommands->command('undo');
303350
$file = urldecode($filePath);
304-
$response = $gitUndoCommand->checkoutFile($file, 'HEAD');
351+
$response = $gitUndoCommand->checkoutFile($file, 'HEAD', false);
305352
$this->get('session')->getFlashBag()->add('notice', $response);
306353
$this->get('session')->getFlashBag()->add('status-refresh', 'true');
307354
} catch (\Exception $e) {
@@ -325,4 +372,87 @@ protected function issueNumberfromBranch($branch)
325372

326373
return $issueNumber;
327374
}
375+
376+
/**
377+
* Fix git conflict files
378+
*
379+
* @Route("/fix-conflict/{filePath}", name="project_fix_conflict")
380+
* @Method("GET")
381+
* @ProjectAccess(grantType="EDIT")
382+
* @Template()
383+
*/
384+
public function fixConflictAction($filePath)
385+
{
386+
$file = urldecode($filePath);
387+
388+
return array_merge($this->viewVariables, array(
389+
'filePath' => $filePath,
390+
));
391+
}
392+
393+
/**
394+
* Reset a File back to head.
395+
*
396+
* @Route("/fixed-conflict/{filePath}/{option}", name="project_fixed_conflict")
397+
* @Method("GET")
398+
* @ProjectAccess(grantType="EDIT")
399+
* @Template()
400+
*/
401+
public function fixedConflictAction($filePath,$option)
402+
{
403+
$file = urldecode($filePath);
404+
try {
405+
$gitUndoCommand = $this->gitCommands->command('undo');
406+
if($option === 'theirs'){
407+
$response = $gitUndoCommand->checkoutTheirFile($file);
408+
}elseif($option === 'ours'){
409+
$response = $gitUndoCommand->checkoutOurFile($file);
410+
}elseif($option === 'delete'){
411+
$response = $gitUndoCommand->deleteFile($file);
412+
}else{
413+
$response = $gitUndoCommand->addFile($file);
414+
}
415+
416+
$this->get('session')->getFlashBag()->add('notice', $response);
417+
$this->get('session')->getFlashBag()->add('status-refresh', 'true');
418+
} catch (\Exception $e) {
419+
$this->get('session')->getFlashBag()->add('error', $e->getMessage());
420+
}
421+
422+
return $this->redirect($this->generateUrl('project_commitlist'));
423+
}
424+
425+
/**
426+
* Fix deleted conflict e.g. (D U)
427+
*
428+
* @Route("/fix-delete-conflict/{filePath}", name="project_fix_delete_conflict")
429+
* @Method("GET")
430+
* @ProjectAccess(grantType="EDIT")
431+
* @Template()
432+
*/
433+
public function fixDeleteConflictAction($filePath)
434+
{
435+
$file = urldecode($filePath);
436+
437+
return array_merge($this->viewVariables, array(
438+
'filePath' => $filePath,
439+
));
440+
}
441+
442+
/**
443+
* Fix file that has been added in both branches e.g. (A A)
444+
*
445+
* @Route("/fix-add-conflict/{filePath}", name="project_fix_add_conflict")
446+
* @Method("GET")
447+
* @ProjectAccess(grantType="EDIT")
448+
* @Template()
449+
*/
450+
public function fixAddConflictAction($filePath)
451+
{
452+
$file = urldecode($filePath);
453+
454+
return array_merge($this->viewVariables, array(
455+
'filePath' => $filePath,
456+
));
457+
}
328458
}

src/VersionControl/GitControlBundle/Resources/public/theme/css/custom.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,3 +521,17 @@ a.environment-info-btn.active>.fa-angle-left {
521521
margin-top: 0;
522522
}
523523

524+
.small-box h3{
525+
color: #fff;
526+
font-size: 28px;
527+
font-weight: normal;
528+
}
529+
530+
.small-box a p{
531+
color: #fff;
532+
}
533+
534+
.small-box .icon{
535+
font-size: 80px;
536+
}
537+

src/VersionControl/GitControlBundle/Resources/views/FormTheme/_field-prototype.html.twig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@
101101
{% if((file.workTreeStatus == 'M') or (file.workTreeStatus == 'D') ) %}
102102
<a href="{{ path('project_reset_file', { 'id': project.id,'filePath':file.path1|url_encode })}}" class="pull-right btn btn-sm btn-default btn-flat non-ajax" data-confirm="Are you sure you wish to undo all the changes to this file? Warning: You will not be able to revert back." data-confirm-header="Reset File">Reset to head</a>
103103
{% endif %}
104+
{% if((file.indexStatus == 'U')) %}
105+
<a data-toggle="modal" data-target="#diff" href="{{ path('project_fix_conflict', { 'id': project.id,'filePath':file.path1|url_encode })}}" class="pull-right btn btn-sm btn-default btn-flat non-ajax">
106+
Fix Conflict
107+
</a>
108+
{% endif %}
104109
</div>
105110
</div>
106111
</div>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<div class="modal-header">
2+
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
3+
<h4 class="modal-title">Fix Conflict: {{filePath}}</h4>
4+
</div>
5+
<div class="modal-body">
6+
<div class="row">
7+
<div class="col-sm-4">
8+
<div class="small-box bg-aqua">
9+
<div class="inner">
10+
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'ours' }) }}" class="non-ajax">
11+
<h3>Use Our File</h3>
12+
<p>Use original working branch file</p>
13+
</a>
14+
</div>
15+
<div class="icon">
16+
<i class="fa fa-file"></i>
17+
</div>
18+
19+
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'ours' }) }}" class="small-box-footer non-ajax">
20+
<i class="fa fa-file" aria-hidden="true"></i>
21+
Use our file
22+
</a>
23+
</div>
24+
</div>
25+
<div class="col-sm-4">
26+
<div class="small-box bg-green">
27+
<div class="inner">
28+
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'theirs' }) }}" class="non-ajax">
29+
<h3>Use Their File</h3>
30+
<p>Use other branches file</p>
31+
</a>
32+
</div>
33+
<div class="icon">
34+
<i class="fa fa-file-o"></i>
35+
</div>
36+
37+
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'theirs' }) }}" class="small-box-footer non-ajax">
38+
<i class="fa fa-file-o fa-4" aria-hidden="true"></i>
39+
Use their file
40+
</a>
41+
</div>
42+
</div>
43+
<div class="col-sm-4">
44+
<div class="small-box bg-orange">
45+
<div class="inner">
46+
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'manual' }) }}" class="non-ajax">
47+
<h3>Manual Fix</h3>
48+
<p>Fixed with IDE</p>
49+
</a>
50+
</div>
51+
<div class="icon">
52+
<i class="fa fa-file-code-o"></i>
53+
</div>
54+
55+
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'manual' }) }}" class="small-box-footer non-ajax">
56+
<i class="fa fa-file-code-o " aria-hidden="true"></i>
57+
Manual Fix
58+
</a>
59+
</div>
60+
</div>
61+
</div>
62+
</div>
63+
<div class="modal-footer">
64+
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
65+
</div>

0 commit comments

Comments
 (0)