Coverage Report - com.aragost.javahg.merge.ConflictResolvingContext
 
Classes in this File Line Coverage Branch Coverage Complexity
ConflictResolvingContext
94%
71/75
79%
27/34
2.818
 
 1  
 package com.aragost.javahg.merge;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.util.Collection;
 5  
 import java.util.Collections;
 6  
 import java.util.List;
 7  
 
 8  
 import com.aragost.javahg.Changeset;
 9  
 import com.aragost.javahg.Repository;
 10  
 import com.aragost.javahg.WorkingCopy;
 11  
 import com.aragost.javahg.commands.LogCommand;
 12  
 import com.aragost.javahg.commands.ResolveCommand;
 13  
 import com.aragost.javahg.commands.ResolveStatusLine;
 14  
 import com.aragost.javahg.internals.AbstractCommand;
 15  
 import com.aragost.javahg.internals.HgInputStream;
 16  
 import com.aragost.javahg.internals.UnexpectedCommandOutputException;
 17  
 import com.aragost.javahg.internals.Utils;
 18  
 import com.google.common.collect.Lists;
 19  
 
 20  
 /**
 21  
  * Base class for a context where conflicts are resolved.
 22  
  * <p>
 23  
  * That is for example after a merge or graft.
 24  
  */
 25  
 public abstract class ConflictResolvingContext {
 26  
 
 27  1
     private static final byte[] USE_RESOLVE_EXPLANATION = "use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon\n".getBytes();
 28  1
     private static final byte[] USE_RESOLVE_SHORT_EXPLANATION = "use 'hg resolve' to retry unresolved file merges\n".getBytes();
 29  1
     private static final byte[] BRANCH_MERGE_EXPLANATION = "(branch merge, don't forget to commit)\n".getBytes();
 30  1
     private static final byte[] FILES_REMOVED = " files removed, ".getBytes();
 31  1
     private static final byte[] FILES_MERGED = " files merged, ".getBytes();
 32  1
     private static final byte[] FILES_UPDATED = " files updated, ".getBytes();
 33  1
     private static final byte[] LOCAL_CHANGED_AFTER = " which remote deleted\nuse (c)hanged version or (d)elete? c\n".getBytes();
 34  1
     private static final byte[] LOCAL_CHANGED = " local changed ".getBytes();
 35  1
     private static final byte[] REMOVED_CHANGE_AFTER = " which local deleted\nuse (c)hanged version or leave (d)eleted? c\n".getBytes();
 36  1
     private static final byte[] REMOTE_CHANGED = "remote changed ".getBytes();
 37  1
     private static final byte[] CONFLICTING_FLAGS = " conflicting flags for ".getBytes();
 38  
     private static final String NONE_EXEC_SYMLINK = "(n)one, e(x)ec or sym(l)ink? n\n";
 39  
 
 40  
     private AbstractCommand command;
 41  
 
 42  
     private WorkingCopy workingCopy;
 43  
 
 44  14
     private List<KeepDeleteConflict> keepDeleteConflicts = Lists.newArrayList();
 45  
 
 46  14
     private List<FlagConflict> flagConflicts = Lists.newArrayList();
 47  
 
 48  
     private List<MergeConflict> mergeConflicts;
 49  
 
 50  
     private Changeset base;
 51  
 
 52  14
     public ConflictResolvingContext(AbstractCommand command) {
 53  14
         this.command = command;
 54  14
         this.workingCopy = this.command.getRepository().workingCopy();
 55  14
     }
 56  
 
 57  
     public WorkingCopy getWorkingCopy() {
 58  7
         return workingCopy;
 59  
     }
 60  
 
 61  
     public Collection<FlagConflict> getFlagConflicts() {
 62  7
         return flagConflicts;
 63  
     }
 64  
 
 65  
     public List<KeepDeleteConflict> getKeepDeleteConflicts() {
 66  9
         return keepDeleteConflicts;
 67  
     }
 68  
 
 69  
     public synchronized List<MergeConflict> getMergeConflicts() {
 70  6
         if (this.mergeConflicts == null) {
 71  5
             List<ResolveStatusLine> lines = ResolveCommand.on(getRepository()).list();
 72  5
             List<MergeConflict> conflicts = Lists.newArrayListWithCapacity(lines.size());
 73  5
             for (ResolveStatusLine line : lines) {
 74  7
                 MergeConflict mergeConflict = new MergeConflict(this, line.getFileName());
 75  7
                 conflicts.add(mergeConflict);
 76  7
             }
 77  5
             this.mergeConflicts = conflicts;
 78  
         }
 79  6
         return mergeConflicts;
 80  
     }
 81  
 
 82  
     public Repository getRepository() {
 83  14
         return this.command.getRepository();
 84  
     }
 85  
 
 86  
     public AbstractCommand getCommand() {
 87  1
         return command;
 88  
     }
 89  
 
 90  
     /**
 91  
      * Read input from the stream record conflicts.
 92  
      * <p>
 93  
      * 
 94  
      * @param in
 95  
      * @param whenUnknowReturn
 96  
      * @throws IOException
 97  
      */
 98  
     public void processStream(HgInputStream in, boolean whenUnknowReturn) throws IOException {
 99  33
         while (!in.isEof()) {
 100  21
             byte[] endPattern = null;
 101  21
             KeepDeleteConflict.State keepState = null;
 102  21
             if (in.match(REMOTE_CHANGED)) {
 103  2
                 endPattern = REMOVED_CHANGE_AFTER;
 104  2
                 keepState = KeepDeleteConflict.State.DELETE;
 105  19
             } else if (in.match(LOCAL_CHANGED)) {
 106  1
                 endPattern = LOCAL_CHANGED_AFTER;
 107  1
                 keepState = KeepDeleteConflict.State.KEEP;
 108  18
             } else if (in.match(CONFLICTING_FLAGS)) {
 109  1
                 String fileName = in.textUpTo('\n');
 110  1
                 in.mustMatch(NONE_EXEC_SYMLINK.getBytes());
 111  1
                 FlagConflict flagConflict = new FlagConflict(this, fileName);
 112  1
                 this.flagConflicts.add(flagConflict);
 113  
 
 114  1
             } else if ((in.readDecimal()) != null) {
 115  9
                 in.mustMatch(FILES_UPDATED);
 116  9
                 Integer merged = in.readDecimal();
 117  9
                 in.mustMatch(FILES_MERGED);
 118  9
                 Integer removed = in.readDecimal();
 119  9
                 in.mustMatch(FILES_REMOVED);
 120  9
                 Integer unresolved = in.readDecimal();
 121  9
                 in.mustMatch(" files unresolved\n".getBytes());
 122  9
                 if (merged == null || removed == null || unresolved == null) {
 123  0
                     throw new UnexpectedCommandOutputException(this.command, null);
 124  
                 }
 125  9
                 if (unresolved.intValue() == 0) {
 126  4
                     this.mergeConflicts = Collections.emptyList();
 127  
                     // If there is merge conflicts it will be lazy
 128  
                     // intialized
 129  
                 }
 130  9
             } else if (in.match(USE_RESOLVE_EXPLANATION)) {
 131  
                 // ignore
 132  4
             } else if (in.match(USE_RESOLVE_SHORT_EXPLANATION)) {
 133  
                 // ignore
 134  3
             } else if (in.match(BRANCH_MERGE_EXPLANATION)) {
 135  
                 // ignore
 136  
             } else {
 137  0
                 if (whenUnknowReturn) {
 138  0
                     return;
 139  
                 } else {
 140  0
                     throw new UnexpectedCommandOutputException(Utils.readStream(in,
 141  
                             command.getRepository().newDecoder()));
 142  
                 }
 143  
             }
 144  21
             if (endPattern != null) {
 145  3
                 String fileName = in.textUpTo(endPattern);
 146  3
                 KeepDeleteConflict keepRemoveConflict = new KeepDeleteConflict(this, fileName, keepState);
 147  3
                 this.keepDeleteConflicts.add(keepRemoveConflict);
 148  
             }
 149  21
         }
 150  12
     }
 151  
 
 152  
     public Changeset getLocal() {
 153  4
         return getWorkingCopy().getParent1();
 154  
     }
 155  
 
 156  
     public Changeset getRemote() {
 157  3
         return getWorkingCopy().getParent2();
 158  
     }
 159  
 
 160  
     public synchronized Changeset getBase() {
 161  1
         if (base == null) {
 162  1
             String ancestorRev = "ancestor(" + getLocal().getNode() + "," + getRemote().getNode() + ")";
 163  1
             this.base = LogCommand.on(getRepository()).rev(ancestorRev).single();
 164  
         }
 165  1
         return this.base;
 166  
     }
 167  
 
 168  
 }