001package org.apache.maven.scm.provider.cvslib; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.File; 023import java.io.IOException; 024import java.util.ArrayList; 025import java.util.List; 026 027import org.apache.maven.scm.CommandParameters; 028import org.apache.maven.scm.ScmException; 029import org.apache.maven.scm.ScmFileSet; 030import org.apache.maven.scm.ScmResult; 031import org.apache.maven.scm.ScmTagParameters; 032import org.apache.maven.scm.command.Command; 033import org.apache.maven.scm.command.add.AddScmResult; 034import org.apache.maven.scm.command.blame.BlameScmResult; 035import org.apache.maven.scm.command.branch.BranchScmResult; 036import org.apache.maven.scm.command.changelog.ChangeLogScmResult; 037import org.apache.maven.scm.command.checkin.CheckInScmResult; 038import org.apache.maven.scm.command.checkout.CheckOutScmResult; 039import org.apache.maven.scm.command.diff.DiffScmResult; 040import org.apache.maven.scm.command.export.ExportScmResult; 041import org.apache.maven.scm.command.list.ListScmResult; 042import org.apache.maven.scm.command.login.LoginScmResult; 043import org.apache.maven.scm.command.mkdir.MkdirScmResult; 044import org.apache.maven.scm.command.remove.RemoveScmResult; 045import org.apache.maven.scm.command.status.StatusScmResult; 046import org.apache.maven.scm.command.tag.TagScmResult; 047import org.apache.maven.scm.command.update.UpdateScmResult; 048import org.apache.maven.scm.provider.AbstractScmProvider; 049import org.apache.maven.scm.provider.ScmProviderRepository; 050import org.apache.maven.scm.provider.cvslib.repository.CvsScmProviderRepository; 051import org.apache.maven.scm.repository.ScmRepositoryException; 052import org.apache.maven.scm.repository.UnknownRepositoryStructure; 053import org.codehaus.plexus.util.FileUtils; 054import org.codehaus.plexus.util.StringUtils; 055 056/** 057 * @author <a href="mailto:evenisse@apache.org">Emmanuel Venisse </a> 058 * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a> 059 * 060 */ 061public abstract class AbstractCvsScmProvider 062 extends AbstractScmProvider 063{ 064 /** ext transport method */ 065 public static final String TRANSPORT_EXT = "ext"; 066 067 /** local transport method */ 068 public static final String TRANSPORT_LOCAL = "local"; 069 070 /** lserver transport method */ 071 public static final String TRANSPORT_LSERVER = "lserver"; 072 073 /** pserver transport method */ 074 public static final String TRANSPORT_PSERVER = "pserver"; 075 076 /** sspi transport method */ 077 public static final String TRANSPORT_SSPI = "sspi"; 078 079 // ---------------------------------------------------------------------- 080 // 081 // ---------------------------------------------------------------------- 082 083 /** 084 * The current ScmUrlParserResult 085 * 086 * @since 1.1.1 087 */ 088 public static class ScmUrlParserResult 089 { 090 private List<String> messages; 091 092 private ScmProviderRepository repository; 093 094 public ScmUrlParserResult() 095 { 096 messages = new ArrayList<String>(); 097 } 098 099 /** 100 * @return the messages 101 */ 102 public List<String> getMessages() 103 { 104 return messages; 105 } 106 107 /** 108 * @param messages the messages to set 109 */ 110 public void setMessages( List<String> messages ) 111 { 112 this.messages = messages; 113 } 114 115 /** 116 * @return the repository 117 */ 118 public ScmProviderRepository getRepository() 119 { 120 return repository; 121 } 122 123 /** 124 * @param repository the repository to set 125 */ 126 public void setRepository( ScmProviderRepository repository ) 127 { 128 this.repository = repository; 129 } 130 131 /** 132 * Reset messages. 133 */ 134 public void resetMessages() 135 { 136 this.messages = new ArrayList<String>(); 137 } 138 } 139 140 // ---------------------------------------------------------------------- 141 // ScmProvider Implementation 142 // ---------------------------------------------------------------------- 143 144 /** {@inheritDoc} */ 145 public String getScmSpecificFilename() 146 { 147 return "CVS"; 148 } 149 150 /* From the Cederqvist: 151 * 152 * "Tag names must start with an uppercase or lowercase letter and can 153 * contain uppercase and lowercase letters, digits, `-', and `_'. The 154 * two tag names BASE and HEAD are reserved for use by CVS. It is expected 155 * that future names which are special to CVS will be specially named, 156 * for example by starting with `.', rather than being named analogously 157 * to BASE and HEAD, to avoid conflicts with actual tag names." 158 */ 159 /** {@inheritDoc} */ 160 public String sanitizeTagName( String arg0 ) 161 { 162 if ( validateTagName( arg0 ) ) 163 { 164 return arg0; 165 } 166 167 if ( arg0.equals( "HEAD" ) || arg0.equals( "BASE" ) || !arg0.matches( "[A-Za-z].*" ) ) 168 /* we don't even bother to sanitize these, they're just silly */ 169 { 170 throw new RuntimeException( 171 "Unable to sanitize tag " + arg0 + ": must begin with a letter" + "and not be HEAD or BASE" ); 172 } 173 174 /* swap all illegal characters for a _ */ 175 return arg0.replaceAll( "[^A-Za-z0-9_-]", "_" ); 176 } 177 178 /** {@inheritDoc} */ 179 public boolean validateTagName( String arg0 ) 180 { 181 return ( arg0.matches( "[A-Za-z][A-Za-z0-9_-]*" ) && !arg0.equals( "HEAD" ) && !arg0.equals( "BASE" ) ); 182 } 183 184 /** {@inheritDoc} */ 185 public ScmProviderRepository makeProviderScmRepository( String scmSpecificUrl, char delimiter ) 186 throws ScmRepositoryException 187 { 188 ScmUrlParserResult result = parseScmUrl( scmSpecificUrl, delimiter ); 189 190 if ( result.getMessages().size() > 0 ) 191 { 192 throw new ScmRepositoryException( "The scm url is invalid.", result.getMessages() ); 193 } 194 195 return result.getRepository(); 196 } 197 198 /** {@inheritDoc} */ 199 public ScmProviderRepository makeProviderScmRepository( File path ) 200 throws ScmRepositoryException, UnknownRepositoryStructure 201 { 202 if ( path == null ) 203 { 204 throw new NullPointerException( "Path argument is null" ); 205 } 206 207 if ( !path.isDirectory() ) 208 { 209 throw new ScmRepositoryException( path.getAbsolutePath() + " isn't a valid directory." ); 210 } 211 212 File cvsDirectory = new File( path, "CVS" ); 213 214 if ( !cvsDirectory.exists() ) 215 { 216 throw new ScmRepositoryException( path.getAbsolutePath() + " isn't a cvs checkout directory." ); 217 } 218 219 File cvsRootFile = new File( cvsDirectory, "Root" ); 220 221 File moduleFile = new File( cvsDirectory, "Repository" ); 222 223 String cvsRoot; 224 225 String module; 226 227 try 228 { 229 cvsRoot = FileUtils.fileRead( cvsRootFile ).trim().substring( 1 ); 230 } 231 catch ( IOException e ) 232 { 233 throw new ScmRepositoryException( "Can't read " + cvsRootFile.getAbsolutePath() ); 234 } 235 try 236 { 237 module = FileUtils.fileRead( moduleFile ).trim(); 238 } 239 catch ( IOException e ) 240 { 241 throw new ScmRepositoryException( "Can't read " + moduleFile.getAbsolutePath() ); 242 } 243 244 return makeProviderScmRepository( cvsRoot + ":" + module, ':' ); 245 } 246 247 /** {@inheritDoc} */ 248 public List<String> validateScmUrl( String scmSpecificUrl, char delimiter ) 249 { 250 ScmUrlParserResult result = parseScmUrl( scmSpecificUrl, delimiter ); 251 252 return result.getMessages(); 253 } 254 255 /** {@inheritDoc} */ 256 public String getScmType() 257 { 258 return "cvs"; 259 } 260 261 /** {@inheritDoc} */ 262 public AddScmResult add( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 263 throws ScmException 264 { 265 return (AddScmResult) executeCommand( getAddCommand(), repository, fileSet, parameters ); 266 } 267 268 /** {@inheritDoc} */ 269 public BranchScmResult branch( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 270 throws ScmException 271 { 272 return (BranchScmResult) executeCommand( getBranchCommand(), repository, fileSet, parameters ); 273 } 274 275 /** {@inheritDoc} */ 276 protected BlameScmResult blame( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 277 throws ScmException 278 { 279 return (BlameScmResult) executeCommand( getBlameCommand(), repository, fileSet, parameters ); 280 } 281 282 /** {@inheritDoc} */ 283 public ChangeLogScmResult changelog( ScmProviderRepository repository, ScmFileSet fileSet, 284 CommandParameters parameters ) 285 throws ScmException 286 { 287 return (ChangeLogScmResult) executeCommand( getChangeLogCommand(), repository, fileSet, parameters ); 288 } 289 290 /** {@inheritDoc} */ 291 public CheckInScmResult checkin( ScmProviderRepository repository, ScmFileSet fileSet, 292 CommandParameters parameters ) 293 throws ScmException 294 { 295 return (CheckInScmResult) executeCommand( getCheckInCommand(), repository, fileSet, parameters ); 296 } 297 298 /** {@inheritDoc} */ 299 public CheckOutScmResult checkout( ScmProviderRepository repository, ScmFileSet fileSet, 300 CommandParameters parameters ) 301 throws ScmException 302 { 303 return (CheckOutScmResult) executeCommand( getCheckOutCommand(), repository, fileSet, parameters ); 304 } 305 306 /** {@inheritDoc} */ 307 public DiffScmResult diff( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 308 throws ScmException 309 { 310 return (DiffScmResult) executeCommand( getDiffCommand(), repository, fileSet, parameters ); 311 } 312 313 /** {@inheritDoc} */ 314 protected ExportScmResult export( ScmProviderRepository repository, ScmFileSet fileSet, 315 CommandParameters parameters ) 316 throws ScmException 317 { 318 return (ExportScmResult) executeCommand( getExportCommand(), repository, fileSet, parameters ); 319 } 320 321 /** {@inheritDoc} */ 322 public LoginScmResult login( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 323 throws ScmException 324 { 325 return (LoginScmResult) executeCommand( getLoginCommand(), repository, fileSet, parameters ); 326 } 327 328 /** {@inheritDoc} */ 329 public RemoveScmResult remove( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 330 throws ScmException 331 { 332 return (RemoveScmResult) executeCommand( getRemoveCommand(), repository, fileSet, parameters ); 333 } 334 335 /** {@inheritDoc} */ 336 public StatusScmResult status( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 337 throws ScmException 338 { 339 return (StatusScmResult) executeCommand( getStatusCommand(), repository, fileSet, parameters ); 340 } 341 342 /** {@inheritDoc} */ 343 public TagScmResult tag( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 344 throws ScmException 345 { 346 return (TagScmResult) executeCommand( getTagCommand(), repository, fileSet, parameters ); 347 } 348 349 protected TagScmResult tag( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters, 350 ScmTagParameters scmParameters ) 351 throws ScmException 352 { 353 return (TagScmResult) getTagCommand().execute( repository, fileSet, parameters ); 354 } 355 356 357 /** {@inheritDoc} */ 358 public UpdateScmResult update( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 359 throws ScmException 360 { 361 return (UpdateScmResult) executeCommand( getUpdateCommand(), repository, fileSet, parameters ); 362 } 363 364 /** {@inheritDoc} */ 365 protected ListScmResult list( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 366 throws ScmException 367 { 368 return (ListScmResult) executeCommand( getListCommand(), repository, fileSet, parameters ); 369 } 370 371 /** {@inheritDoc} */ 372 protected MkdirScmResult mkdir( ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters ) 373 throws ScmException 374 { 375 return (MkdirScmResult) executeCommand( getMkdirCommand(), repository, fileSet, parameters ); 376 } 377 378 /** 379 * @param basedir not null 380 * @param f not null 381 * @return the relative path 382 * @throws ScmException if any 383 * @throws IOException if any 384 */ 385 public static String getRelativePath( File basedir, File f ) 386 throws ScmException, IOException 387 { 388 File fileOrDir = getAbsoluteFilePath( f ); 389 390 if ( !fileOrDir.getPath().startsWith( basedir.getPath() ) ) 391 { 392 throw new ScmException( fileOrDir.getPath() + " was not contained in " + basedir.getPath() ); 393 } 394 395 return fileOrDir.getPath().substring( basedir.getPath().length() + 1, fileOrDir.getPath().length() ); 396 } 397 398 // ---------------------------------------------------------------------- 399 // Protected methods 400 // ---------------------------------------------------------------------- 401 402 protected ScmUrlParserResult parseScmUrl( String scmSpecificUrl, char delimiter ) 403 { 404 ScmUrlParserResult result = new ScmUrlParserResult(); 405 406 String[] tokens = StringUtils.split( scmSpecificUrl, Character.toString( delimiter ) ); 407 408 if ( tokens.length < 3 ) 409 { 410 result.getMessages().add( "The connection string contains too few tokens." ); 411 412 return result; 413 } 414 415 String cvsroot; 416 417 String transport = tokens[0]; 418 419 if ( transport.equalsIgnoreCase( TRANSPORT_LOCAL ) ) 420 { 421 // use the local repository directory eg. '/home/cvspublic' 422 cvsroot = tokens[1]; 423 } 424 else if ( transport.equalsIgnoreCase( TRANSPORT_PSERVER ) || transport.equalsIgnoreCase( TRANSPORT_LSERVER ) 425 || transport.equalsIgnoreCase( TRANSPORT_EXT ) || transport.equalsIgnoreCase( TRANSPORT_SSPI ) ) 426 { 427 if ( tokens.length != 4 && transport.equalsIgnoreCase( TRANSPORT_EXT ) ) 428 { 429 result.getMessages().add( "The connection string contains too few tokens." ); 430 431 return result; 432 } 433 else if ( ( tokens.length < 4 || tokens.length > 6 ) && transport.equalsIgnoreCase( TRANSPORT_PSERVER ) ) 434 { 435 result.getMessages().add( "The connection string contains too few tokens." ); 436 437 return result; 438 } 439 else if ( tokens.length < 4 || tokens.length > 5 && !transport.equalsIgnoreCase( TRANSPORT_PSERVER ) ) 440 { 441 result.getMessages().add( "The connection string contains too few tokens." ); 442 443 return result; 444 } 445 else if ( tokens.length < 4 || tokens.length > 5 && transport.equalsIgnoreCase( TRANSPORT_SSPI ) ) 446 { 447 result.getMessages().add( "The connection string contains too few tokens." ); 448 449 return result; 450 } 451 452 if ( transport.equalsIgnoreCase( TRANSPORT_LSERVER ) ) 453 { 454 //create the cvsroot as the local socket cvsroot 455 cvsroot = tokens[1] + ":" + tokens[2]; 456 } 457 else 458 { 459 //create the cvsroot as the remote cvsroot 460 if ( tokens.length == 4 ) 461 { 462 cvsroot = ":" + transport + ":" + tokens[1] + ":" + tokens[2]; 463 } 464 else 465 { 466 cvsroot = ":" + transport + ":" + tokens[1] + ":" + tokens[2] + ":" + tokens[3]; 467 } 468 } 469 } 470 else 471 { 472 result.getMessages().add( "Unknown transport: " + transport ); 473 474 return result; 475 } 476 477 String user = null; 478 479 String password = null; 480 481 String host = null; 482 483 String path = null; 484 485 String module = null; 486 487 int port = -1; 488 489 if ( transport.equalsIgnoreCase( TRANSPORT_PSERVER ) ) 490 { 491 // set default port, it's necessary for checking entries in .cvspass 492 port = 2401; 493 494 if ( tokens.length == 4 ) 495 { 496 //pserver:[username@]host:path:module 497 String userhost = tokens[1]; 498 499 int index = userhost.indexOf( '@' ); 500 501 if ( index == -1 ) 502 { 503 host = userhost; 504 } 505 else 506 { 507 user = userhost.substring( 0, index ); 508 509 host = userhost.substring( index + 1 ); 510 } 511 512 path = tokens[2]; 513 514 module = tokens[3]; 515 } 516 else if ( tokens.length == 6 ) 517 { 518 //pserver:username:password@host:port:path:module 519 user = tokens[1]; 520 521 String passhost = tokens[2]; 522 523 int index = passhost.indexOf( '@' ); 524 525 if ( index == -1 ) 526 { 527 result.getMessages() 528 .add( "The user_password_host part must be on the form: <username>:<password>@<hostname>." ); 529 530 return result; 531 } 532 533 password = passhost.substring( 0, index ); 534 535 host = passhost.substring( index + 1 ); 536 537 port = Integer.valueOf( tokens[3] ).intValue(); 538 539 path = tokens[4]; 540 541 module = tokens[5]; 542 } 543 else 544 { 545 //tokens.length == 5 546 if ( tokens[1].indexOf( '@' ) > 0 ) 547 { 548 //pserver:username@host:port:path:module 549 String userhost = tokens[1]; 550 551 int index = userhost.indexOf( '@' ); 552 553 user = userhost.substring( 0, index ); 554 555 host = userhost.substring( index + 1 ); 556 557 port = new Integer( tokens[2] ).intValue(); 558 } 559 else if ( tokens[2].indexOf( '@' ) >= 0 ) 560 { 561 //pserver:username:password@host:path:module 562 //<username>:<password>@<hostname> 563 user = tokens[1]; 564 565 String passhost = tokens[2]; 566 567 int index = passhost.indexOf( '@' ); 568 569 password = passhost.substring( 0, index ); 570 571 host = passhost.substring( index + 1 ); 572 } 573 else 574 { 575 //pserver:host:port:path:module 576 try 577 { 578 port = new Integer( tokens[2] ).intValue(); 579 } 580 catch ( Exception e ) 581 { 582 //incorrect 583 result.getMessages().add( "Your scm url is invalid." ); 584 585 return result; 586 } 587 588 host = tokens[1]; 589 } 590 591 path = tokens[3]; 592 593 module = tokens[4]; 594 } 595 596 String userHost = host; 597 598 if ( user != null ) 599 { 600 userHost = user + "@" + host; 601 } 602 603 // cvsroot format is :pserver:[user@]host:[port]path 604 cvsroot = ":" + transport + ":" + userHost + ":"; 605 606 if ( port != -1 ) 607 { 608 cvsroot += port; 609 } 610 611 cvsroot += path; 612 } 613 else if ( transport.equalsIgnoreCase( TRANSPORT_SSPI ) ) 614 { 615 //sspi:[username@]host:[port]path:module 616 String userhost = tokens[1]; 617 618 int index = userhost.indexOf( '@' ); 619 620 if ( index == -1 ) 621 { 622 user = ""; 623 624 host = userhost; 625 } 626 else 627 { 628 user = userhost.substring( 0, index ); 629 630 host = userhost.substring( index + 1 ); 631 } 632 633 // no port specified 634 if ( tokens.length == 4 ) 635 { 636 path = tokens[2]; 637 module = tokens[3]; 638 } 639 else 640 { 641 // getting port 642 try 643 { 644 port = new Integer( tokens[2] ).intValue(); 645 path = tokens[3]; 646 module = tokens[4]; 647 } 648 catch ( Exception e ) 649 { 650 //incorrect 651 result.getMessages().add( "Your scm url is invalid, could not get port value." ); 652 653 return result; 654 } 655 } 656 657 // cvsroot format is :sspi:host:path 658 cvsroot = ":" + transport + ":" + host + ":"; 659 660 if ( port != -1 ) 661 { 662 cvsroot += port; 663 } 664 665 cvsroot += path; 666 } 667 else 668 { 669 if ( !transport.equalsIgnoreCase( TRANSPORT_LOCAL ) ) 670 { 671 String userhost = tokens[1]; 672 673 int index = userhost.indexOf( '@' ); 674 675 if ( index == -1 ) 676 { 677 host = userhost; 678 } 679 else 680 { 681 user = userhost.substring( 0, index ); 682 683 host = userhost.substring( index + 1 ); 684 } 685 } 686 687 if ( transport.equals( TRANSPORT_LOCAL ) ) 688 { 689 path = tokens[1]; 690 691 module = tokens[2]; 692 693 if ( module != null && module.startsWith( "/" ) ) 694 { 695 module = module.substring( 1 ); 696 } 697 698 } 699 else 700 { 701 if ( tokens.length == 4 ) 702 { 703 path = tokens[2]; 704 705 module = tokens[3]; 706 } 707 else 708 { 709 port = new Integer( tokens[2] ).intValue(); 710 711 path = tokens[3]; 712 713 module = tokens[4]; 714 } 715 } 716 } 717 718 if ( port == -1 ) 719 { 720 result.setRepository( new CvsScmProviderRepository( cvsroot, transport, user, password, host, path, 721 module ) ); 722 } 723 else 724 { 725 result.setRepository( new CvsScmProviderRepository( cvsroot, transport, user, password, host, port, 726 path, module ) ); 727 } 728 729 return result; 730 } 731 732 protected abstract Command getAddCommand(); 733 734 protected abstract Command getBranchCommand(); 735 736 protected abstract Command getBlameCommand(); 737 738 protected abstract Command getChangeLogCommand(); 739 740 protected abstract Command getCheckInCommand(); 741 742 protected abstract Command getCheckOutCommand(); 743 744 protected abstract Command getDiffCommand(); 745 746 protected abstract Command getExportCommand(); 747 748 protected abstract Command getListCommand(); 749 750 protected abstract Command getLoginCommand(); 751 752 protected abstract Command getRemoveCommand(); 753 754 protected abstract Command getStatusCommand(); 755 756 protected abstract Command getTagCommand(); 757 758 protected abstract Command getUpdateCommand(); 759 760 protected abstract Command getMkdirCommand(); 761 762 // ---------------------------------------------------------------------- 763 // Private methods 764 // ---------------------------------------------------------------------- 765 766 private ScmResult executeCommand( Command command, ScmProviderRepository repository, ScmFileSet fileSet, 767 CommandParameters parameters ) 768 throws ScmException 769 { 770 fileSet = fixUpScmFileSetAbsoluteFilePath( fileSet ); 771 772 command.setLogger( getLogger() ); 773 774 return command.execute( repository, fileSet, parameters ); 775 } 776 777 778 /** 779 * CVS provider requires that all files in ScmFileSet must be relative to basedir 780 * This function ensures and converts all absolute paths to relative paths 781 * 782 * @param currentFileSet 783 * @return 784 * @throws ScmException 785 */ 786 private static ScmFileSet fixUpScmFileSetAbsoluteFilePath( ScmFileSet currentFileSet ) 787 throws ScmException 788 { 789 ScmFileSet newFileSet = null; 790 791 try 792 { 793 File basedir = getAbsoluteFilePath( currentFileSet.getBasedir() ); 794 List<File> fixedFiles = new ArrayList<File>( currentFileSet.getFileList().size() ); 795 for ( File file : currentFileSet.getFileList() ) 796 { 797 if ( file.isAbsolute() ) 798 { 799 fixedFiles.add( new File( getRelativePath( basedir, file ) ) ); 800 } 801 else 802 { 803 fixedFiles.add( file ); 804 } 805 } 806 807 newFileSet = new ScmFileSet( basedir, fixedFiles ); 808 } 809 catch ( IOException e ) 810 { 811 throw new ScmException( "Invalid file set.", e ); 812 } 813 814 return newFileSet; 815 } 816 817 private static File getAbsoluteFilePath( File fileOrDir ) 818 throws IOException 819 { 820 String javaPathString = fileOrDir.getCanonicalPath().replace( '\\', '/' ); 821 822 if ( javaPathString.endsWith( "/" ) ) 823 { 824 javaPathString = javaPathString.substring( 0, javaPathString.length() - 1 ); 825 } 826 827 return new File( javaPathString ); 828 } 829}