Coverage Report - com.aragost.javahg.commands.GraftCommand
 
Classes in this File Line Coverage Branch Coverage Complexity
GraftCommand
92%
37/40
79%
27/34
4
 
 1  
 /*
 2  
  * #%L
 3  
  * JavaHg
 4  
  * %%
 5  
  * Copyright (C) 2011 aragost Trifork ag
 6  
  * %%
 7  
  * Permission is hereby granted, free of charge, to any person obtaining a copy
 8  
  * of this software and associated documentation files (the "Software"), to deal
 9  
  * in the Software without restriction, including without limitation the rights
 10  
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  
  * copies of the Software, and to permit persons to whom the Software is
 12  
  * furnished to do so, subject to the following conditions:
 13  
  * 
 14  
  * The above copyright notice and this permission notice shall be included in
 15  
  * all copies or substantial portions of the Software.
 16  
  * 
 17  
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18  
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19  
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20  
  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21  
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22  
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23  
  * THE SOFTWARE.
 24  
  * #L%
 25  
  */
 26  
 package com.aragost.javahg.commands;
 27  
 
 28  
 import java.io.IOException;
 29  
 
 30  
 import com.aragost.javahg.Changeset;
 31  
 import com.aragost.javahg.Repository;
 32  
 import com.aragost.javahg.commands.flags.GraftCommandFlags;
 33  
 import com.aragost.javahg.internals.HgInputStream;
 34  
 import com.aragost.javahg.internals.RuntimeIOException;
 35  
 import com.aragost.javahg.merge.GraftContext;
 36  
 
 37  
 /**
 38  
  * Command class for executing <tt>hg graft</tt>. Set flags from
 39  
  * {@link GraftCommandFlags} and call the {@link #execute} method.
 40  
  */
 41  
 public class GraftCommand extends GraftCommandFlags {
 42  
 
 43  4
     private boolean hasConflicts = false;
 44  4
     private boolean somethingSkipped = false;
 45  
 
 46  
     /**
 47  
      * @param repository
 48  
      *            the repository associated with this command.
 49  
      */
 50  
     public GraftCommand(Repository repository) {
 51  4
         super(repository);
 52  4
         cmdAppend("-y");
 53  4
         cmdAppend("--tool", "internal:fail");
 54  4
     }
 55  
 
 56  
     @Override
 57  
     public boolean isSuccessful() {
 58  5
         return super.isSuccessful() || this.hasConflicts || this.somethingSkipped;
 59  
     }
 60  
 
 61  
     /**
 62  
      * Run <tt>hg graft</tt> with the specified revisions.
 63  
      * <p>
 64  
      * If the grafting is succesful null is return. Otherwise a
 65  
      * MergeContext is return where the conflicts can be inspected and
 66  
      * resolved.
 67  
      * 
 68  
      * @param changeset
 69  
      *            the changeset to graft
 70  
      */
 71  
     public GraftContext execute(Changeset changeset) {
 72  4
         Repository repo = getRepository();
 73  4
         repo.lock();
 74  4
         HgInputStream stream = launchStream(changeset.getNode());
 75  
         try {
 76  4
             if (stream.match("grafting revision ".getBytes())) {
 77  3
                 int rev = stream.revisionUpTo('\n');
 78  3
                 GraftContext ctx = new GraftContext(this, rev);
 79  3
                 if (!stream.isEof()) {
 80  1
                     ctx.processStream(stream, true);
 81  
                 }
 82  3
                 stream.consumeAll();
 83  3
                 boolean flagOrKeepDeleteConflicts = !ctx.getFlagConflicts().isEmpty()
 84  
                         || !ctx.getKeepDeleteConflicts().isEmpty();
 85  3
                 if (getReturnCode() == -1 && this.hasConflicts || flagOrKeepDeleteConflicts) {
 86  2
                     if (flagOrKeepDeleteConflicts && ctx.getMergeConflicts().isEmpty()) {
 87  
                         // graft has actually made a new changeset,
 88  
                         // but
 89  
                         // there is actually flag conflict or
 90  
                         // keep/delete
 91  
                         // conflict. So rollback the changeset.
 92  1
                         Changeset rollbackChangeset = repo.tip();
 93  1
                         if (!changeset.getNode().equals(rollbackChangeset.getExtra().getString("source"))) {
 94  0
                             throw new IllegalStateException("Current tip is not grafted from expected changeset");
 95  
                         }
 96  1
                         RollbackCommand.on(repo).execute();
 97  1
                         ctx.setRollbackChangeset(rollbackChangeset);
 98  
                     }
 99  2
                     return ctx;
 100  
                 } else {
 101  1
                     return null;
 102  
                 }
 103  
             } else {
 104  1
                 return null;
 105  
             }
 106  0
         } catch (IOException e) {
 107  0
             throw new RuntimeIOException(e);
 108  
         } finally {
 109  4
             repo.unlock();
 110  
         }
 111  
     }
 112  
 
 113  
     /**
 114  
      * Execute the graft command with the continue flag.
 115  
      * 
 116  
      * @return true if a new changeset was created, false if for some
 117  
      *         reason graft did not succeed
 118  
      */
 119  
     public boolean executeContinue() {
 120  1
         launchString("--continue");
 121  1
         return getReturnCode() == 0;
 122  
     }
 123  
 
 124  
     @Override
 125  
     protected void doneHook() {
 126  5
         String errorString = getErrorString();
 127  5
         this.hasConflicts = errorString.indexOf("abort: unresolved conflicts, can't continue") >= 0
 128  
                 || errorString.indexOf("abort: unresolved merge conflicts (see hg help resolve)") >= 0;
 129  5
         this.somethingSkipped = errorString.indexOf("skipping ancestor revision ") >= 0;
 130  5
     }
 131  
 
 132  
     @Override
 133  
     protected void clear() {
 134  5
         super.clear();
 135  5
         this.hasConflicts = false;
 136  5
         this.somethingSkipped = false;
 137  5
     }
 138  
 
 139  
 }