# HG changeset patch # User Artem Tikhomirov # Date 1321509898 -3600 # Node ID 75c452fdd76ac9364846bb034f2aa449740947ca # Parent a54bfe0db959dc332270c4eea0a40e0c404e1702 Merging state not detected when there's no conflicts to resolve (no merge/state file) diff -r a54bfe0db959 -r 75c452fdd76a cmdline/org/tmatesoft/hg/console/Main.java --- a/cmdline/org/tmatesoft/hg/console/Main.java Thu Nov 17 06:16:20 2011 +0100 +++ b/cmdline/org/tmatesoft/hg/console/Main.java Thu Nov 17 07:04:58 2011 +0100 @@ -99,9 +99,9 @@ // m.testParents(); // m.testEffectiveFileLog(); // m.testCatAtCsetRevision(); -// m.testMergeState(); + m.testMergeState(); // m.testFileStatus(); - m.dumpBranches(); +// m.dumpBranches(); // m.inflaterLengthException(); // m.dumpIgnored(); // m.dumpDirstate(); diff -r a54bfe0db959 -r 75c452fdd76a src/org/tmatesoft/hg/repo/HgMergeState.java --- a/src/org/tmatesoft/hg/repo/HgMergeState.java Thu Nov 17 06:16:20 2011 +0100 +++ b/src/org/tmatesoft/hg/repo/HgMergeState.java Thu Nov 17 07:04:58 2011 +0100 @@ -93,16 +93,18 @@ public void refresh() throws IOException/*XXX it's unlikely caller can do anything reasonable about IOException */ { entries = null; - wcp1 = wcp2 = stateParent = Nodeid.NULL; + // it's possible there are two parents but no merge/state, we shall report this case as 'merging', with proper + // first and second parent values + stateParent = Nodeid.NULL; + Pool nodeidPool = new Pool(); + Pool fnamePool = new Pool(); + Pair wcParents = repo.getWorkingCopyParents(); + wcp1 = nodeidPool.unify(wcParents.first()); wcp2 = nodeidPool.unify(wcParents.second()); final File f = new File(repo.getRepositoryRoot(), "merge/state"); if (!f.canRead()) { // empty state return; } - Pool nodeidPool = new Pool(); - Pool fnamePool = new Pool(); - Pair wcParents = repo.getWorkingCopyParents(); - wcp1 = nodeidPool.unify(wcParents.first()); wcp2 = nodeidPool.unify(wcParents.second()); ArrayList result = new ArrayList(); // FIXME need to settle use of Pool and PathPool // latter is pool that can create objects on demand, former is just cache @@ -159,24 +161,33 @@ pathPool.clear(); } - + /** + * Repository is in 'merging' state when changeset to be committed got two parents. + * This method doesn't tell whether there are (un)resolved conflicts in the working copy, + * use {@link #getConflicts()} (which makes sense only when {@link #isStale()} is false). + * @return true when repository is being merged + */ public boolean isMerging() { return !getFirstParent().isNull() && !getSecondParent().isNull() && !isStale(); } /** + * Merge state file may not match actual working copy due to rollback or undo operations. + * Value of {@link #getConflicts()} is reasonable iff this method returned false. + * * @return true when recorded merge state doesn't seem to correspond to present working copy */ public boolean isStale() { if (wcp1 == null) { throw new HgBadStateException("Call #refresh() first"); } - return !wcp1.equals(stateParent); + return !stateParent.isNull() /*there's merge state*/ && !wcp1.equals(stateParent) /*and it doesn't match*/; } /** - * FIXME decide what to return if there's no merge state altogether (perhaps, separate method to check that) - * @return never null + * It's possible for a repository to be in a 'merging' state (@see {@link #isMerging()} without any + * conflict to resolve (no merge state information file). + * @return first parent of the working copy, never null */ public Nodeid getFirstParent() { if (wcp1 == null) { @@ -185,6 +196,9 @@ return wcp1; } + /** + * @return second parent of the working copy, never null + */ public Nodeid getSecondParent() { if (wcp2 == null) { throw new HgBadStateException("Call #refresh() first"); @@ -202,6 +216,12 @@ return stateParent; } + /** + * List of conflicts as recorded in the merge state information file. + * Note, this information is valid unless {@link #isStale()} is true. + * + * @return non-null list with both resolved and unresolved conflicts. + */ public List getConflicts() { return entries == null ? Collections.emptyList() : Arrays.asList(entries); }