Coverage Report - org.apache.maven.scm.provider.jazz.command.changelog.JazzListChangesetConsumer
 
Classes in this File Line Coverage Branch Coverage Complexity
JazzListChangesetConsumer
78 %
96/122
68 %
51/74
6,5
 
 1  
 package org.apache.maven.scm.provider.jazz.command.changelog;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  * http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import org.apache.maven.scm.ChangeFile;
 23  
 import org.apache.maven.scm.ChangeSet;
 24  
 import org.apache.maven.scm.ScmFileStatus;
 25  
 import org.apache.maven.scm.log.ScmLogger;
 26  
 import org.apache.maven.scm.provider.ScmProviderRepository;
 27  
 import org.apache.maven.scm.provider.jazz.command.consumer.AbstractRepositoryConsumer;
 28  
 import org.apache.regexp.RE;
 29  
 import org.apache.regexp.RESyntaxException;
 30  
 
 31  
 import java.util.ArrayList;
 32  
 import java.util.Calendar;
 33  
 import java.util.Date;
 34  
 import java.util.List;
 35  
 import java.util.Locale;
 36  
 
 37  
 /**
 38  
  * Consume the output of the scm command for the "list changesets" operation.
 39  
  * <p/>
 40  
  * This parses the contents of the output and uses it to fill in the remaining
 41  
  * information in the <code>entries</code> list.
 42  
  *
 43  
  * @author <a href="mailto:ChrisGWarp@gmail.com">Chris Graham</a>
 44  
  */
 45  
 public class JazzListChangesetConsumer
 46  
     extends AbstractRepositoryConsumer
 47  
 {
 48  
 //Change sets:
 49  
 //  (1589)  ---$ Deb "[maven-release-plugin] prepare for next development iteration"
 50  
 //    Component: (1158) "GPDB"
 51  
 //    Modified: Feb 25, 2012 10:15 PM (Yesterday)
 52  
 //    Changes:
 53  
 //      ---c- (1170) \GPDB\GPDBEAR\pom.xml
 54  
 //      ---c- (1171) \GPDB\GPDBResources\pom.xml
 55  
 //      ---c- (1167) \GPDB\GPDBWeb\pom.xml
 56  
 //      ---c- (1165) \GPDB\pom.xml
 57  
 //  (1585)  ---$ Deb "[maven-release-plugin] prepare release GPDB-1.0.21"
 58  
 //    Component: (1158) "GPDB"
 59  
 //    Modified: Feb 25, 2012 10:13 PM (Yesterday)
 60  
 //    Changes:
 61  
 //      ---c- (1170) \GPDB\GPDBEAR\pom.xml
 62  
 //      ---c- (1171) \GPDB\GPDBResources\pom.xml
 63  
 //      ---c- (1167) \GPDB\GPDBWeb\pom.xml
 64  
 //      ---c- (1165) \GPDB\pom.xml
 65  
 //  (1584)  ---$ Deb "This is my first changeset (2)"
 66  
 //    Component: (1158) "GPDB"
 67  
 //    Modified: Feb 25, 2012 10:13 PM (Yesterday)
 68  
 //  (1583)  ---$ Deb "This is my first changeset (1)"
 69  
 //    Component: (1158) "GPDB"
 70  
 //    Modified: Feb 25, 2012 10:13 PM (Yesterday)
 71  
 //  (1323)  ---$ Deb <No comment>
 72  
 //    Component: (1158) "GPDB"
 73  
 //    Modified: Feb 24, 2012 11:04 PM (Last Week)
 74  
 //    Changes:
 75  
 //      ---c- (1170) \GPDB\GPDBEAR\pom.xml
 76  
 //      ---c- (1171) \GPDB\GPDBResources\pom.xml
 77  
 //      ---c- (1167) \GPDB\GPDBWeb\pom.xml
 78  
 //      ---c- (1165) \GPDB\pom.xml
 79  
 //  (1319)  ---$ Deb <No comment>
 80  
 //    Component: (1158) "GPDB"
 81  
 //    Modified: Feb 24, 2012 11:03 PM (Last Week)
 82  
 //    Changes:
 83  
 //      ---c- (1170) \GPDB\GPDBEAR\pom.xml
 84  
 //      ---c- (1171) \GPDB\GPDBResources\pom.xml
 85  
 //      ---c- (1167) \GPDB\GPDBWeb\pom.xml
 86  
 //      ---c- (1165) \GPDB\pom.xml
 87  
 //
 88  
 // NOTE: If the change sets originate on the current date, the date is not
 89  
 //       displayed, only the time is.
 90  
 // EG:
 91  
 //Change sets:
 92  
 //  (1809)  ---$ Deb "[maven-release-plugin] prepare for next development iteration"
 93  
 //    Component: (1158) "GPDB"
 94  
 //    Modified: 6:20 PM (5 minutes ago)
 95  
 //    Changes:
 96  
 //      ---c- (1170) \GPDB\GPDBEAR\pom.xml
 97  
 //      ---c- (1171) \GPDB\GPDBResources\pom.xml
 98  
 //      ---c- (1167) \GPDB\GPDBWeb\pom.xml
 99  
 //      ---c- (1165) \GPDB\pom.xml
 100  
 //  (1801)  ---$ Deb "[maven-release-plugin] prepare release GPDB-1.0.26"
 101  
 //    Component: (1158) "GPDB"
 102  
 //    Modified: 6:18 PM (10 minutes ago)
 103  
 //    Changes:
 104  
 //      ---c- (1170) \GPDB\GPDBEAR\pom.xml
 105  
 //      ---c- (1171) \GPDB\GPDBResources\pom.xml
 106  
 //      ---c- (1167) \GPDB\GPDBWeb\pom.xml
 107  
 //  (1799)  ---$ Deb <No comment>
 108  
 //    Component: (1158) "GPDB"
 109  
 //    Modified: 6:18 PM (10 minutes ago)
 110  
 //    Changes:
 111  
 //      ---c- (1165) \GPDB\pom.xml
 112  
 //  (1764)  ---$ Deb <No comment>
 113  
 //    Component: (1158) "GPDB"
 114  
 //    Modified: Mar 1, 2012 2:34 PM
 115  
 //    Changes:
 116  
 //      ---c- (1165) \GPDB\pom.xml
 117  
 
 118  
 
 119  
     // State Machine Definitions
 120  
     private static final int STATE_CHANGE_SETS = 0;
 121  
 
 122  
     private static final int STATE_CHANGE_SET = 1;
 123  
 
 124  
     private static final int STATE_COMPONENT = 2;
 125  
 
 126  
     private static final int STATE_MODIFIED = 3;
 127  
 
 128  
     private static final int STATE_CHANGES = 4;
 129  
 
 130  
     // Header definitions. 
 131  
     private static final String HEADER_CHANGE_SETS = "Change sets:";
 132  
 
 133  
     private static final String HEADER_CHANGE_SET = "(";
 134  
 
 135  
     private static final String HEADER_COMPONENT = "Component:";
 136  
 
 137  
     private static final String HEADER_MODIFIED = "Modified:";
 138  
 
 139  
     private static final String HEADER_CHANGES = "Changes:";
 140  
 
 141  
     private static final String JAZZ_TIMESTAMP_PATTERN = "MMM d, yyyy h:mm a";
 142  
     // Actually: DateFormat.getDateTimeInstance( DateFormat.MEDIUM, DateFormat.SHORT );
 143  
 
 144  
     private static final String JAZZ_TIMESTAMP_PATTERN_TIME = "h:mm a";
 145  
     // Only seen when the data = today. Only the time is displayed.
 146  
 
 147  
     //  (1589)  ---$ Deb "[maven-release-plugin] prepare for next development iteration"
 148  
     //  (1585)  ---$ Deb "[maven-release-plugin] prepare release GPDB-1.0.21"
 149  
     private static final String CHANGESET_PATTERN = "\\((\\d+)\\)  (....) (\\w+) (.*)";
 150  
 
 151  
     /**
 152  
      * @see #CHANGESET_PATTERN
 153  
      */
 154  
     private RE changeSetRegExp;
 155  
 
 156  
     //      ---c- (1170) \GPDB\GPDBEAR\pom.xml
 157  
     //      ---c- (1171) \GPDB\GPDBResources\pom.xml
 158  
     //      ---c- (1167) \GPDB\GPDBWeb\pom.xml
 159  
     //      ---c- (1165) \GPDB\pom.xml
 160  
     private static final String CHANGES_PATTERN = "(.....) \\((\\d+)\\) (.*)";
 161  
 
 162  
     /**
 163  
      * @see #CHANGES_PATTERN
 164  
      */
 165  
     private RE changesRegExp;
 166  
 
 167  
 
 168  
     private List<ChangeSet> entries;
 169  
 
 170  
     private final String userDateFormat;
 171  
 
 172  
     // This is incremented at the beginning of every change set line. So we start at -1 (to get zero on first processing)
 173  6
     private int currentChangeSetIndex = -1;
 174  
 
 175  6
     private int currentState = STATE_CHANGE_SETS;
 176  
 
 177  
     /**
 178  
      * Constructor for our "scm list changeset" consumer.
 179  
      *
 180  
      * @param repo    The JazzScmProviderRepository being used.
 181  
      * @param logger  The ScmLogger to use.
 182  
      * @param entries The List of ChangeSet entries that we will populate.
 183  
      */
 184  
     public JazzListChangesetConsumer( ScmProviderRepository repo, ScmLogger logger, List<ChangeSet> entries,
 185  
                                       String userDateFormat )
 186  
     {
 187  6
         super( repo, logger );
 188  6
         this.entries = entries;
 189  6
         this.userDateFormat = userDateFormat;
 190  
 
 191  
         try
 192  
         {
 193  6
             changeSetRegExp = new RE( CHANGESET_PATTERN );
 194  6
             changesRegExp = new RE( CHANGES_PATTERN );
 195  
         }
 196  0
         catch ( RESyntaxException ex )
 197  
         {
 198  0
             throw new RuntimeException(
 199  
                 "INTERNAL ERROR: Could not create regexp to parse jazz scm history output. This shouldn't happen. Something is probably wrong with the oro installation.",
 200  
                 ex );
 201  6
         }
 202  6
     }
 203  
 
 204  
     /**
 205  
      * Process one line of output from the execution of the "scm list changeset" command.
 206  
      *
 207  
      * @param line The line of output from the external command that has been pumped to us.
 208  
      * @see org.codehaus.plexus.util.cli.StreamConsumer#consumeLine(java.lang.String)
 209  
      */
 210  
     public void consumeLine( String line )
 211  
     {
 212  65
         super.consumeLine( line );
 213  
 
 214  
         // Process the "Change sets:" line - do nothing
 215  65
         if ( line.trim().startsWith( HEADER_CHANGE_SETS ) )
 216  
         {
 217  2
             currentState = STATE_CHANGE_SETS;
 218  
         }
 219  
         else
 220  
         {
 221  63
             if ( line.trim().startsWith( HEADER_CHANGE_SET ) )
 222  
             {
 223  10
                 currentState = STATE_CHANGE_SET;
 224  
             }
 225  
             else
 226  
             {
 227  53
                 if ( line.trim().startsWith( HEADER_COMPONENT ) )
 228  
                 {
 229  10
                     currentState = STATE_COMPONENT;
 230  
                 }
 231  
                 else
 232  
                 {
 233  43
                     if ( line.trim().startsWith( HEADER_MODIFIED ) )
 234  
                     {
 235  10
                         currentState = STATE_MODIFIED;
 236  
                     }
 237  
                     else
 238  
                     {
 239  33
                         if ( line.trim().startsWith( HEADER_CHANGES ) )
 240  
                         {
 241  
                             // Note: processChangesLine() will also be passed the "Changes:" line
 242  
                             // So, it needs to be able to deal with that.
 243  
                             // Changes:
 244  
                             //   ---c- (1170) \GPDB\GPDBEAR\pom.xml
 245  
                             //   ---c- (1171) \GPDB\GPDBResources\pom.xml
 246  
                             //   ---c- (1167) \GPDB\GPDBWeb\pom.xml
 247  
                             //   ---c- (1165) \GPDB\pom.xml
 248  8
                             currentState = STATE_CHANGES;
 249  
                         }
 250  
                     }
 251  
                 }
 252  
             }
 253  
         }
 254  
 
 255  65
         switch ( currentState )
 256  
         {
 257  
             case STATE_CHANGE_SETS:
 258  
                 // Nothing to do.
 259  2
                 break;
 260  
 
 261  
             case STATE_CHANGE_SET:
 262  10
                 processChangeSetLine( line );
 263  10
                 break;
 264  
 
 265  
             case STATE_COMPONENT:
 266  
                 // Nothing to do. Not used (Yet?)
 267  10
                 break;
 268  
 
 269  
             case STATE_MODIFIED:
 270  10
                 processModifiedLine( line );
 271  10
                 break;
 272  
 
 273  
             case STATE_CHANGES:
 274  33
                 processChangesLine( line );
 275  
                 break;
 276  
         }
 277  
 
 278  65
     }
 279  
 
 280  
     private void processChangeSetLine( String line )
 281  
     {
 282  
         // Process the headerless change set line - starts with a '(', eg:
 283  
         // (1589)  ---$ Deb "[maven-release-plugin] prepare for next development iteration"
 284  
         // (1585)  ---$ Deb "[maven-release-plugin] prepare release GPDB-1.0.21"
 285  10
         if ( changeSetRegExp.match( line ) )
 286  
         {
 287  
             // This is the only place this gets incremented.
 288  
             // It starts at -1, and on first execution is incremented to 0 - which is correct.
 289  10
             currentChangeSetIndex++;
 290  10
             ChangeSet currentChangeSet = entries.get( currentChangeSetIndex );
 291  
 
 292  
             // Init the file of files, so it is not null, but it can be empty!
 293  10
             List<ChangeFile> files = new ArrayList<ChangeFile>();
 294  10
             currentChangeSet.setFiles( files );
 295  
 
 296  10
             String changesetAlias = changeSetRegExp.getParen( 1 );
 297  10
             String changeFlags = changeSetRegExp.getParen( 2 );     // Not used.
 298  10
             String author = changeSetRegExp.getParen( 3 );
 299  10
             String comment = changeSetRegExp.getParen( 4 );
 300  
 
 301  10
             if ( getLogger().isDebugEnabled() )
 302  
             {
 303  0
                 getLogger().debug( "  Parsing ChangeSet Line : " + line );
 304  0
                 getLogger().debug( "    changesetAlias : " + changesetAlias );
 305  0
                 getLogger().debug( "    changeFlags    : " + changeFlags );
 306  0
                 getLogger().debug( "    author         : " + author );
 307  0
                 getLogger().debug( "    comment        : " + comment );
 308  
             }
 309  
 
 310  
             // Sanity check.
 311  10
             if ( currentChangeSet.getRevision() != null && !currentChangeSet.getRevision().equals( changesetAlias ) )
 312  
             {
 313  0
                 getLogger().warn( "Warning! The indexes appear to be out of sequence! " +
 314  
                                       "For currentChangeSetIndex = " + currentChangeSetIndex + ", we got '" +
 315  
                                       changesetAlias + "' and not '" + currentChangeSet.getRevision()
 316  
                                       + "' as expected." );
 317  
             }
 318  
 
 319  10
             comment = stripDelimiters( comment );
 320  10
             currentChangeSet.setAuthor( author );
 321  10
             currentChangeSet.setComment( comment );
 322  
         }
 323  10
     }
 324  
 
 325  
     private void processModifiedLine( String line )
 326  
     {
 327  
         // Process the "Modified: ..." line, eg:
 328  
         // Modified: Feb 25, 2012 10:15 PM (Yesterday)
 329  
         // Modified: Feb 25, 2012 10:13 PM (Yesterday)
 330  
         // Modified: Feb 24, 2012 11:03 PM (Last Week)
 331  
         // Modified: Mar 1, 2012 2:34 PM
 332  
         // Modified: 6:20 PM (5 minutes ago)
 333  
 
 334  10
         if ( getLogger().isDebugEnabled() )
 335  
         {
 336  0
             getLogger().debug( "  Parsing Modified Line : " + line );
 337  
         }
 338  
 
 339  10
         int colonPos = line.indexOf( ":" );
 340  10
         int parenPos = line.indexOf( "(" );
 341  
 
 342  10
         String date = null;
 343  
 
 344  10
         if ( colonPos != -1 && parenPos != -1 )
 345  
         {
 346  9
             date = line.substring( colonPos + 2, parenPos - 1 );
 347  
         }
 348  
         else
 349  
         {
 350  1
             if ( colonPos != -1 && parenPos == -1 )
 351  
             {
 352  
                 // No trailing bracket
 353  1
                 date = line.substring( colonPos + 2 );
 354  
             }
 355  
         }
 356  
 
 357  10
         if ( date != null )
 358  
         {
 359  10
             Date changesetDate = parseDate( date.toString(), userDateFormat, JAZZ_TIMESTAMP_PATTERN );
 360  
             // try again forcing en locale
 361  10
             if ( changesetDate == null )
 362  
             {
 363  10
                 changesetDate = parseDate( date.toString(), userDateFormat, JAZZ_TIMESTAMP_PATTERN, Locale.ENGLISH );
 364  
             }
 365  10
             if ( changesetDate == null )
 366  
             {
 367  
                 // changesetDate will be null when the date is not given, it only has just the time. The date is today.
 368  3
                 changesetDate = parseDate( date.toString(), userDateFormat, JAZZ_TIMESTAMP_PATTERN_TIME );
 369  
                 // Get today's time/date. Used to get the date.
 370  3
                 Calendar today = Calendar.getInstance();
 371  
                 // Get a working one.
 372  3
                 Calendar changesetCal = Calendar.getInstance();
 373  
                 // Set the date/time. Used to set the time.
 374  3
                 changesetCal.setTimeInMillis( changesetDate.getTime() );
 375  
                 // Now set the date (today).
 376  3
                 changesetCal.set( today.get( Calendar.YEAR ), today.get( Calendar.MONTH ),
 377  
                                   today.get( Calendar.DAY_OF_MONTH ) );
 378  
                 // Now get the date of the combined results.
 379  3
                 changesetDate = changesetCal.getTime();
 380  
             }
 381  
 
 382  10
             if ( getLogger().isDebugEnabled() )
 383  
             {
 384  0
                 getLogger().debug( "    date           : " + date );
 385  0
                 getLogger().debug( "    changesetDate  : " + changesetDate );
 386  
             }
 387  
 
 388  10
             ChangeSet currentChangeSet = entries.get( currentChangeSetIndex );
 389  10
             currentChangeSet.setDate( changesetDate );
 390  
         }
 391  10
     }
 392  
 
 393  
     private void processChangesLine( String line )
 394  
     {
 395  
         // Process the changes line, eg:
 396  
         //      ---c- (1170) \GPDB\GPDBEAR\pom.xml
 397  
         //      ---c- (1171) \GPDB\GPDBResources\pom.xml
 398  
         //      ---c- (1167) \GPDB\GPDBWeb\pom.xml
 399  
         //      ---c- (1165) \GPDB\pom.xml
 400  33
         if ( changesRegExp.match( line ) )
 401  
         {
 402  25
             ChangeSet currentChangeSet = entries.get( currentChangeSetIndex );
 403  
 
 404  25
             String changeFlags = changesRegExp.getParen( 1 );     // Not used.
 405  25
             String fileAlias = changesRegExp.getParen( 2 );
 406  25
             String file = changesRegExp.getParen( 3 );
 407  
 
 408  25
             if ( getLogger().isDebugEnabled() )
 409  
             {
 410  0
                 getLogger().debug( "  Parsing Changes Line : " + line );
 411  0
                 getLogger().debug(
 412  
                     "    changeFlags    : " + changeFlags + " Translated to : " + parseFileChangeState( changeFlags ) );
 413  0
                 getLogger().debug( "    filetAlias     : " + fileAlias );
 414  0
                 getLogger().debug( "    file           : " + file );
 415  
             }
 416  
 
 417  25
             ChangeFile changeFile = new ChangeFile( file );
 418  25
             ScmFileStatus status = parseFileChangeState( changeFlags );
 419  25
             changeFile.setAction( status );
 420  25
             currentChangeSet.getFiles().add( changeFile );
 421  
         }
 422  33
     }
 423  
 
 424  
     /**
 425  
      * String the leading/trailing ", < and > from the text.
 426  
      *
 427  
      * @param text The text to process.
 428  
      * @return The striped text.
 429  
      */
 430  
     protected String stripDelimiters( String text )
 431  
     {
 432  17
         if ( text == null )
 433  
         {
 434  0
             return null;
 435  
         }
 436  17
         String workingText = text;
 437  17
         if ( workingText.startsWith( "\"" ) || workingText.startsWith( "<" ) )
 438  
         {
 439  14
             workingText = workingText.substring( 1 );
 440  
         }
 441  17
         if ( workingText.endsWith( "\"" ) || workingText.endsWith( ">" ) )
 442  
         {
 443  14
             workingText = workingText.substring( 0, workingText.length() - 1 );
 444  
         }
 445  
 
 446  17
         return workingText;
 447  
     }
 448  
 
 449  
     /**
 450  
      * Parse the change state file flags from Jazz and map them to the maven SCM ones.
 451  
      * <p/>
 452  
      * "----" Character positions 0-3.
 453  
      * <p/>
 454  
      * [0] is '*' or '-'    Indicates that this is the current change set ('*') or not ('-').   STATE_CHANGESET_CURRENT
 455  
      * [1] is '!' or '-'    Indicates a Potential Conflict ('!') or not ('-').                  STATE_POTENTIAL_CONFLICT
 456  
      * [2] is '#' or '-'    Indicates a Conflict ('#') or not ('-').                            STATE_CONFLICT
 457  
      * [3] is '@' or '$'    Indicates whether the changeset is active ('@') or not ('$').       STATE_CHANGESET_ACTIVE
 458  
      *
 459  
      * @param state The 5 character long state string
 460  
      * @return The ScmFileStatus value.
 461  
      */
 462  
     private ScmFileStatus parseChangeSetChangeState( String state )
 463  
     {
 464  0
         if ( state.length() != 4 )
 465  
         {
 466  0
             throw new IllegalArgumentException( "Change State string must be 4 chars long!" );
 467  
         }
 468  
 
 469  
         // This is not used, but is here for potential future usage and for documentation purposes.
 470  0
         return ScmFileStatus.UNKNOWN;
 471  
     }
 472  
 
 473  
     /**
 474  
      * Parse the change state file flags from Jazz and map them to the maven SCM ones.
 475  
      * <p/>
 476  
      * "-----" Character positions 0-4. The default is '-'.
 477  
      * <p/>
 478  
      * [0] is '-' or '!'    Indicates a Potential Conflict. STATE_POTENTIAL_CONFLICT
 479  
      * [1] is '-' or '#'    Indicates a Conflict.           STATE_CONFLICT
 480  
      * [2] is '-' or 'a'    Indicates an addition.          STATE_ADD
 481  
      * or 'd'    Indicates a deletion.           STATE_DELETE
 482  
      * or 'm'    Indicates a move.               STATE_MOVE
 483  
      * [3] is '-' or 'c'    Indicates a content change.     STATE_CONTENT_CHANGE
 484  
      * [4] is '-' or 'p'    Indicates a property change.    STATE_PROPERTY_CHANGE
 485  
      * <p/>
 486  
      * NOTE: [3] and [4] can only be set it [2] is NOT 'a' or 'd'.
 487  
      *
 488  
      * @param state The 5 character long state string
 489  
      * @return The SCMxxx value.
 490  
      */
 491  
     private ScmFileStatus parseFileChangeState( String state )
 492  
     {
 493  25
         if ( state.length() != 5 )
 494  
         {
 495  0
             throw new IllegalArgumentException( "Change State string must be 5 chars long!" );
 496  
         }
 497  
 
 498  
         // NOTE: We have an impedance mismatch here. The Jazz file change flags represent
 499  
         // many different states. However, we can only return *ONE* ScmFileStatus value,
 500  
         // so we need to be careful as to the precedence that we give to them.
 501  
 
 502  25
         ScmFileStatus status = ScmFileStatus.UNKNOWN;   // Probably not a valid initial default value.
 503  
 
 504  
         // [0] is '-' or '!'    Indicates a Potential Conflict. STATE_POTENTIAL_CONFLICT
 505  25
         if ( state.charAt( 0 ) == '!' )
 506  
         {
 507  0
             status = ScmFileStatus.CONFLICT;
 508  
         }
 509  
         // [1] is '-' or '#'    Indicates a Conflict.           STATE_CONFLICT
 510  25
         if ( state.charAt( 1 ) == '#' )
 511  
         {
 512  0
             status = ScmFileStatus.CONFLICT;
 513  
         }
 514  
 
 515  
         // [2] is '-' or 'a'    Indicates an addition.          STATE_ADD
 516  
         //            or 'd'    Indicates a deletion.           STATE_DELETE
 517  
         //            or 'm'    Indicates a move.               STATE_MOVE
 518  25
         if ( state.charAt( 2 ) == 'a' )
 519  
         {
 520  0
             status = ScmFileStatus.ADDED;
 521  
         }
 522  
         else
 523  
         {
 524  25
             if ( state.charAt( 2 ) == 'd' )
 525  
             {
 526  0
                 status = ScmFileStatus.DELETED;
 527  
             }
 528  
             else
 529  
             {
 530  25
                 if ( state.charAt( 2 ) == 'm' )
 531  
                 {
 532  0
                     status = ScmFileStatus.RENAMED;     // Has been renamed or moved.
 533  
                 }
 534  
 
 535  
                 // [3] is '-' or 'c'    Indicates a content change.     STATE_CONTENT_CHANGE
 536  25
                 if ( state.charAt( 3 ) == 'c' )
 537  
                 {
 538  25
                     status = ScmFileStatus.MODIFIED;    // The file has been modified in the working tree.
 539  
                 }
 540  
 
 541  
                 // [4] is '-' or 'p'    Indicates a property change.    STATE_PROPERTY_CHANGE
 542  25
                 if ( state.charAt( 4 ) == 'p' )
 543  
                 {
 544  0
                     status =
 545  
                         ScmFileStatus.MODIFIED;    // ScmFileStatus has no concept of property or meta data changes.
 546  
                 }
 547  
             }
 548  
         }
 549  
 
 550  25
         return status;
 551  
     }
 552  
 }