Version Control - Git Project Work

Instructions

As this is considerably harder, an honest try is enough to pass this, see SVN project work for the instructions.

Steps

  1. Create a repository with Create-A-Repo. Clone a working copy from it.

    If you get stuck, you can create a new repository, or use commands such as below to resolve the situation:
    git push -f
    git reset --hard HEAD~1
    git reset --hard begin

  2. Add the following files to your repository:
    src/main/java/longcat/CliArgumentParser.java
    src/main/java/longcat/LengthUnit.java
    src/main/java/longcat/LongcatFactoryImpl.java
    src/test/java/longcat/CliArgumentParserTest.java

    Do these changes:
    src/main/java/longcat/LongcatFactory.java

    --- a/src/main/java/longcat/LongcatFactory.java
    +++ b/src/main/java/longcat/LongcatFactory.java
    @@ -1,8 +1,8 @@
     package longcat;
     
    -public class LongcatFactory {
    +public interface LongcatFactory {
     
    -    public Longcat createLongcat(int bodySize) {
    -        return new Longcat(bodySize);
    -    }
    +    Longcat createLongcat(int bodySize);
    +
    +    Longcat createLongcat(int length, LengthUnit unit);
     }
    

    src/test/java/longcat/LongcatFactoryTest.java
    --- a/src/test/java/longcat/LongcatFactoryTest.java
    +++ b/src/test/java/longcat/LongcatFactoryTest.java
    @@ -4,7 +4,7 @@ import junit.framework.TestCase;
     
     public class LongcatFactoryTest extends TestCase {
     
    -    private LongcatFactory factory = new LongcatFactory();
    +    private LongcatFactory factory = new LongcatFactoryImpl();
     
         public void test__Longcat_with_body_size_0() {
             Longcat longcat = factory.createLongcat(0);
    

    Commit the added and modified files with the following comment: "Command line argument parsing"

  3. Push the changes to the central repository.

    If everything was correct, the Robot will make a commit after yours with the message: "Command line interface".

    Pull the latest changes from the central repository.

  4. Add these files:
    src/test/java/longcat/LengthUnitTest.java

    Do these changes:
    src/main/java/longcat/LengthUnit.java

    --- a/src/main/java/longcat/LengthUnit.java
    +++ b/src/main/java/longcat/LengthUnit.java
    @@ -2,12 +2,14 @@ package longcat;
     
     public enum LengthUnit {
     
    -    METERS("m"), FEET("ft"), PETRONAS("petronas");
    +    METERS("m", 1.0), FEET("ft", 0.3048), PETRONAS("petronas", 451.9);
     
         private final String name;
    +    private final double lengthInMeters;
     
    -    private LengthUnit(String name) {
    +    private LengthUnit(String name, double lengthInMeters) {
             this.name = name;
    +        this.lengthInMeters = lengthInMeters;
         }
     
         public static LengthUnit parse(String name) {
    @@ -18,4 +20,8 @@ public enum LengthUnit {
             }
             throw new IllegalArgumentException("No such unit of length: " + name);
         }
    +
    +    public int from(int length, LengthUnit unit) {
    +        return (int) (length * unit.lengthInMeters / this.lengthInMeters);
    +    }
     }
    

    Commit them with the comment: "Length unit conversions"

  5. Push the changes to the central repository.

    The push will fail because the Robot made two commits just before yours: "Optimized: use StringBuilder to construct the longcat body, as it can be very loooooooooong" and "Refactored: renamed constants".

    Pull the latest changes. Use rebase so that your recent "Length unit conversions" will be last in the commit history. (There should be no conflicts.)

    Push the changes to the central repository.

    If rebase was not used correctly, the Robot will give an error message. In that case try again (old commits can be accessed with the "git reflog" command).

  6. It should be possible to specify the Longcat length with natural length units, such as Petronas Towers. Do these changes:
    src/main/java/longcat/LengthUnit.java
    --- a/src/main/java/longcat/LengthUnit.java
    +++ b/src/main/java/longcat/LengthUnit.java
    @@ -2,7 +2,7 @@ package longcat;
     
     public enum LengthUnit {
     
    -    METERS("m", 1.0), FEET("ft", 0.3048), PETRONAS("petronas", 451.9);
    +    METERS("m", 1.0), FEET("ft", 0.3048), PETRONAS("petronas", 451.9), LINES("lines", 0.009);
     
         private final String name;
         private final double lengthInMeters;
    

    src/main/java/longcat/Longcat.java
    --- a/src/main/java/longcat/Longcat.java
    +++ b/src/main/java/longcat/Longcat.java
    @@ -27,11 +27,14 @@ public class Longcat {
         private final int bodySize;
     
         public Longcat(int bodySize) {
    +        if (bodySize < 0) {
    +            throw new IllegalArgumentException("Longcat can not be that short!");
    +        }
             this.bodySize = bodySize;
         }
     
         public String getBody() {
    -        StringBuilder body = new StringBuilder();
    +        StringBuilder body = new StringBuilder(bodySize * BODY_LINE.length());
             for (int i = 0; i < bodySize; i++) {
                 body.append(BODY_LINE);
             }
    

    src/main/java/longcat/LongcatFactoryImpl.java
    --- a/src/main/java/longcat/LongcatFactoryImpl.java
    +++ b/src/main/java/longcat/LongcatFactoryImpl.java
    @@ -7,6 +7,19 @@ public class LongcatFactoryImpl implements LongcatFactory {
         }
     
         public Longcat createLongcat(int length, LengthUnit unit) {
    -        return null;
    +        int totalLines = LengthUnit.LINES.from(length, unit);
    +        int nonBodyLines = lineCount(Longcat.HEAD_LINES + Longcat.FEET_LINES);
    +        return new Longcat(totalLines - nonBodyLines);
    +    }
    +
    +    static int lineCount(String s) {
    +        int lines = 0;
    +        for (int i = 0; i < s.length(); i++) {
    +            char c = s.charAt(i);
    +            if (c == '\n') {
    +                lines++;
    +            }
    +        }
    +        return lines;
         }
     }
    

    src/test/java/longcat/LongcatFactoryTest.java
    --- a/src/test/java/longcat/LongcatFactoryTest.java
    +++ b/src/test/java/longcat/LongcatFactoryTest.java
    @@ -25,4 +25,19 @@ public class LongcatFactoryTest extends TestCase {
             Longcat longcat = factory.createLongcat(2);
             assertEquals(Longcat.HEAD_LINES + longcat.getBody() + Longcat.FEET_LINES, longcat.toString());
         }
    +
    +    public void test__Longcat_length_specified_in_meters() {
    +        Longcat longcat = factory.createLongcat(1, LengthUnit.METERS);
    +        int lines = LongcatFactoryImpl.lineCount(longcat.toString());
    +        assertEquals(LengthUnit.LINES.from(1, LengthUnit.METERS), lines);
    +    }
    +
    +    public void test__Too_short_longcat() {
    +        try {
    +            factory.createLongcat(0, LengthUnit.METERS);
    +            fail();
    +        } catch (IllegalArgumentException e) {
    +            assertEquals("Longcat can not be that short!", e.getMessage());
    +        }
    +    }
     }
    

    Commit them with the message: "Specifying Longcat length with natural length units"

  7. Push the changes to the central repository.

    Sadly, the commit will fail. The Robot decided to add one more useful length unit just before your commit.

    Pull the latest changes. Use rebase so that your commit "Specifying Longcat length with natural length units" will be last in the commit history.

    The changes in your commit conflict with those made by the Robot. Resolve the conflicts manually.

    Push the changes to the central repository.

    If everything went right, the Robot will do after you a series of commits, of which the last one is "Release 1.0". If you got this far, you have finished the project work and you may spend the rest of the evening relaxing by watching a movie. :-) Also remember to do the SVN project work.