-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better handling of add/add conflicts #728
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -515,6 +515,9 @@ exports.computeChanges = co.wrap(function *(repo, index, targetCommit) { | |
* `repo`. If `conflicts` is non-empty, return a non-empty string desribing | ||
* them. Otherwise, return the empty string. | ||
* | ||
* Half-open the conflicting repos and fetch all commits that are in the | ||
* conflict; this will make it easier for users to resolve the conflict. | ||
* | ||
* @param {NodeGit.Repository} repo | ||
* @param {NodeGit.Index} index | ||
* @param {Object} conflicts from sub name to `Conflict` | ||
|
@@ -523,11 +526,47 @@ exports.computeChanges = co.wrap(function *(repo, index, targetCommit) { | |
exports.writeConflicts = co.wrap(function *(repo, index, conflicts) { | ||
let errorMessage = ""; | ||
const names = Object.keys(conflicts).sort(); | ||
const opener = new Open.Opener(repo, null); | ||
const fetcher = yield opener.fetcher(); | ||
for (let name of names) { | ||
yield ConflictUtil.addConflict(index, name, conflicts[name]); | ||
let conflict = conflicts[name]; | ||
let configured = false; | ||
try { | ||
// We just want to see if it's configured | ||
const url = yield fetcher.getSubmoduleUrl(name); | ||
configured = true; | ||
} catch (e) { | ||
// nope, so we cannot fetch | ||
} | ||
if (configured) { | ||
const bare = Open.SUB_OPEN_OPTION.FORCE_BARE; | ||
const subRepo = yield opener.getSubrepo(name, bare); | ||
|
||
for (const stage of [conflict.ancestor, conflict.our, | ||
conflict.their]) { | ||
if (stage !== null) { | ||
yield fetcher.fetchSha(subRepo, name, stage.id); | ||
} | ||
} | ||
} | ||
yield ConflictUtil.addConflict(index, name, conflict); | ||
errorMessage += `\ | ||
Conflicting entries for submodule ${colors.red(name)} | ||
Conflicting entries for submodule ${colors.red(name)}. | ||
`; | ||
if (conflict.our !== null && conflict.their !== null) { | ||
// add-add | ||
const root = repo.workdir(); | ||
const our = conflict.our.id; | ||
const their = conflict.their.id; | ||
errorMessage += ` | ||
To choose your version of the ${name}, use the following magic: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this the only/recommended way to resolve add-add conflict? Should we trust our user to resolve the conflict manually? I am afraid people may blinded run them and override upstream changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The third way is more complicated: we could see if the two sets share a merge-base and if so rebase inside the submodule. That's a TODO -- it's one reason why I did the half-open. But I would guess that this same merge-base thing only happens in some small number of cases; mostly add/adds are e.g. different people importing the same ext codebase. People might do something stupid, and if so it'll show up in code review. So hopefully someone will notice. |
||
git -C ${root} update-index --cache-info 160000,${our},${name} | ||
To choose their version of the ${name}, use the following magic: | ||
git -C ${root} update-index --cache-info 160000,${their},${name} | ||
To compare, try: | ||
git -C ${root}${name} diff ${their} ${our} | ||
`; | ||
} | ||
} | ||
return errorMessage; | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -281,3 +281,7 @@ exports.makeBareCopy = co.wrap(function *(repo, path) { | |
yield NodeGit.Remote.delete(bare, "origin"); | ||
return bare; | ||
}); | ||
|
||
exports.quotemeta = function(str) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you explain briefly why we suddenly need this helper now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we're now doing regex matching. |
||
return String(str).replace(/\W/g, "\\$&"); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a useful and orthogonal piece of code, could we make it a util function, something like "fetch sha for half opend subrepo if needed"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question is: what sha? Here, we loop over the stages, which is what's needed in this case. But is that really generally useful?