mirror of
https://github.com/fluxscape/fluxscape.git
synced 2026-01-12 07:12:54 +01:00
Initial commit
Co-Authored-By: Eric Tuvesson <eric.tuvesson@gmail.com> Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com> Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com> Co-Authored-By: Anders Larsson <64838990+anders-topp@users.noreply.github.com> Co-Authored-By: Johan <4934465+joolsus@users.noreply.github.com> Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com> Co-Authored-By: victoratndl <99176179+victoratndl@users.noreply.github.com>
This commit is contained in:
193
packages/noodl-git/src/core/merge-tree-parser.ts
Normal file
193
packages/noodl-git/src/core/merge-tree-parser.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
import { IMergeTreeEntry, MergeTreeResult } from './models/merge';
|
||||
import { ComputedAction } from './models/computed-action';
|
||||
|
||||
interface IBlobSource {
|
||||
readonly type: string;
|
||||
readonly path: string;
|
||||
readonly sha: string;
|
||||
readonly mode: string;
|
||||
}
|
||||
|
||||
function updateCurrentMergeEntry(
|
||||
entry: IMergeTreeEntry | undefined,
|
||||
context: string,
|
||||
blobSource: IBlobSource
|
||||
): IMergeTreeEntry {
|
||||
const currentMergeEntry = entry || {
|
||||
context,
|
||||
diff: ''
|
||||
};
|
||||
|
||||
const blob = {
|
||||
sha: blobSource.sha,
|
||||
mode: blobSource.mode,
|
||||
path: blobSource.path
|
||||
};
|
||||
|
||||
switch (blobSource.type) {
|
||||
case 'base':
|
||||
return {
|
||||
...currentMergeEntry,
|
||||
base: blob
|
||||
};
|
||||
case 'result':
|
||||
return {
|
||||
...currentMergeEntry,
|
||||
result: blob
|
||||
};
|
||||
case 'our':
|
||||
return {
|
||||
...currentMergeEntry,
|
||||
our: blob
|
||||
};
|
||||
case 'their':
|
||||
return {
|
||||
...currentMergeEntry,
|
||||
their: blob
|
||||
};
|
||||
default:
|
||||
return currentMergeEntry;
|
||||
}
|
||||
}
|
||||
|
||||
// the merge-tree output is a collection of entries like this
|
||||
//
|
||||
// changed in both
|
||||
// base 100644 f69fbc5c40409a1db7a3f8353bfffe46a21d6054 atom/browser/resources/mac/Info.plist
|
||||
// our 100644 9094f0f7335edf833d51f688851e6a105de60433 atom/browser/resources/mac/Info.plist
|
||||
// their 100644 2dd8bc646cff3869557549a39477e30022e6cfdd atom/browser/resources/mac/Info.plist
|
||||
// @@ -17,9 +17,15 @@
|
||||
// <key>CFBundleIconFile</key>
|
||||
// <string>electron.icns</string>
|
||||
// <key>CFBundleVersion</key>
|
||||
// +<<<<<<< .our
|
||||
// <string>4.0.0</string>
|
||||
// <key>CFBundleShortVersionString</key>
|
||||
// <string>4.0.0</string>
|
||||
// +=======
|
||||
// + <string>1.4.16</string>
|
||||
// + <key>CFBundleShortVersionString</key>
|
||||
// + <string>1.4.16</string>
|
||||
// +>>>>>>> .their
|
||||
// <key>LSApplicationCategoryType</key>
|
||||
//<string>public.app-category.developer-tools</string>
|
||||
// <key>LSMinimumSystemVersion</key>
|
||||
|
||||
// The first line for each entry is what I'm referring to as the the header
|
||||
// This regex filters on the known entries that can appear
|
||||
const contextHeaderRe = /^(merged|added in remote|removed in remote|changed in both|removed in local|added in both)$/;
|
||||
|
||||
// the rest of the header is made up of a number of entries formatted like this
|
||||
//
|
||||
// base 100644 f69fbc5c40409a1db7a3f8353bfffe46a21d6054 atom/browser/resources/mac/Info.plist
|
||||
//
|
||||
// this regex let's us extract the blob details - the filename may also change
|
||||
// as part of the merge if files are moved or renamed
|
||||
const blobEntryRe = /^\s{2}(result|our|their|base)\s+(\d{6})\s([0-9a-f]{40})\s(.+)$/;
|
||||
|
||||
/**
|
||||
* Parse the Git output of a merge-tree command to identify whether it
|
||||
* has detected any conflicts between the branches to be merged
|
||||
*
|
||||
* @param text the stdout from a `git merge-tree` command
|
||||
*
|
||||
*/
|
||||
export function parseMergeTreeResult(text: string): MergeTreeResult {
|
||||
const entries = new Array<IMergeTreeEntry>();
|
||||
|
||||
const lines = text.split('\n');
|
||||
|
||||
let mergeEntryHeader: string | undefined;
|
||||
let currentMergeEntry: IMergeTreeEntry | undefined;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
const headerMatch = contextHeaderRe.exec(line);
|
||||
if (headerMatch != null) {
|
||||
mergeEntryHeader = headerMatch[1];
|
||||
|
||||
// push the previous entry, if defined, into the array
|
||||
if (currentMergeEntry != null) {
|
||||
entries.push(currentMergeEntry);
|
||||
currentMergeEntry = undefined;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// the next lines are a number of merge result entries
|
||||
// pointing to blobs representing the source blob
|
||||
// and the resulting blob generated by the merge
|
||||
const blobMatch = blobEntryRe.exec(line);
|
||||
if (blobMatch != null) {
|
||||
const type = blobMatch[1];
|
||||
const mode = blobMatch[2];
|
||||
const sha = blobMatch[3];
|
||||
const path = blobMatch[4];
|
||||
|
||||
const blob = {
|
||||
type,
|
||||
mode,
|
||||
sha,
|
||||
path
|
||||
};
|
||||
|
||||
if (mergeEntryHeader == null) {
|
||||
console.warn(`An unknown header was set while trying to parse the blob on line ${i}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'base':
|
||||
case 'result':
|
||||
case 'our':
|
||||
case 'their':
|
||||
currentMergeEntry = updateCurrentMergeEntry(currentMergeEntry, mergeEntryHeader, blob);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`invalid state - unexpected entry ${type} found when parsing rows`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentMergeEntry == null) {
|
||||
throw new Error(`invalid state - trying to append the diff to a merge entry that isn't defined on line ${i}`);
|
||||
} else {
|
||||
const currentDiff = currentMergeEntry.diff;
|
||||
const newDiff = currentDiff + line + '\n';
|
||||
currentMergeEntry = {
|
||||
...currentMergeEntry,
|
||||
diff: newDiff
|
||||
};
|
||||
|
||||
const lineHasConflictMarker =
|
||||
line.startsWith('+<<<<<<<') || line.startsWith('+=======') || line.startsWith('+>>>>>>>');
|
||||
|
||||
if (lineHasConflictMarker) {
|
||||
currentMergeEntry = {
|
||||
...currentMergeEntry,
|
||||
hasConflicts: true
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure the last entry is pushed onto the array
|
||||
if (currentMergeEntry != null) {
|
||||
entries.push(currentMergeEntry);
|
||||
currentMergeEntry = undefined;
|
||||
}
|
||||
|
||||
const entriesWithConflicts = entries.filter((e) => e.hasConflicts || false);
|
||||
|
||||
if (entriesWithConflicts.length > 0) {
|
||||
return {
|
||||
kind: ComputedAction.Conflicts,
|
||||
conflictedFiles: entriesWithConflicts.length,
|
||||
conflictedEntries: entriesWithConflicts
|
||||
};
|
||||
} else {
|
||||
return { kind: ComputedAction.Clean, entries };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user