Skip to content

Commit

Permalink
Fixed bugs
Browse files Browse the repository at this point in the history
Handle merge conflicts better
  • Loading branch information
bobfloats authored and root committed Apr 12, 2017
1 parent b6a70db commit 5404175
Show file tree
Hide file tree
Showing 15 changed files with 889 additions and 394 deletions.
456 changes: 233 additions & 223 deletions composer.lock

Large diffs are not rendered by default.

Expand Up @@ -123,5 +123,16 @@ public function getPreviousCommitHash($commitHash = 'HEAD', $fileName = false)

return $previousCommitHash;
}

/**
* Get array of conflict file names
* @return array of conflict file names
*/
public function getConflictFileNames(){

$command = " git diff --name-only --diff-filter=U";
$response = $this->command->runCommand($command);
return$this->splitOnNewLine($response);
}

}
Expand Up @@ -67,10 +67,86 @@ public function checkoutCommit($commitHash = 'HEAD')
*
* @return string
*/
public function checkoutFile($file, $commitHash = 'HEAD')
public function checkoutFile($file, $commitHash = 'HEAD', $triggerGitAlterFilesEvent = true)
{
$response = $this->command->runCommand(sprintf('git checkout %s %s', escapeshellarg($commitHash), escapeshellarg($file)));

//Trigger file alter Event
if($triggerGitAlterFilesEvent === true){
$this->triggerGitAlterFilesEvent();
}

return $response;
}

/**
* Check out a file from merge
*
* @param string $file
*
* @return string
*/
public function checkoutTheirFile($file)
{
$this->command->runCommand(sprintf('git checkout --theirs %s', escapeshellarg($file)));
$this->command->runCommand(sprintf('git add %s', escapeshellarg($file)));
$response = 'Using their merged in file for "'.$file.'"';

//Trigger file alter Event
$this->triggerGitAlterFilesEvent();

return $response;
}

/**
* Check out a file from merge conflict
*
* @param string $file
*
* @return string
*/
public function checkoutOurFile($file)
{
$this->command->runCommand(sprintf('git checkout --ours %s', escapeshellarg($file)));
$this->command->runCommand(sprintf('git add %s', escapeshellarg($file)));
$response = 'Using original file from current branch for "'.$file.'"';

//Trigger file alter Event
$this->triggerGitAlterFilesEvent();

return $response;
}

/**
* Check out a file from merge conflict
*
* @param string $file
*
* @return string
*/
public function addFile($file)
{
$this->command->runCommand(sprintf('git add %s', escapeshellarg($file)));
$response = 'Manually fixed file "'.$file.'"';

//Trigger file alter Event
$this->triggerGitAlterFilesEvent();

return $response;
}

/**
* Check out a file from merge conflict
*
* @param string $file
*
* @return string
*/
public function deleteFile($file)
{
$this->command->runCommand(sprintf('git rm %s', escapeshellarg($file)));
$response = 'Delete file "'.$file.'"';

//Trigger file alter Event
$this->triggerGitAlterFilesEvent();

Expand Down
Expand Up @@ -72,6 +72,11 @@ class ProjectCommitController extends BaseProjectController
public function listAction($id)
{
$files = $this->gitCommitCommand->getFilesToCommit();

//Get merge conflicts
$conflictFileNames = $this->gitCommands->command('diff')->getConflictFileNames();

$files = $this->filterConflicts($files,$conflictFileNames);

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

return array_merge($this->viewVariables, array(
'files' => $files,
'conflictFileNames' => $conflictFileNames,
'commit_form' => $commitForm->createView(),
'issueCount' => $this->issuesCount,
));
Expand All @@ -102,6 +108,10 @@ public function listAction($id)
public function commitAction(Request $request)
{
$files = $this->gitCommitCommand->getFilesToCommit();

//Get merge conflicts
$conflictFileNames = $this->gitCommands->command('diff')->getConflictFileNames();
$files = $this->filterConflicts($files,$conflictFileNames);

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

return array_merge($this->viewVariables, array(
'files' => $files,
'conflictFileNames' => $conflictFileNames,
'commit_form' => $commitForm->createView(),
'issueCount' => $this->issuesCount,
));
Expand Down Expand Up @@ -288,9 +299,45 @@ public function fileDiffAction($id, $difffile)
'diffs' => $gitDiffs,
));
}

/**
* Filter conflicted files. Following is list of conflicted states
* -------------------------------------------------
* D D unmerged, both deleted
* A U unmerged, added by us
* U D unmerged, deleted by them
* U A unmerged, added by them
* D U unmerged, deleted by us
* A A unmerged, both added
* U U unmerged, both modified
* -------------------------------------------------
*
* @param array $files
* @param array $conflictedFiles
* @return type
*/
public function filterConflicts($files,$conflictedFiles){

//Get merge conflicts
$conflictFileNames = $this->gitCommands->command('diff')->getConflictFileNames();
if(count($conflictFileNames) > 0){
$conflictedFiles = array();
foreach($files as $file){
if(($file->getIndexStatus() == 'U' || $file->getWorkTreeStatus() == 'U')
|| ($file->getIndexStatus() == 'D' && $file->getWorkTreeStatus() == 'D')
|| ($file->getIndexStatus() == 'A' && $file->getWorkTreeStatus() == 'A')
){
$conflictedFiles[] = $file;
}
}
$files = $conflictedFiles;
}

return $files;
}

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

return $issueNumber;
}

/**
* Fix git conflict files
*
* @Route("/fix-conflict/{filePath}", name="project_fix_conflict")
* @Method("GET")
* @ProjectAccess(grantType="EDIT")
* @Template()
*/
public function fixConflictAction($filePath)
{
$file = urldecode($filePath);

return array_merge($this->viewVariables, array(
'filePath' => $filePath,
));
}

/**
* Reset a File back to head.
*
* @Route("/fixed-conflict/{filePath}/{option}", name="project_fixed_conflict")
* @Method("GET")
* @ProjectAccess(grantType="EDIT")
* @Template()
*/
public function fixedConflictAction($filePath,$option)
{
$file = urldecode($filePath);
try {
$gitUndoCommand = $this->gitCommands->command('undo');
if($option === 'theirs'){
$response = $gitUndoCommand->checkoutTheirFile($file);
}elseif($option === 'ours'){
$response = $gitUndoCommand->checkoutOurFile($file);
}elseif($option === 'delete'){
$response = $gitUndoCommand->deleteFile($file);
}else{
$response = $gitUndoCommand->addFile($file);
}

$this->get('session')->getFlashBag()->add('notice', $response);
$this->get('session')->getFlashBag()->add('status-refresh', 'true');
} catch (\Exception $e) {
$this->get('session')->getFlashBag()->add('error', $e->getMessage());
}

return $this->redirect($this->generateUrl('project_commitlist'));
}

/**
* Fix deleted conflict e.g. (D U)
*
* @Route("/fix-delete-conflict/{filePath}", name="project_fix_delete_conflict")
* @Method("GET")
* @ProjectAccess(grantType="EDIT")
* @Template()
*/
public function fixDeleteConflictAction($filePath)
{
$file = urldecode($filePath);

return array_merge($this->viewVariables, array(
'filePath' => $filePath,
));
}

/**
* Fix file that has been added in both branches e.g. (A A)
*
* @Route("/fix-add-conflict/{filePath}", name="project_fix_add_conflict")
* @Method("GET")
* @ProjectAccess(grantType="EDIT")
* @Template()
*/
public function fixAddConflictAction($filePath)
{
$file = urldecode($filePath);

return array_merge($this->viewVariables, array(
'filePath' => $filePath,
));
}
}
Expand Up @@ -521,3 +521,17 @@ a.environment-info-btn.active>.fa-angle-left {
margin-top: 0;
}

.small-box h3{
color: #fff;
font-size: 28px;
font-weight: normal;
}

.small-box a p{
color: #fff;
}

.small-box .icon{
font-size: 80px;
}

Expand Up @@ -101,6 +101,11 @@
{% if((file.workTreeStatus == 'M') or (file.workTreeStatus == 'D') ) %}
<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>
{% endif %}
{% if((file.indexStatus == 'U')) %}
<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">
Fix Conflict
</a>
{% endif %}
</div>
</div>
</div>
Expand Down
@@ -0,0 +1,65 @@
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Fix Conflict: {{filePath}}</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-sm-4">
<div class="small-box bg-aqua">
<div class="inner">
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'ours' }) }}" class="non-ajax">
<h3>Use Our File</h3>
<p>Use original working branch file</p>
</a>
</div>
<div class="icon">
<i class="fa fa-file"></i>
</div>

<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'ours' }) }}" class="small-box-footer non-ajax">
<i class="fa fa-file" aria-hidden="true"></i>
Use our file
</a>
</div>
</div>
<div class="col-sm-4">
<div class="small-box bg-green">
<div class="inner">
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'theirs' }) }}" class="non-ajax">
<h3>Use Their File</h3>
<p>Use other branches file</p>
</a>
</div>
<div class="icon">
<i class="fa fa-file-o"></i>
</div>

<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'theirs' }) }}" class="small-box-footer non-ajax">
<i class="fa fa-file-o fa-4" aria-hidden="true"></i>
Use their file
</a>
</div>
</div>
<div class="col-sm-4">
<div class="small-box bg-orange">
<div class="inner">
<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'manual' }) }}" class="non-ajax">
<h3>Manual Fix</h3>
<p>Fixed with IDE</p>
</a>
</div>
<div class="icon">
<i class="fa fa-file-code-o"></i>
</div>

<a href="{{ path('project_fixed_conflict', { 'id': project.id,'filePath':filePath,'option': 'manual' }) }}" class="small-box-footer non-ajax">
<i class="fa fa-file-code-o " aria-hidden="true"></i>
Manual Fix
</a>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>

0 comments on commit 5404175

Please sign in to comment.