pax_global_header00006660000000000000000000000064117371350050014514gustar00rootroot0000000000000052 comment=cac471e4acb0e445e17c72b9c180ac2c5aad4f9c eclipse-mercurialeclipse-1.9.4/000077500000000000000000000000001173713500500165015ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/LICENSE000066400000000000000000000262111173713500500175100ustar00rootroot00000000000000Copyright (c) 2005-2009 Zingo Andersen (VecTrace) The Mercurial "droplets" logo is used in Mercurialeclipse with permission of its author. Eclipse Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. eclipse-mercurialeclipse-1.9.4/README000066400000000000000000000001431173713500500173570ustar00rootroot00000000000000MercurialEclipse Eclipse plugin for Mercurial SCM For Contributors file see plugin/Contributors eclipse-mercurialeclipse-1.9.4/feature/000077500000000000000000000000001173713500500201345ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/feature/.project000066400000000000000000000006131173713500500216030ustar00rootroot00000000000000 MercurialEclipseFeature org.eclipse.pde.FeatureBuilder org.eclipse.pde.FeatureNature eclipse-mercurialeclipse-1.9.4/feature/build.properties000077500000000000000000000000331173713500500233500ustar00rootroot00000000000000bin.includes = feature.xml eclipse-mercurialeclipse-1.9.4/feature/feature.xml000077500000000000000000000332741173713500500223250ustar00rootroot00000000000000 Mercurial plugin for Eclipse IDE Copyright (C) 2005-2011 MercurialEclipse project. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Eclipse Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. eclipse-mercurialeclipse-1.9.4/plugin/000077500000000000000000000000001173713500500177775ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/.checkstyle000066400000000000000000000010371173713500500221370ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.classpath000066400000000000000000000006311173713500500217620ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.fbprefs000066400000000000000000000216251173713500500214350ustar00rootroot00000000000000#FindBugs User Preferences #Fri Aug 21 22:57:26 CEST 2009 detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true detectorBCPMethodReturnCheck=BCPMethodReturnCheck|false detectorBadAppletConstructor=BadAppletConstructor|false detectorBadResultSetAccess=BadResultSetAccess|false detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true detectorBadUseOfReturnValue=BadUseOfReturnValue|true detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true detectorBooleanReturnNull=BooleanReturnNull|true detectorBuildInterproceduralCallGraph=BuildInterproceduralCallGraph|false detectorBuildObligationPolicyDatabase=BuildObligationPolicyDatabase|true detectorCallToUnsupportedMethod=CallToUnsupportedMethod|true detectorCalledMethods=CalledMethods|true detectorCheckCalls=CheckCalls|false detectorCheckExpectedWarnings=CheckExpectedWarnings|false detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true detectorCheckTypeQualifiers=CheckTypeQualifiers|true detectorCloneIdiom=CloneIdiom|true detectorComparatorIdiom=ComparatorIdiom|false detectorConfusedInheritance=ConfusedInheritance|true detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true detectorCrossSiteScripting=CrossSiteScripting|false detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true detectorDontIgnoreResultOfPutIfAbsent=DontIgnoreResultOfPutIfAbsent|true detectorDontUseEnum=DontUseEnum|true detectorDroppedException=DroppedException|true detectorDumbMethodInvocations=DumbMethodInvocations|true detectorDumbMethods=DumbMethods|true detectorDuplicateBranches=DuplicateBranches|true detectorEmptyZipFileEntry=EmptyZipFileEntry|true detectorEqStringTest=EqStringTest|false detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true detectorFieldItemSummary=FieldItemSummary|true detectorFinalizerNullsFields=FinalizerNullsFields|true detectorFindBadCast=FindBadCast|false detectorFindBadCast2=FindBadCast2|true detectorFindBadEqualsImplementation=FindBadEqualsImplementation|false detectorFindBadForLoop=FindBadForLoop|true detectorFindBugsSummaryStats=FindBugsSummaryStats|true detectorFindCircularDependencies=FindCircularDependencies|false detectorFindDeadLocalStores=FindDeadLocalStores|true detectorFindDoubleCheck=FindDoubleCheck|true detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true detectorFindFinalizeInvocations=FindFinalizeInvocations|true detectorFindFloatEquality=FindFloatEquality|true detectorFindFloatMath=FindFloatMath|false detectorFindHEmismatch=FindHEmismatch|true detectorFindInconsistentSync2=FindInconsistentSync2|true detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true detectorFindMaskedFields=FindMaskedFields|true detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true detectorFindNakedNotify=FindNakedNotify|true detectorFindNonSerializableStoreIntoSession=FindNonSerializableStoreIntoSession|false detectorFindNonSerializableValuePassedToWriteObject=FindNonSerializableValuePassedToWriteObject|true detectorFindNonShortCircuit=FindNonShortCircuit|true detectorFindNullDeref=FindNullDeref|true detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true detectorFindOpenStream=FindOpenStream|true detectorFindPuzzlers=FindPuzzlers|true detectorFindRefComparison=FindRefComparison|true detectorFindReturnRef=FindReturnRef|false detectorFindRunInvocations=FindRunInvocations|true detectorFindSelfComparison=FindSelfComparison|true detectorFindSelfComparison2=FindSelfComparison2|true detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true detectorFindSpinLoop=FindSpinLoop|true detectorFindSqlInjection=FindSqlInjection|false detectorFindTwoLockWait=FindTwoLockWait|true detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true detectorFindUnconditionalWait=FindUnconditionalWait|true detectorFindUninitializedGet=FindUninitializedGet|true detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true detectorFindUnreleasedLock=FindUnreleasedLock|true detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true detectorFindUnsyncGet=FindUnsyncGet|true detectorFindUselessControlFlow=FindUselessControlFlow|true detectorFormatStringChecker=FormatStringChecker|true detectorHugeSharedStringConstants=HugeSharedStringConstants|true detectorIDivResultCastToDouble=IDivResultCastToDouble|true detectorIncompatMask=IncompatMask|true detectorInconsistentAnnotations=InconsistentAnnotations|true detectorInefficientMemberAccess=InefficientMemberAccess|false detectorInefficientToArray=InefficientToArray|true detectorInfiniteLoop=InfiniteLoop|true detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true detectorInfiniteRecursiveLoop2=InfiniteRecursiveLoop2|false detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true detectorInitializationChain=InitializationChain|true detectorInstantiateStaticClass=InstantiateStaticClass|true detectorInvalidJUnitTest=InvalidJUnitTest|true detectorIteratorIdioms=IteratorIdioms|true detectorLazyInit=LazyInit|true detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true detectorLockedFields=LockedFields|false detectorLostLoggerDueToWeakReference=LostLoggerDueToWeakReference|true detectorMethodReturnCheck=MethodReturnCheck|true detectorMethods=Methods|true detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true detectorMutableLock=MutableLock|true detectorMutableStaticFields=MutableStaticFields|false detectorNaming=Naming|true detectorNoteAnnotationRetention=NoteAnnotationRetention|true detectorNoteCheckReturnValue=NoteCheckReturnValue|true detectorNoteCheckReturnValueAnnotations=NoteCheckReturnValueAnnotations|true detectorNoteDirectlyRelevantTypeQualifiers=NoteDirectlyRelevantTypeQualifiers|true detectorNoteJCIPAnnotation=NoteJCIPAnnotation|true detectorNoteNonNullAnnotations=NoteNonNullAnnotations|true detectorNoteNonnullReturnValues=NoteNonnullReturnValues|true detectorNoteSuppressedWarnings=NoteSuppressedWarnings|true detectorNoteUnconditionalParamDerefs=NoteUnconditionalParamDerefs|true detectorNumberConstructor=NumberConstructor|true detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true detectorPublicSemaphores=PublicSemaphores|true detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true detectorReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass=ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass|true detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true detectorRedundantInterfaces=RedundantInterfaces|true detectorReflectiveClasses=ReflectiveClasses|true detectorRepeatedConditionals=RepeatedConditionals|true detectorResolveAllReferences=ResolveAllReferences|false detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true detectorSerializableIdiom=SerializableIdiom|false detectorStartInConstructor=StartInConstructor|true detectorStaticCalendarDetector=StaticCalendarDetector|true detectorStringConcatenation=StringConcatenation|true detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true detectorSwitchFallthrough=SwitchFallthrough|true detectorSynchronizationOnSharedBuiltinConstant=SynchronizationOnSharedBuiltinConstant|true detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true detectorTestASM=TestASM|false detectorTestDataflowAnalysis=TestDataflowAnalysis|false detectorTestingGround=TestingGround|false detectorTrainFieldStoreTypes=TrainFieldStoreTypes|true detectorTrainNonNullAnnotations=TrainNonNullAnnotations|true detectorTrainUnconditionalDerefParams=TrainUnconditionalDerefParams|true detectorURLProblems=URLProblems|true detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true detectorUnnecessaryMath=UnnecessaryMath|true detectorUnreadFields=UnreadFields|true detectorUseObjectEquals=UseObjectEquals|true detectorUselessSubclassMethod=UselessSubclassMethod|true detectorVarArgsProblems=VarArgsProblems|true detectorVolatileUsage=VolatileUsage|true detectorWaitInLoop=WaitInLoop|true detectorWrongMapIterator=WrongMapIterator|true detectorXMLFactoryBypass=XMLFactoryBypass|true detector_threshold=2 effort=default excludefilter0=.settings/findbugs_exclude.xml filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,EXPERIMENTAL,I18N,MALICIOUS_CODE,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false filter_settings_neg=NOISE| run_at_full_build=false eclipse-mercurialeclipse-1.9.4/plugin/.options000066400000000000000000000001351173713500500214720ustar00rootroot00000000000000com.vectrace.MercurialEclipse/debug=false com.vectrace.MercurialEclipse/debug/commands=false eclipse-mercurialeclipse-1.9.4/plugin/.project000066400000000000000000000020571173713500500214520ustar00rootroot00000000000000 MercurialEclipse org.eclipse.jdt.core.javabuilder org.eclipse.pde.ManifestBuilder org.eclipse.pde.SchemaBuilder edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder net.sf.eclipsecs.core.CheckstyleBuilder org.eclipse.pde.PluginNature org.eclipse.jdt.core.javanature edu.umd.cs.findbugs.plugin.eclipse.findbugsNature net.sf.eclipsecs.core.CheckstyleNature eclipse-mercurialeclipse-1.9.4/plugin/.settings/000077500000000000000000000000001173713500500217155ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/.settings/Eclipse3.4_with_Mylyn.target000066400000000000000000000005111173713500500271560ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/Eclipse3.5_with_Mylyn.target000066400000000000000000000005111173713500500271570ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/Eclipse3.6_with_Mylyn.target000066400000000000000000000005111173713500500271600ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/Eclipse3.7.1_with_Mylyn.target000066400000000000000000000005141173713500500273230ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/Eclipse3.7_with_Mylyn.target000066400000000000000000000005111173713500500271610ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/Eclipse3.8_with_Mylyn.target000066400000000000000000000005101173713500500271610ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/MercurialEclipseTests.launch000066400000000000000000000056511173713500500273730ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/checkstyle.xml000066400000000000000000000067311173713500500246040ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/checkstyle_suppressions.xml000066400000000000000000000010511173713500500274270ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/de.loskutov.anyedit.AnyEditTools.prefs000066400000000000000000000007511173713500500312470ustar00rootroot00000000000000#Sat Nov 14 22:57:56 CET 2009 activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF,plugin.xml convertActionOnSaave=AnyEdit.CnvrtSpacesToTabs eclipse.preferences.version=1 inActiveContentFilterList= javaTabWidthForJava=true org.eclipse.jdt.ui.editor.tab.width=4 projectPropsEnabled=true removeTrailingSpaces=true replaceAllSpaces=false replaceAllTabs=false saveAndAddLine=false saveAndConvert=true saveAndTrim=true useModulo4Tabs=false eclipse-mercurialeclipse-1.9.4/plugin/.settings/findbugs_exclude.xml000066400000000000000000000011111173713500500257430ustar00rootroot00000000000000 eclipse-mercurialeclipse-1.9.4/plugin/.settings/org.eclipse.core.resources.prefs000066400000000000000000000001251173713500500301260ustar00rootroot00000000000000#Wed Mar 04 21:18:09 CET 2009 eclipse.preferences.version=1 encoding/=UTF-8 eclipse-mercurialeclipse-1.9.4/plugin/.settings/org.eclipse.core.runtime.prefs000066400000000000000000000001211173713500500275730ustar00rootroot00000000000000#Sat Nov 14 22:57:56 CET 2009 eclipse.preferences.version=1 line.separator=\n eclipse-mercurialeclipse-1.9.4/plugin/.settings/org.eclipse.jdt.core.prefs000066400000000000000000000664051173713500500267120ustar00rootroot00000000000000#Sun Feb 13 09:57:51 CET 2011 eclipse.preferences.version=1 org.eclipse.jdt.core.codeComplete.argumentPrefixes= org.eclipse.jdt.core.codeComplete.argumentSuffixes= org.eclipse.jdt.core.codeComplete.fieldPrefixes= org.eclipse.jdt.core.codeComplete.fieldSuffixes= org.eclipse.jdt.core.codeComplete.localPrefixes= org.eclipse.jdt.core.codeComplete.localSuffixes= org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.autoboxing=warning org.eclipse.jdt.core.compiler.problem.comparingIdentical=error org.eclipse.jdt.core.compiler.problem.deadCode=warning org.eclipse.jdt.core.compiler.problem.deprecation=warning org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled org.eclipse.jdt.core.compiler.problem.discouragedReference=warning org.eclipse.jdt.core.compiler.problem.emptyStatement=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled org.eclipse.jdt.core.compiler.problem.fieldHiding=warning org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=error org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=error org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=error org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=error org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=warning org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore org.eclipse.jdt.core.compiler.problem.nullReference=error org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning org.eclipse.jdt.core.compiler.problem.redundantNullCheck=error org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=warning org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled org.eclipse.jdt.core.compiler.problem.unusedImport=warning org.eclipse.jdt.core.compiler.problem.unusedLabel=error org.eclipse.jdt.core.compiler.problem.unusedLocal=warning org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error org.eclipse.jdt.core.compiler.source=1.5 org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,HIGH,HIGH org.eclipse.jdt.core.compiler.taskTags=TODO,FIXME,XXX org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_assignment=0 org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 org.eclipse.jdt.core.formatter.blank_lines_after_package=1 org.eclipse.jdt.core.formatter.blank_lines_before_field=0 org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 org.eclipse.jdt.core.formatter.blank_lines_before_method=1 org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 org.eclipse.jdt.core.formatter.blank_lines_before_package=0 org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false org.eclipse.jdt.core.formatter.comment.format_block_comments=true org.eclipse.jdt.core.formatter.comment.format_header=false org.eclipse.jdt.core.formatter.comment.format_html=true org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true org.eclipse.jdt.core.formatter.comment.format_line_comments=true org.eclipse.jdt.core.formatter.comment.format_source_code=true org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true org.eclipse.jdt.core.formatter.comment.indent_root_tags=true org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert org.eclipse.jdt.core.formatter.comment.line_length=100 org.eclipse.jdt.core.formatter.compact_else_if=true org.eclipse.jdt.core.formatter.continuation_indentation=2 org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_empty_lines=false org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false org.eclipse.jdt.core.formatter.indentation.size=4 org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.join_lines_in_comments=true org.eclipse.jdt.core.formatter.join_wrapped_lines=true org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.jdt.core.formatter.lineSplit=100 org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.jdt.core.formatter.tabulation.char=tab org.eclipse.jdt.core.formatter.tabulation.size=4 org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true eclipse-mercurialeclipse-1.9.4/plugin/.settings/org.eclipse.jdt.ui.prefs000066400000000000000000000210571173713500500263710ustar00rootroot00000000000000#Sat Aug 21 21:00:34 EDT 2010 eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile formatter_settings_version=11 internal.default.compliance=default org.eclipse.jdt.ui.exception.name=e org.eclipse.jdt.ui.gettersetter.use.is=true org.eclipse.jdt.ui.ignorelowercasenames=true org.eclipse.jdt.ui.importorder=java;javax;org;com; org.eclipse.jdt.ui.javadoc=true org.eclipse.jdt.ui.keywordthis=false org.eclipse.jdt.ui.ondemandthreshold=99 org.eclipse.jdt.ui.overrideannotation=true org.eclipse.jdt.ui.staticondemandthreshold=2 org.eclipse.jdt.ui.text.custom_code_templates= sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false sp_cleanup.add_missing_annotations=true sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false sp_cleanup.add_missing_override_annotations=true sp_cleanup.add_missing_override_annotations_interface_methods=false sp_cleanup.add_serial_version_id=false sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false sp_cleanup.convert_to_enhanced_for_loop=false sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=false sp_cleanup.format_source_code_changes_only=true sp_cleanup.make_local_variable_final=false sp_cleanup.make_parameters_final=false sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false sp_cleanup.make_variable_declarations_final=true sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=true sp_cleanup.on_save_use_additional_actions=true sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_with_declaring_class=false sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false sp_cleanup.remove_unnecessary_casts=true sp_cleanup.remove_unnecessary_nls_tags=true sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false sp_cleanup.use_blocks=true sp_cleanup.use_blocks_only_for_return_and_throw=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true eclipse-mercurialeclipse-1.9.4/plugin/.settings/org.eclipse.pde.api.tools.prefs000066400000000000000000000160431173713500500276520ustar00rootroot00000000000000#Sat Jul 12 15:24:48 CEST 2008 ANNOTATION_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error ANNOTATION_ELEMENT_TYPE_ADDED_FIELD=Error ANNOTATION_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error ANNOTATION_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error ANNOTATION_ELEMENT_TYPE_ADDED_METHOD=Error ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error ANNOTATION_ELEMENT_TYPE_ADDED_TYPE_MEMBER=Error ANNOTATION_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error ANNOTATION_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error ANNOTATION_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error ANNOTATION_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error ANNOTATION_ELEMENT_TYPE_CHANGED_INTERFACE_BOUNDS=Error ANNOTATION_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error ANNOTATION_ELEMENT_TYPE_CHANGED_TO_CLASS=Error ANNOTATION_ELEMENT_TYPE_CHANGED_TO_ENUM=Error ANNOTATION_ELEMENT_TYPE_CHANGED_TO_INTERFACE=Error ANNOTATION_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error ANNOTATION_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD_WITHOUT_DEFAULT_VALUE=Error ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD_WITH_DEFAULT_VALUE=Error ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_PARAMETERS=Error API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error CLASS_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error CLASS_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error CLASS_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error CLASS_ELEMENT_TYPE_ADDED_METHOD=Error CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error CLASS_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERCLASS_SET=Error CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error CLASS_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error CLASS_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error CLASS_ELEMENT_TYPE_CHANGED_SUPERCLASS=Error CLASS_ELEMENT_TYPE_CHANGED_TO_ANNOTATION=Error CLASS_ELEMENT_TYPE_CHANGED_TO_ENUM=Error CLASS_ELEMENT_TYPE_CHANGED_TO_INTERFACE=Error CLASS_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error CLASS_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error CLASS_ELEMENT_TYPE_REMOVED_INTERFACE_BOUNDS=Error CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETERS=Error CONSTRUCTOR_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error CONSTRUCTOR_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error CONSTRUCTOR_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_TYPE_PARAMETER=Error CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error CONSTRUCTOR_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error CONSTRUCTOR_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error CONSTRUCTOR_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error CONSTRUCTOR_ELEMENT_TYPE_REMOVED_INTERFACE_BOUNDS=Error CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETERS=Error ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error ENUM_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error ENUM_ELEMENT_TYPE_CHANGED_TO_ANNOTATION=Error ENUM_ELEMENT_TYPE_CHANGED_TO_CLASS=Error ENUM_ELEMENT_TYPE_CHANGED_TO_INTERFACE=Error ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error FIELD_ELEMENT_TYPE_ADDED_VALUE=Error FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENTS=Error FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error ILLEGAL_EXTEND=Warning ILLEGAL_IMPLEMENT=Warning ILLEGAL_INSTANTIATE=Warning ILLEGAL_OVERRIDE=Warning ILLEGAL_REFERENCE=Warning INTERFACE_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error INTERFACE_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error INTERFACE_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error INTERFACE_ELEMENT_TYPE_ADDED_TYPE_MEMBER=Error INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETERS=Error INTERFACE_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error INTERFACE_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error INTERFACE_ELEMENT_TYPE_CHANGED_INTERFACE_BOUNDS=Error INTERFACE_ELEMENT_TYPE_CHANGED_RESTRICTIONS=Error INTERFACE_ELEMENT_TYPE_CHANGED_TO_ANNOTATION=Error INTERFACE_ELEMENT_TYPE_CHANGED_TO_CLASS=Error INTERFACE_ELEMENT_TYPE_CHANGED_TO_ENUM=Error INTERFACE_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error INTERFACE_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error INTERFACE_ELEMENT_TYPE_REMOVED_INTERFACE_BOUNDS=Error INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error INVALID_JAVADOC_TAG=Ignore LEAK_EXTEND=Warning LEAK_FIELD_DECL=Warning LEAK_IMPLEMENT=Warning LEAK_METHOD_PARAM=Warning LEAK_METHOD_RETURN_TYPE=Warning METHOD_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error METHOD_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error METHOD_ELEMENT_TYPE_ADDED_INTERFACE_BOUNDS=Error METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error METHOD_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error METHOD_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error METHOD_ELEMENT_TYPE_CHANGED_TYPE_PARAMETER=Error METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error METHOD_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error METHOD_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error METHOD_ELEMENT_TYPE_REMOVED_INTERFACE_BOUNDS=Error METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETERS=Error eclipse.preferences.version=1 incompatible_api_component_version=Error incompatible_api_component_version_include_major_without_breaking_change=Disabled incompatible_api_component_version_include_minor_without_api_change=Disabled invalid_since_tag_version=Error malformed_since_tag=Error missing_since_tag=Error eclipse-mercurialeclipse-1.9.4/plugin/.settings/org.eclipse.pde.prefs000066400000000000000000000020131173713500500257330ustar00rootroot00000000000000#Fri Feb 19 23:23:06 CET 2010 compilers.f.unresolved-features=1 compilers.f.unresolved-plugins=1 compilers.incompatible-environment=1 compilers.p.build=1 compilers.p.build.bin.includes=1 compilers.p.build.java.compliance=1 compilers.p.build.missing.output=2 compilers.p.build.output.library=1 compilers.p.build.source.library=1 compilers.p.build.src.includes=1 compilers.p.deprecated=1 compilers.p.discouraged-class=1 compilers.p.internal=1 compilers.p.missing-packages=1 compilers.p.missing-version-export-package=2 compilers.p.missing-version-import-package=2 compilers.p.missing-version-require-bundle=2 compilers.p.no-required-att=0 compilers.p.not-externalized-att=1 compilers.p.unknown-attribute=1 compilers.p.unknown-class=1 compilers.p.unknown-element=1 compilers.p.unknown-identifier=1 compilers.p.unknown-resource=1 compilers.p.unresolved-ex-points=0 compilers.p.unresolved-import=0 compilers.s.create-docs=false compilers.s.doc-folder=doc compilers.s.open-tags=1 eclipse.preferences.version=1 eclipse-mercurialeclipse-1.9.4/plugin/Contributors000066400000000000000000000111441173713500500224200ustar00rootroot00000000000000Mercurial Eclipse Plugin Here is a list of people that has been contributing to this project if you supply a patch please dont forget to patch this file also add your name, a few lines about yourself and if you want an email. Contributors: (In order of appearance) Zingo Andersen - Creator of this nice piece of software. I'm an old Amiga fart, that likes hacking around. I have two kids and a wife, both take there share of my private Life so lately there has not been so much hacking after I come home from my day job as a Realtime Consultant from Enea. I live in Sweden in the town called Lund. More info about me might be found at http://www.zingo.org Gunnar Ahlberg - I'm a developer. Other than that, I'm generally outdoors playing in the woods and archipelago of sunny Stockholm, Sweden. Cheers! Zingo's Comment: Gunnar is the first external contributor, he started the work on getting the plugin configurable, thanks for the help. Peter Hunnisett - Peter Hunnisett is a bipedal mammal hailing from Canada who's wondering if you have to come from a northern country to contribute to this software. Zingo's Comment: Peter insted of whising for feature just plain wrote them :) He is responsible for the cloning,rename/move and selectable commit handling. He as also refacorated the messy code that I have wrote. Indra Talip Zingo's Comment: Indra added a browse button to the clone wizard, this was very nice. Sebastian Herbszt - Some code changes and some testing on Windows Zingo's Comment: Sebastian started out with a small changelog patch but have since then help with bug tracking and other patches Stefan Chyssler I currently work as a python developer in Stockholm, Sweden. Previously I worked as an eclipse plugin developer developer at an company in Sweden. I have a genuine interest in eclipse plugin development and believe a full fledged mercurial team support will help make eclipse stay on top. Zingo's Comment: StefanC started out to helped me with not selecting ignored files in Commit dialog and making it resizable, after that he has made numerous contributions. StefanG Zingo's Comment: StefanG help me with better log output thanx for pointing this out. Stefan Groschupf - Zingo's Comment: Stefan Groschupf help with logError (He could be the same person as StefanG But Im not sure) Charles O'Farrell - Zingo's Comment: Fixed decoration on Project outside of workspace. Then continued with a lot of changes. Jerome Negre - Zingo's Comment: Jerome started to fix a few issues and started add missing features like .hgignore support, after that he has made numerous contributions. Bastian Doetsch - I'm interested in Mercurial and MercurialEclipse so I started contributing a bit while learning. I try to get the synchronize infrastructure to work. Zingos Comment: Well Bastian seem to learn fast :) the Time from the first small patch to large contribution was quite small. Bastian is now driving the project forward. Brian Wallis: Zingos Comments: Brian helped with some bugfixing an a few features. Georg Koltermann: Zingos Comment: Georg was one of the first users leaving feedback and even helped fixing some bugs. Steeven Lee: Steeven introduced himself by contributing export functionality for changes. This, together with a revamped import wizard is nicely integrated in Eclipse and we look forward to further contributions! Ismael Juma - I'm interested in moving from SVN to Mercurial at work and good Eclipse support is important. While testing the plugin I ran into some issues and decided to contribute. Andrei Loskutov: I've started to use hg because I was shocked that SVN can't propagate changes to renamed/moved files. Because I'm Eclipse guy, I've started to use MercurialEclipse. To make my life easier I've started to fix the issues I found in the plugin. More info about me might be found at http://andrei.gmxhome.de Adam Berkes & Zsolt Koppany - Intland Software - http://www.intland.com Because of well known limitations of Subversion we moved from Subversion to Mercurial. We at Intland Software are very happy with Mercurial and our goal is to enhance and extend this free and open source plugin for enterprise environment. Philip Graf: Implemented proxy support for remote operations. Bjoern Stachmann: Actually i'm more of a git type. But then i'm an eclipse type too. Have you tried EGit? I did. Then i stumbled upon upon this nice piece of plugin here. Trying it i found that using mercurial isn't that bad ;-) But it did miss some features so i started to contribute. John Peberdy: Improved the synchronize view and conflicted rebase and other usability improvements. eclipse-mercurialeclipse-1.9.4/plugin/LICENSE000066400000000000000000000262111173713500500210060ustar00rootroot00000000000000Copyright (c) 2005-2009 Zingo Andersen (VecTrace) The Mercurial "droplets" logo is used in Mercurialeclipse with permission of its author. Eclipse Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. eclipse-mercurialeclipse-1.9.4/plugin/META-INF/000077500000000000000000000000001173713500500211375ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/META-INF/MANIFEST.MF000066400000000000000000000061241173713500500225740ustar00rootroot00000000000000Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name.0 Bundle-SymbolicName: com.vectrace.MercurialEclipse; singleton:=true Bundle-Version: 1.9.4.qualifier Bundle-Activator: com.vectrace.MercurialEclipse.MercurialEclipsePlugin Bundle-Vendor: %Bundle-Vendor.0 Bundle-Localization: plugin Require-Bundle: org.eclipse.ui;bundle-version="3.5.0", org.eclipse.core.runtime;bundle-version="3.5.0", org.eclipse.core.resources;bundle-version="3.5.0", org.eclipse.team.core;bundle-version="3.5.0", org.eclipse.team.ui;bundle-version="3.5.0", org.eclipse.jface.text;bundle-version="3.5.0", org.eclipse.ui.editors;bundle-version="3.5.0", org.eclipse.ui.workbench.texteditor;bundle-version="3.5.0", org.eclipse.ui.ide;bundle-version="3.5.0", org.eclipse.ui.console;bundle-version="3.4.0", org.eclipse.compare;bundle-version="3.5.0", org.eclipse.core.filesystem;bundle-version="1.1.0", org.eclipse.core.expressions;bundle-version="3.4.0", org.eclipse.core.net;bundle-version="1.1.0", org.eclipse.ui.navigator;bundle-version="3.4.0", org.eclipse.search;bundle-version="3.5.0", org.eclipse.ui.views.properties.tabbed;bundle-version="3.5.0", org.junit;resolution:=optional, org.eclipse.mylyn.team.ui;bundle-version="3.0.0";resolution:=optional, org.eclipse.mylyn.tasks.core;bundle-version="3.0.0";resolution:=optional, org.eclipse.mylyn.context.core;bundle-version="3.0.0";resolution:=optional, org.eclipse.mylyn.tasks.ui;bundle-version="3.0.0";resolution:=optional, org.eclipse.mylyn.resources.ui;bundle-version="3.0.0";resolution:=optional Eclipse-LazyStart: true Export-Package: com.vectrace.MercurialEclipse, com.vectrace.MercurialEclipse.actions, com.vectrace.MercurialEclipse.annotations, com.vectrace.MercurialEclipse.commands, com.vectrace.MercurialEclipse.commands.extensions, com.vectrace.MercurialEclipse.commands.extensions.forest, com.vectrace.MercurialEclipse.commands.extensions.mq, com.vectrace.MercurialEclipse.compare, com.vectrace.MercurialEclipse.dialogs, com.vectrace.MercurialEclipse.exception, com.vectrace.MercurialEclipse.history, com.vectrace.MercurialEclipse.menu, com.vectrace.MercurialEclipse.model, com.vectrace.MercurialEclipse.model.resources, com.vectrace.MercurialEclipse.mylyn, com.vectrace.MercurialEclipse.operations, com.vectrace.MercurialEclipse.preferences, com.vectrace.MercurialEclipse.properties, com.vectrace.MercurialEclipse.repository, com.vectrace.MercurialEclipse.repository.actions, com.vectrace.MercurialEclipse.repository.model, com.vectrace.MercurialEclipse.search, com.vectrace.MercurialEclipse.storage, com.vectrace.MercurialEclipse.synchronize, com.vectrace.MercurialEclipse.synchronize.actions, com.vectrace.MercurialEclipse.synchronize.cs, com.vectrace.MercurialEclipse.team, com.vectrace.MercurialEclipse.team.cache, com.vectrace.MercurialEclipse.team.images, com.vectrace.MercurialEclipse.ui, com.vectrace.MercurialEclipse.utils, com.vectrace.MercurialEclipse.views, com.vectrace.MercurialEclipse.views.console, com.vectrace.MercurialEclipse.wizards, com.vectrace.MercurialEclipse.wizards.mq Bundle-RequiredExecutionEnvironment: J2SE-1.5 eclipse-mercurialeclipse-1.9.4/plugin/META-INF/p2.inf000066400000000000000000000012451173713500500221600ustar00rootroot00000000000000requires.0.namespace = osgi.bundle requires.0.name = org.eclipse.mylyn.team.ui requires.0.greedy = false requires.0.optional = true requires.1.namespace = osgi.bundle requires.1.name = org.eclipse.mylyn.tasks.core requires.1.greedy = false requires.1.optional = true requires.2.namespace = osgi.bundle requires.2.name = org.eclipse.mylyn.context.core requires.2.greedy = false requires.2.optional = true requires.3.namespace = osgi.bundle requires.3.name = org.eclipse.mylyn.tasks.ui requires.3.greedy = false requires.3.optional = true requires.4.namespace = osgi.bundle requires.4.name = org.eclipse.mylyn.resources.ui requires.4.greedy = false requires.4.optional = trueeclipse-mercurialeclipse-1.9.4/plugin/about.ini000066400000000000000000000011331173713500500216100ustar00rootroot00000000000000# about.ini # contains information about a feature # java.io.Properties file (ISO 8859-1 with "\" escapes) # "%key" are externalized strings defined in about.properties # This file does not need to be translated. # Property "aboutText" contains blurb for "About" dialog (translated) aboutText=%featureText # Property "featureImage" contains path to feature image (32x32) featureImage=mercurial.png # Property "appName" contains name of the application (translated) appName=%featureName # Property "welcomePage" contains path to welcome page (special XML-based format) # welcomePage=$nl$/welcome.xml eclipse-mercurialeclipse-1.9.4/plugin/about.properties000066400000000000000000000000711173713500500232250ustar00rootroot00000000000000featureName=MercurialEclipse featureText=MercurialEclipseeclipse-mercurialeclipse-1.9.4/plugin/build.properties000066400000000000000000000004761173713500500232230ustar00rootroot00000000000000source.. = src/ output.. = bin/ bin.includes = plugin.xml,\ META-INF/,\ .,\ icons/,\ styles/,\ plugin.properties,\ plugin_zh.properties,\ about.ini,\ about.properties,\ mercurial.png eclipse-mercurialeclipse-1.9.4/plugin/docs/000077500000000000000000000000001173713500500207275ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/docs/how_to_build_native_hg_fragment.txt000066400000000000000000000134131173713500500300570ustar00rootroot00000000000000##################################### # How to create native hg fragments # # ----------------------------------# # Author: Andrei Loskutov # # Date: 03.12.2009 # ########################################################################################## # Please note, that the instructions below are not perfect and reflecting my personal # experience with building the native fragment for Eclipse. I'm pretty sure there is more # elegant way to do it, but right now it simply works... ########################################################################################## Below are the steps I run to create the native hg fragment for Windows. I've tested this on Windows XP and it works. Hovewer, I can imagine, that this may NOT work for Vista or Vista SP2 (Windows 7). Similar way is to go for all other operating systems. 1) Create a new "Plugin Fragment" project with Eclipse wizard. Please use for the fragment project name the plugin name plus the target platform, like: "hgeclipseFragment_win32" 2) Please give the fragment a meaningful, full-qualified bundle id (also derived from the target platform), like: "com.intland.hgbinary.win32" 3) Create the "os/name/architecture" folder structure in the fragment project. For Windows, we simply use "os/win32" (there is no need to have "os/win32/x86" or "os/win32/x86_64"), but for Linux it would be "os/linux/x86" for 32 bit and "os/linux/x86_64" for 64 bit binaries. 4) Add the "os" folder to the build.properties: ------------- output.. = bin/ bin.includes = META-INF/,\ .,\ os/ ------------- 5) Get the binaries from http://mercurial.selenic.com/wiki/Download?action=show&redirect=BinaryPackages 6) Run the installer and let it install the hg "as usual" 7) Go to the installation directory and copy everything EXCEPT the "locale" directory to the "hgeclipseFragment_win32/os/win32" directory. The "locale" contains translated hg messages, which are bad for Eclipse plugin, because it relies sometimes on EXACT hg output messages. On a german PC it would simply sometimes not work... Default *hardcoded* hg language used by plugin is english and does not require anything from "locale". 8) (For Hg 1.7.3 and above) Open hgeclipseFragment_win32/os/win32/hgrc.d/Paths.rc. Repace the line, "cacerts=...\cacert.pem", with "cacerts=%HGE_RUNDIR%\hgrc.d\cacert.pem" (without quote) This line sets the path to CA root certificates. MercurialEclipse will set environment variable %HGE_RUNDIR% to the hg.exe install path at runtime. 9) Also delete unins000.dat file, which is created by the installer and which contains local PC data required to uninstall hg. 10) Check the META-INF/MANIFEST.MF file in the fragment project. The file should look like: ------------- Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: com.intland.hgbinary.win32 Bundle-SymbolicName: com.intland.hgbinary.win32 Bundle-Version: 1.3.1 Bundle-Vendor: Intland Software Fragment-Host: com.vectrace.MercurialEclipse;bundle-version="1.5.0" Bundle-RequiredExecutionEnvironment: J2SE-1.5 Eclipse-PlatformFilter: (osgi.os=win32) ------------- Please notice 3 important things: - "Bundle-Version: 1.3.1" - must match hg version - "Fragment-Host: ... " - must match hgeclipse plugin version - "Eclipse-PlatformFilter: (osgi.os=win32)" - it MUST contain right platform filter 11) Create a "feature" project with Eclipse wizard. This is required for the update site. As name, use something like "hgeclipseFragmentFeature_win32". Feature ID must be unique, so it can be something like "hgeclipse_win32". 12) Check the feature.xml in the feature project. The file should look like: ------------- Hg (Mercurial) binaries for Windows operating system Intland Software GPL ------------- Please notice 4 important things: - feature and plugin versions should match the fragment version (1.3.1) - "feature os" should match the target platform ("win32") - plugin MUST have "unpack="true"" attribute set. Otherwise Eclipse would package the hg binaries in a jar and deploy it so to the target Eclipse platform. In this case hg will not be able to find all required files etc. So we MUST set unpack="true". 13) Now, in the update site of your choice, add something like this: An example update site.xml file can look like: ------------- ------------- Again, important to consider is: - feature must have a platform filter, like os="win32". Otherwise Linux users would try to install the Windows version, which will be a little bit disappointing for them at the end. 14) So now we are ready to build: open site.xml with Eclipse default site editor, click on "hgeclipse_win32" entry and then on "Build" button. This would trigger the generation of the fragment and feature jars. Put jars and site.xml to the web server of your choice and you are done. eclipse-mercurialeclipse-1.9.4/plugin/icons/000077500000000000000000000000001173713500500211125ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/000077500000000000000000000000001173713500500225525ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/branch.gif000066400000000000000000000002361173713500500244770ustar00rootroot00000000000000GIF89a ̯`Vg! ,KIekWY\$`8ɠf,A0&xa/!%aQ\,_b:DU B!P &, ZU;eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/commit.gif000066400000000000000000000003361173713500500245330ustar00rootroot00000000000000GIF89aҗΓ笫Eϕ $܃֝뚚ޥ&a!,[&di(AiSY*cLĶ$,IMpz06 @*z-: 추i0j`rqSq)kz 9)#!;eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/compare_with_local.gif000066400000000000000000000005411173713500500270740ustar00rootroot00000000000000GIF89ahacG2c!;p!,@pH,cȤ2V<8P&1XYHB!\qS8u "@ q#79*-: !.<3; #/>== 0E=3=+=,E®(E %E&&A;eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/merge.gif000066400000000000000000000002251173713500500243370ustar00rootroot00000000000000GIF89a nƏֽͨ{第tײ! ,BIv4M5 TH1 A00L.x CjcSĊTjX XRHh\08;eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/qrefresh.gif000066400000000000000000000003361173713500500250620ustar00rootroot00000000000000GIF89aJEΓϕ җ֝ޥ$^c&rEa܃!,['di(i @,*?vi$  Op05EAzL-: 2P0j yq"kz9)#!;eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/revert.gif000066400000000000000000000002261173713500500245500ustar00rootroot00000000000000GIF89a _5vy͜a yt܃! ,CPI8m2H"%j j= a!bRfULX( `;eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/search.gif000066400000000000000000000011341173713500500245050ustar00rootroot00000000000000GIF89a?nM{tPoNrQyM|JG}VEB\A>=bf9;ư]߽Ťs҅ՒՑ}ڣߞ!Created with GIMP!@,@@==@ <  :66 40 955 .+ 8 3+&72%Ѿ/@ɲ)#@ -,($!1; @;>~ @!?I|(A@AI".1$}q¢@;eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/switch.gif000066400000000000000000000002171173713500500245420ustar00rootroot00000000000000GIF89a螬t`_Vgn!,I8jsRP#|́|@4U \B p6EfJևAn";eclipse-mercurialeclipse-1.9.4/plugin/icons/actions/update.gif000066400000000000000000000003461173713500500245260ustar00rootroot00000000000000GIF89aϕ EA;֝r܃^c$җ&ޥaJE!,c &di(D<)e-PeM*[(8bCo]0`.8|V`pasmJrh)p?'E~y&9)#!;eclipse-mercurialeclipse-1.9.4/plugin/icons/add.gif000066400000000000000000000004761173713500500223400ustar00rootroot00000000000000GIF89a5vT8zW8yW;~Z<~Z@^DbEcEbEcEbJgJhOlPlTqUqTpXuUq\y_{]ySTUVXXZ[ZZ[````aceef!+,[pH,HaeYI+*UӹPJr 'D>=C$2ڥAdB(D  HZZZZA;eclipse-mercurialeclipse-1.9.4/plugin/icons/annotate.gif000066400000000000000000000011201173713500500234040ustar00rootroot00000000000000GIF89a^LTH:@ZGPcPYhU^gV^bPYK=DOAHm\eWJQ[NU~m[erbkwgp{lupyREMqakvfpzlu~pys|.8FGGGXXZkk}~~~0>>OJW҃!fvҏӗͧ||ݲyˤ'Þ-u4qw:?n@DegjG![,[CCEEI[C5 5D5C[B4 3A34424G[H// <0.-/1/F[K*, @)+,)*,K[N''(?(('(N[P%%$$;$%9>P[T #QQ:BaBI)Zd m0p 3fʠ+ CRő@;eclipse-mercurialeclipse-1.9.4/plugin/icons/branches_rep.gif000066400000000000000000000001711173713500500242330ustar00rootroot00000000000000GIF89a7\7\ť!,>HԪVe-\L5Xkv- J? 뱄C1eI(%XE;eclipse-mercurialeclipse-1.9.4/plugin/icons/checkout_action.gif000066400000000000000000000011061173713500500247410ustar00rootroot00000000000000GIF89aֺտ׻պզ̠ͦʉʉ̈uz}lpomZѪŔlҶ|䗻~znqqnqqruk!M,M:M7":7>>M;!!2.1  3C..BB=BA64?++0(5M@9/)-K<<8(*EHFFJI,'G`!Ѐu FAۮPѸ l`p p&;eclipse-mercurialeclipse-1.9.4/plugin/icons/cview16/repository_rep.gif000066400000000000000000000010411173713500500261460ustar00rootroot00000000000000GIF89aaeOopp2MWXYZ^a45=%(!=B?HFefGo̰c!Ȳ!_,_F[8;8=  7G::-5.6_419+3++,K_ *M#0)2)P"!(R_ A@CEQ\^ $NhI4K'JɕH_ظ*e9(;eclipse-mercurialeclipse-1.9.4/plugin/icons/elcl16/collapseall.gif000066400000000000000000000001301173713500500251540ustar00rootroot00000000000000GIF89a___!,)砈B;qơ>FZBT'zK59S;eclipse-mercurialeclipse-1.9.4/plugin/icons/elcl16/expandall.gif000066400000000000000000000002441173713500500246370ustar00rootroot00000000000000GIF89aFz! ,QI6C D(h9@1@@ B h:2򉤄֧K'V$˅zAX8f;eclipse-mercurialeclipse-1.9.4/plugin/icons/elcl16/refresh.gif000066400000000000000000000002201173713500500243170ustar00rootroot00000000000000GIF89a___!,Ux\8Kt0" aAz!*g@r`8$ASa<lAJF9رۼw;eclipse-mercurialeclipse-1.9.4/plugin/icons/elcl16/uncommitted_cs.gif000066400000000000000000000005411173713500500257040ustar00rootroot00000000000000GIF89aP``ppx@Xx`px`p8P (а0Ȩ8Ƞ08880HX8@(0P80!+,~p"šR5ΏrثTD&x;$E A`𒅡dNq=x J! zk C! p 'S'  %z S& SB&&"A;eclipse-mercurialeclipse-1.9.4/plugin/icons/export.gif000066400000000000000000000010651173713500500231240ustar00rootroot00000000000000GIF89aJrnޅ_s즒fڃz~짒fnkkqoykw}|njw|xpyyuezu{hz~u|™ kw!J,J:?AII&(G <3G  G0I 7G+Ņ6. G 4*2/'9BE! ,; C=8$)@D5"- F|$aIH*D@;eclipse-mercurialeclipse-1.9.4/plugin/icons/flatLayout.gif000066400000000000000000000001411173713500500237210ustar00rootroot00000000000000GIF89amkquz}!,&x0@ $@CiV)V%q)u_r_&;eclipse-mercurialeclipse-1.9.4/plugin/icons/history.gif000066400000000000000000000010641173713500500233030ustar00rootroot00000000000000GIF89a~ovwҼνﳣ³,X񖭪QȸG`u}"ë.äƨ(4:<àà5 , ČċÊv n !S,S2E>FI2+A8$-3@+?B7%@PJH,'19KO&=0)(5GNC5@MC6@L; 4„.(0B@) : / 549 GH8BE;eclipse-mercurialeclipse-1.9.4/plugin/icons/import_project.gif000066400000000000000000000005411173713500500246410ustar00rootroot00000000000000GIF89a!żoouwv@wÝl \l3p3pwؤ!!,~pH, Ȥ29\(a4Wk -DL,CLX(a0uu}BF!C  ! ! ECE A;eclipse-mercurialeclipse-1.9.4/plugin/icons/mercurialeclipse.png000066400000000000000000000014631173713500500251540ustar00rootroot00000000000000PNG  IHDRasRGB pHYs  tIME 0(*d\IDAT8ˍ]HSqƟ917W97hMPRR(ȺJ]t]t(.Ita.l "nn2俫>n%8!SSSKRtBZ-^]r^\\4JRW ¯EBl,{QA.󭯯\wKKKcw^k{{{SEAYY 8$IDVߟA%a򳳳0_N'dY$?fxJ$:QF"h4!w3dzEE|M0 ŐJR f3 B-$ bT7f.%ˎ,Rs,VN$Iy+gcݮkfl__> յ8(fLNNjg`l9e1 aee%d6Ce^5LX,Ad2yR JJBjv;L&FGGaX򃃃=H]RBڊD"a|>o0j{zzPSS@ b*k˕bhQt"N@voʲ|KCEx^ϣsPfDm#p8aF^F.fxOƣ1pFVQVZb3dMTIENDB`eclipse-mercurialeclipse-1.9.4/plugin/icons/ovr/000077500000000000000000000000001173713500500217205ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/icons/ovr/add_ovr.gif000066400000000000000000000002721173713500500240260ustar00rootroot00000000000000GIF89a 8 .F $#@ 8 /@ )r)r 6~ 7~ 7~ T T S ] !, 7 v$B y-uE+tQa_E#@$dc<CX D'4S;eclipse-mercurialeclipse-1.9.4/plugin/icons/ovr/edited_ovr.gif000066400000000000000000000002471173713500500245360ustar00rootroot00000000000000GIF89am@l._(V>U~&Ix3Py`~{Fnͧ!,$$JQ9F Q0 @DeI(Xc;eclipse-mercurialeclipse-1.9.4/plugin/icons/ovr/pinned_ovr.gif000066400000000000000000000001651173713500500245540ustar00rootroot00000000000000GIF89a2]r6a.R'>5XrI}Qʁn! ,"pE Ksn&VdAF(1JE;eclipse-mercurialeclipse-1.9.4/plugin/icons/release_rls.gif000066400000000000000000000004741173713500500241060ustar00rootroot00000000000000GIF89a%*5KvCs8IKLụɠ ٤Ȝ"Ė'..339<!%,YpH,"`  f`ꄖj;}nZЋ)H1` dX=mVz m V"  !V# #b$BA;eclipse-mercurialeclipse-1.9.4/plugin/icons/reltopics_co.gif000066400000000000000000000002461173713500500242700ustar00rootroot00000000000000GIF89a}Мz˳s߿w! ,S0I54OYGQ"vjrai@B݇"dHwB%fLX% V2*u~AWD;eclipse-mercurialeclipse-1.9.4/plugin/icons/rem_co.gif000066400000000000000000000005361173713500500230510ustar00rootroot00000000000000GIF89aRUUXWZWZRTUVy{z{z{z|RVNRNRRUototptIO[e[dKQKQ`i`ifmq{ޜӋh^i^i^l`wlۥd]_Z_[_[njecZXZY!-,{pH,GgS|XDV'a 7* N'(!⦔8F&d%fVPeH-  H  EBC, C\BB-A;eclipse-mercurialeclipse-1.9.4/plugin/icons/root.gif000066400000000000000000000001241173713500500225610ustar00rootroot00000000000000GIF89a\z!,%HzwҕQƍSZ,J;eclipse-mercurialeclipse-1.9.4/plugin/icons/sample_hg.gif000066400000000000000000000017101173713500500235370ustar00rootroot00000000000000GIF89aE>A̰ٞϺʩH@QkDy[}̥ȩmzfzlX7E4ctZP?mNBc_G JQ?vRGhzkQHcYGZJXJyǰĸ]LmæE2|KZHPPP@?" ?-Pt@%0}]G?:Ա&O2NW%<ш1yj (NGDT$K 6Aр pQr ^Iǎ;eclipse-mercurialeclipse-1.9.4/plugin/icons/tags.gif000066400000000000000000000005541173713500500225430ustar00rootroot00000000000000GIF89a~rqgjV`Va?TDW(F3Mfr 8l|獱bchjmqsvĪ!8,@(Hf E@4 !vg9b/%Ӊ$)I䉲 w--.*C %& 8   G  ,,, 7B G COCA;eclipse-mercurialeclipse-1.9.4/plugin/icons/undo_edit.gif000066400000000000000000000005431173713500500235550ustar00rootroot00000000000000GIF89a؋ʋߴޅ߉͸uչԶ_©fҿǘIërμy|~qnsqvkml!4,@pH, s$ɳHLիp4@ED T愊&J@/ @AR !4&   &C00C.  .D,// "H4--D32D11A;eclipse-mercurialeclipse-1.9.4/plugin/icons/wizards/000077500000000000000000000000001173713500500225755ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/icons/wizards/cleanmanifest_wiz.png000066400000000000000000000110411173713500500270020ustar00rootroot00000000000000PNG  IHDRKBA+"gAMA7tEXtSoftwareAdobe ImageReadyqe<IDATx\{YΙםܽq֎EP4DQ!T!H<H*J@JD*GDMRRǮ$&^}9|ܹ3wzwwgϜ3;} wߜ҄eO`IdHP""<(E-$7Ȃ36E53BpuG =7KQj,ҤdOOͮȀߞ+p!EOJS&=ny9)$Pl, XqezjrD T?䱏,XO|oACu+*>EFai ۽o)҂FyeR0N ]lXIG#*1"ݿ}7 4?}/|$EC?{8r l+Lg%Di"(MWB Q(Ave{kpgs/F@i(QT`ѯڂ6PV 4]ҝ\#Zzizpyi9wXHu??Uܩ=2Ls$DhvKp"wD}$V3WL*Pg+{ޭJ4cz{`7l@zt}4-M JЦm=iNj,f[CGE%0,Wu|QFz' :yx|O(eITD2li 0iঃaDݜ5VA%kt0M `7ffMl[`IBc qM߆J#Ozٝa "ʄ25049F503G2sf =Z!A̞֡c'X]]gXzB>~ , |9X T+h5@EBΛ d> KWvQ ķV>' ꍦrCC;r0C%h)!).!Kӆ >2Ę49,Pi  qA(a#X/U1hI1 fLE}@F( i!`, -E R@P{dј၂)ynaQPM jزYQ'$?xې0:hD(C1 ޖծ P2ׅǹ79X ^Jikɽ]+ nr5J9H6`"Y BאP$+0',nu+/ =u)M2u٩yh6N0DZ!ٻtYP)S!'[SC~Hz޻4džI$EDŽ@_B}9("H'~ `?j$5_O8)DxӖ>λPňZ:zMiOAx%B9ݍ( "H=h)CO`=P܃ Elhr"6̐o1R. {EQhE݁jTo) Oeɣ2JUQY(tr@Xך=#;^Ԕ gb;4V92fL_/~0Oߞ_v'"m[ h>V>r>})nR7޺B HƇC- [S z4*qvHUXw{\?b8vHgTW@jAdJl@IJE(ljA@: <1O>8|K'# X\E1RHu[a%y.n&e&Xo|l߬5޻\(&""u `|%͊5| W1.R$Sf9`dR@{?| z:WoORrt50,do˒62Ζ9,4xO~Nlsoƀ^ (iDJ4N\ ޚ/8*"έxr yvd$3*+k? yXt,* ,a 2LȘ,dcr,P^]SKHA].0lK$х1W4g[aaէ(=ՔvZD4dmmT8B6Wfڮr"ϔ/aМ WlagB+i]_jSM)M둬~Hj9+5x%M*I*Jl MVĀkC&cP7?{Rި78CgSZG0:S酺1yzҚ_qgw86CcU pf_CG'g,CǐFR'>DU4j_Ms5i'с~9H $Go8| UC7`]U:SMsjի[MKo r7Vp aDZadl˄Jk얨ۏGFwNR%o9R$z.0?$so=c|T 'R3Ю\Y[]sjODžG܊*Hc_ENxf߁{2WmچyMmo.q-kf`՜@g3L7o.9CyٚRZK%빤vZk:kOn8|ۯ< _YYP| B/)ͦgޝsKn Z@Z?z=83~;wa`k(U``fϿZk`܋@1 ܅T}~`-Z6kv?j &?-bw㳯}aچY0u1A\&S; >Hy/!d.B4 (0f'^NH5G.xݟdd &Z?hYQ"I-`$[y!nF(qp3Yw\Xep>$B7H7ͥTkR:5dPA[.y,-U)ɌBTC MyMCn=@:Q44 2n. @^J3Ca(c"Ao[mυH"+g)>x\dd1Z9Tz#nűmc@/'\육Sև AM#NEU&eZqt|᩸8abL-iPR;yysJԖ !kľV@0T  qOs/Z20 Rߑ@/>X) j$ OJ JL4VU} 6IENDB`eclipse-mercurialeclipse-1.9.4/plugin/icons/wizards/droplets-50.png000066400000000000000000000054441173713500500253700ustar00rootroot00000000000000PNG  IHDR21bKGD IDAThZyT?EyݰZ+p/.x]ch0RD`XwonOJ$BPBi0RQ*Ҡr~^g :t?9{w|?߽1Dʶn]EVJV{A?;۷ckjj:dO˗/yyywލ\z]p={?~;v9r~ K.1 ===3qϳ(+8p:u]|jSSSu HuuuהCpEmYߘ]rJrrr)ҭ R+)))6d,$$E Ca >>Y*vrQȖ,YR^UU]! K.} X=}2f  {իWRoHDذ7LY"m۶1~Bn 6mr_~=ի#mM4 6/^XL#͛w߿I|m)Uɏnnn5zzzʊG= |)R${ƍ4l3gH6LJ͛73wyfevqƱ3f00H&`ʺbȑk׮z mWtl"DFF6 Y(f__/YYYzUVyR3MMMֹsgŧ;jXZO6uޝ=x`hIS}íY"S551=ȣ"R5j۵kQk @xS$*ij}rJD[JJJԦNzjFҧOd:uA!tHv);xʏ=;1***[Z*-7"DfΜ 8>l|rOc#9s氹sa„ LCC G@$-e+ZbM,d HaHCaaFS&~ 0d`l<-,,eQ{ұcGQ+"4~buxv͋RBqoYRtDiGL>A-ZdFG_~ 7Swح[؎;89e1cϟ bD*(Ǐw e2$ꨂ*DT^7855UR2<R2DG^p*bggԍ%vSV\T܉U@Hbrww 0))R0$"QdFJ@@0NӧOwρ<*H|ZWffO:#k%*?%%T^^Jn<=<2={ƣvѡCl2ΦD':tY||<3g0)MD焊 mYߏdQP`*5e``rALUFFb;r1jnMb889XÇ)͎jpO.>kkk -JcYXtp 9OB3u;4(nx{{́@BQR+jy!H֋jl QI@>B ߿`X={2bIfmmwnn KI&'~hlM" _9&APo=kb$Te,@ qZZAHA^\FFsss9@=zpĬDVegg]x1(݌ۅ\FBQH6\bPsX)Z:8"5]fbb">"鿁N_V P Of͚ŨG4_(MQAƺx(.\ 8P]]-Ѥ4.П0sCZCRSG pA*֗EiU' FOqxG TW(7(8q~\n0#oQ;0!%!/A0ȣ7 lÆ `‚BM_u.Bzm#Fɓ'soRX"cDJx؃ 0htB 8;9"w7݌ NZʹwJߺu+y{yo!*`(46iEnj]UyIY/hh2?,>lxGC T(III>`hrw( qj,J{gWMOK$AݽsWO͛6f 6x0s>ԓtלd-" __CCfe4~633{c7.Ro5מ?֕IENDB`eclipse-mercurialeclipse-1.9.4/plugin/icons/wizards/newconnect_wizban.gif000066400000000000000000000011331173713500500267770ustar00rootroot00000000000000GIF89aK:륷ӆj,K:X0I8ͻ`(VR9l)jβJp4Ƿ&~(_2lhHR]aiK]G YH0jNklp[|Iyw!G0l|b PoGwpnU`Գѭ%ŸTY׭ٷdYYwo\5eecDBy 1+U…wIx;jfU_œ ' 9M 1*td=Xᝲs'˖K='H>;nhn D(qKQ)T,:p+R=`~=uM`Ă o^3okZ3,0E<;Ut"H{4Usd3s׮8#E=mE:aRS 2 c`Y<+D2;q𢤆%m ԥLq)(YAyS ҁ_1a0`fvB;eclipse-mercurialeclipse-1.9.4/plugin/icons/wizards/newlocation_wiz.gif000066400000000000000000000005661173713500500265060ustar00rootroot00000000000000GIF89a2ża98õ#v&ã&ȹV´:yMŽ%Buƪ5utX݃%ڦ$ݡkת!2,@pH,/ktRH>0uz<@fD*AcdBG|E"+j| !2)CyUW2'Dyxy  jCCA;eclipse-mercurialeclipse-1.9.4/plugin/icons/wizards/newstream_wizban.gif000066400000000000000000000045601173713500500266500ustar00rootroot00000000000000GIF89aK:Ȱҷ•ƚĢɥ̨ͿėœƜşȞǡɥˬЩͬϯҰѳԷֺŞdz,K:) H*\ȰÇ#J$Xŋhȱc'DrR $[T9Q Ɨc,irJ-\i /f̍3K̹EϞC JuիV[j F!S3*UXHZm,ph9n) f+V%YRb]AEY0rE H@ފ26Ule|72 %R0QJ]cvWȚ[pZ8]bu+V\2DĈ$&@"Ǒ~y`i%Іja,x ȅ1dDt@Q0eJu̶q;5ң]=Vj-7_}S@AQf%D!$XXueTVYȉ(2bIiDP!ɭ 'EFуHxf#LNair3JăTD>B4CW$n)9țp9%&tG_:˜@F Ё,FDiY R%t ȧXR9a= e6:tЁM@CDbܥ!+%w &ep 4Pj$ȸ{F;nw#@ P?BzjYf <0$|0Li-TlŖ1e 83`[ÿJ(CbhuY` <# ßΪ/ڮdA!:5U6gA^%1׮|S*@6̀C4IH=5Y}xwB aw%]em j>)I X" u5h e1wyL*"9Um.٧E0lW UUUj2p3]xSڥ@Mnn+,e3OApBh%9eâܤ)숢r`M/Hnݚx]_@;eclipse-mercurialeclipse-1.9.4/plugin/icons/wizards/share_wizban.png000066400000000000000000000140241173713500500257600ustar00rootroot00000000000000PNG  IHDRKBA+" pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3gAMA|Q cHRMz%u0`:o_F 1IDATx{pT}?]I7B4$cc\\Z8N3! ɴ&nLN;6LӴtښ&-q2ub4ؐXuY7}&n^_j0ol8{''\^[|mϾN-' 9s Ջ{{IgG'^[g:z~]rxCmYiӦ~!ۋ.zܺ@O]Zɰ :]Ӿj:zp_/dmtF=çg~,k&а2HttSTV`p@=[L4O/KENϩ$B*w8= [M4EOԟ:e(n|Ld-, -g18fz~:d WPҪ\O\ΈuIEQ-G=Q*xD B $\E0Ѹ{K)U0` I)@‘vRm,خ $@v3ro,9jdLX$LdH))+$(gp ȏj8.P?\)ENj H*IOJrΛZ[ ftDmҢRU$(PUwUK뼨Wd뎃ԍ+Z@wԢ'`> ɲ$>XbBU1?'DJ"v)ç9}GVJ}uHUa[Z^GʁrazӧM& $J)H*V|d,Yz u6]4Cq}, RJ~, ˊwA`l9{` ۷F# % $EZ捳Fj~wl[{e l'[73 ,cjuE>3/fY$G ٶ)ex\Gi353PSϷMKyP=qI$qy+ClޑYԕ=z;ߛހ&s7SQU- Hi{:/R;>_? uL;LŽ3?^_+0pԹ4X~|keL+" /":w7@J}p,H%BfR.#xY{Qe@kMҶqEӮ\Cx'm;cьTW_6:8Y-<ųdhA'ڜ:x(e$#Cc+Tbt8zh4Fquьt! ҧ{ʜ4XB qCΗYBT7ػk &}28'u'+%-zMdFnnOۇZaj=_OIqA`Ҕ]T|áv8g3s6dɝ9xNN#E:7.7 Qw]C?oCFVf1KG( ܯrW B{ts|ËP: WoϖwQSg'1 (аiw݋њ7ėY´t.1ڭR) ZLɊjV5<_(r}"?|e7mmN j ҕ>WŀJ;Z\8hmx 9Kr@$Uf؉K8Zܒrأmg"x{Q=_;+9bpXΓP%mFJ'" ZԄz{{CBBʪ3a7S'Qvzzzl}JIzRb<7oح@~~>899t ?oB@F=^;՟8Af&_՗6111XCڦN d_ʹ+HFZWh֭[4]+0_|/, fii9{nػw/kN>>>݃eee?)OLH 'Q ]]]ؾ};hhh)x -@#۴7#d>Cmllض/.X)VkkkfHJ6v;'t5`"1##'cַ:/0ݔV IENDB`eclipse-mercurialeclipse-1.9.4/plugin/plugin.properties000066400000000000000000000157441173713500500234260ustar00rootroot00000000000000#Properties file for mercurialeclipse mercurial = Mercurial mercurialSynchronizeWizard = Mercurial synchronize wizard MercurialEclipseDecorations = Mercurial labelDecorationsForMercurialEclipse = Shows status information about resources in projects under Mercurial control. commitMerge = Commit Merge... commit = Commit... update = Update rootHistory = Show Root History tags = Tags... bookmarks = Bookmarks... merge = Merge... updateTo = Switch To... showAnnotation = Show Annotation add = Add... ignore = Ignore... rollback = Rollback pull = Pull... push = Push... rebase = Rebase... resolve = Mark as Resolved sign = Sign... backout = Backout... transplant = Transplant... strip = Strip... serve = Serve... branch = Add Branch... disconnect = Disconnect qimport = Qimport... qinit = Qinit... qnew = Qnew... qrefresh = Qrefresh... qdelete = Qdelete... synchronize = Synchronize... synchronizeWith = Synchronize With... synchronizeWithLocalRepo = Show Local Changes refreshStatus = Refresh Status importPatchFromFileOrClipboard = Import patch from file or clipboard (hg import) importPatch = I&mport Patch... exportPatchToFileOrClipboard = Export patch to file or clipboard (hg diff) exportPatch = E&xport Patch... menuLabel.team = T&eam menuLabel.undo = Undo menuLabel.extensions = Extensions menuLabel.mqueue = Mqueue actionLabel.applyPatch = Apply Patch... actionLabel.commit = Commit... actionLabel.compareWithRevision = Compare With Revision... actionLabel.showAnnotation = Show Annotation actionLabel.remove = Remove from Repository actionLabel.removeTooltip = hg remove actionLabel.showHistory = Show &History actionLabel.showHistoryTooltip = hg log actionLabel.revert = &Revert... actionLabel.revertTooltip = hg revert actionLabel.compare.anotherRevision = Another Revision... actionLabel.compare.anotherChangeset = Another Changeset... actionLabel.compare.anotherChangesetTooltip = hg diff actionLabel.compare.parentChangeset = Parent Changeset actionLabel.compare.parentChangeSetTooltip = hg diff timeouts = Timeouts synchronize = Synchronize performance = Performance history = History console = Console cloneRepository = Clone Mercurial repository importFromRepository = Projects from Local Mercurial Repository importFile = Import a file from the local file system into the workspace. cloneRepository2 = Clone Existing Mercurial Repository createRepository = Create New Mercurial Repository hgQuickDiff = Mercurial Quick Diff mergeViewName = Mercurial Merge repositoryViewName = Mercurial Repositories patchQueueViewName = Mercurial Patch Queue consoleName = Mercurial Console shelveDescription = Shelve shelveName = Shelve unshelveDescription = Unshelve unshelveName = Unshelve compareWithParentDescription = Compare With Parent Changeset compareWithParentName = Compare With Parent compareWithRevisionName = Compare With Revision showAnnotationsName = Show Annotations showHistoryName = Show History revertName = Revert compareWithPrevious = Compare With Previous compareWithCurrent = Compare With Current Bundle-Vendor.0 = MercurialEclipse project Bundle-Name.0 = MercurialEclipse colorDefinition.label.addedForeground = Added (Foreground) colorDefinition.description.addedForeground = This color is used for the foreground color for resources that have been added. colorDefinition.label.addedBackground = Added (Background) colorDefinition.description.addedBackground = This color is used for the background color for resources that have been added. fontDefinition.label.addedFont = Added Font fontDefinition.description.addedFont = The font used to display added resources. colorDefinition.label.unknownForeground = Unknown (Foreground) colorDefinition.description.unknownForeground = This color is used for the foreground color for resources that are unknown to Mercurial. colorDefinition.label.unknownBackground = Unknown (Background) colorDefinition.description.unknownBackground = This color is used for the background color for resources that are unknown to Mercurial. fontDefinition.label.unknown = Unknown Font fontDefinition.description.unknown = The font used to display unknown resources. colorDefinition.label.conflictForeground = Conflict (Foreground) colorDefinition.description.conflictForeground = This color is used for the foreground color for resources that have conflicts. colorDefinition.label.conflictBackground = Conflict (Background) colorDefinition.description.conflictBackground = This color is used for the background color for resources that have conflicts. fontDefinition.label.conflict = Conflict Font fontDefinition.description.conflict = The font used to display resources with conflicts. colorDefinition.label.deletedFg = Deleted (Foreground) colorDefinition.description.deletedFg = This color is used for the foreground color for resources that are deleted. colorDefinition.label.deletedBg = Deleted (Background) colorDefinition.description.deletedBg = This color is used for the background color for resources that are deleted. fontDefinition.label.deleted = Deleted Font fontDefinition.description.deleted = The font used to display deleted resources. colorDefinition.label.removedFg = Removed (Foreground) colorDefinition.description.removedFg = This color is used for the foreground color for resources that have been removed. colorDefinition.label.removedBg = Removed (Background) colorDefinition.description.removedBg = This color is used for the background color for resources that have been removed. fontDefinition.label.removed = Removed Font fontDefinition.description.removed = The font used to display removed resources. colorDefinition.label.changedFg = Changed (Foreground) colorDefinition.description.changedFg = This color is used for the foreground color for resources that have changes. colorDefinition.label.changedBg = Changed (Background) colorDefinition.description.changedBg = This color is used for the background color for resources that have changes. fontDefinition.label.changed = Changed Font fontDefinition.description.changed = The font used to display changed resources. colorDefinition.label.ignoredFg = Ignored (Foreground) colorDefinition.description.ignoredFg = This color is used for the foreground color for resources that are ignored. colorDefinition.label.ignoredBg = Ignored (Background) colorDefinition.description.ignoredBg = This color is used for the background color for resources that are ignored. fontDefinition.label.ignored = Ignored Font fontDefinition.description.ignored = The font used to display ignored resources. fontDefinition.label.console = Mercurial Console Font fontDefinition.description.console = The font used to display console messages. history.decorator.label = Mercurial file status in views and dialogs history.decoratorDescription = Decorates file elements with their status in Mercurial plugin dialogs and views repositoryPage.name = Mercurial Repository navigatorContent.name = Mercurial Changesets extension.name = Mercurial Changesets bundleRepoWizard.name = Export Selected Repository as Mercurial Bundle openSelectedRevision=Open Selected Version openCurrentRevision=Open Current Version searchMenu.label=Se&archeclipse-mercurialeclipse-1.9.4/plugin/plugin.xml000066400000000000000000002467371173713500500220420ustar00rootroot00000000000000 %labelDecorationsForMercurialEclipse %history.decoratorDescription Clone existing local or remote Mercurial repository Import one or more projects from local Mercurial repository Clone existing local or remote Mercurial repository Create new local Mercurial repository or new remote repository location %colorDefinition.description.addedForeground %colorDefinition.description.addedBackground %fontDefinition.description.addedFont %colorDefinition.description.unknownForeground %colorDefinition.description.unknownBackground %fontDefinition.description.unknown %colorDefinition.description.conflictForeground %colorDefinition.description.conflictBackground %fontDefinition.description.conflict %colorDefinition.description.deletedFg %colorDefinition.description.deletedBg %fontDefinition.description.deleted %colorDefinition.description.removedFg %colorDefinition.description.removedBg %fontDefinition.description.removed %colorDefinition.description.changedFg %colorDefinition.description.changedBg %fontDefinition.description.changed %colorDefinition.description.ignoredFg %colorDefinition.description.ignoredBg %fontDefinition.description.ignored %fontDefinition.description.console eclipse-mercurialeclipse-1.9.4/plugin/plugin_zh.properties000066400000000000000000000070011173713500500241120ustar00rootroot00000000000000#Properties file for mercurialeclipse mercurialSynchronization = Mercurial \u540c\u6b65 mercurialSynchronizeWizard = Mercurial \u540c\u6b65\u5411\u5bfc MercurialEclipseDecorations = Mercurial Eclipse\u4fee\u9970 labelDecorationsForMercurialEclipse = Mercurial eclipse\u63d2\u4ef6\u7684\u56fe\u6807\u4fee\u9970. commitMerge = \u63d0\u4ea4\u5408\u5e76... commit = \u63d0\u4ea4(C)... update = \u66f4\u65b0(U) tags = \u6807\u8bb0(T)... bookmarks = \u4e66\u7b7e(B)... merge = \u5408\u5e76... updateTo = \u66f4\u65b0\u81f3... showAnnotation = \u663e\u793a\u6ce8\u91ca(A) add = \u6dfb\u52a0... ignore = \u5ffd\u7565... rollback = \u56de\u6eda pull = \u62c9... push = \u63a8... rebase = Rebase... sign = \u7b7e\u540d... backout = Backout... transplant = Transplant... strip = \u79fb\u9664... serve = \u670d\u52a1... branch = \u5206\u652f(B)... disconnect = \u65ad\u5f00\u8fde\u63a5 qimport = Qimport... qinit = Qinit... qnew = Qnew... qrefresh = Qrefresh... qdelete = Qdelete... synchronize = \u540c\u6b65(S)... refreshStatus = \u5237\u65b0\u72b6\u6001(R) importPatchFromFileOrClipboard = \u5bfc\u5165\u8865\u4e01(hg import) importPatch = \u5bfc\u5165\u8865\u4e01... exportPatchToFileOrClipboard = \u5bfc\u51fa\u8865\u4e01(hg diff) exportPatch = \u5bfc\u51fa\u8865\u4e01(&E)... menuLabel.commitMerge = \u63d0\u4ea4\u5408\u5e76(&C)... menuLabel.commit = \u63d0\u4ea4(&C)... menuLabel.push = \u63a8(&P)... menuLabel.pull = \u62c9(&L)... menuLabel.update = \u66f4\u65b0(&U) menuLabel.updateTo = \u66f4\u65b0\u81f3... menuLabel.tags = \u6807\u8bb0(&T)... menuLabel.bookmarks = \u4e66\u7b7e... menuLabel.branch = \u5206\u652f(&B)... menuLabel.merge = \u5408\u5e76(&M)... menuLabel.rebase = Rebase... menuLabel.showAnnotation = \u663e\u793a\u6ce8\u91ca(&A) menuLabel.undo = \u6062\u590d menuLabel.backout = Backout... menuLabel.rollback = \u56de\u6eda menuLabel.strip = \u526a\u9664... menuLabel.extensions = \u63d2\u4ef6 menuLabel.mqueue = mqueue menuLabel.qimport = qimport... menuLabel.qinit = qinit... menuLabel.qnew = qnew... menuLabel.qrefresh = qrefresh... menuLabel.qdelete = qdelete... menuLabel.sign = \u7b7e\u540d... menuLabel.transplant = Transplant... menuLabel.serve = \u670d\u52a1... menuLabel.synchronize = \u540c\u6b65... menuLabel.add = \u6dfb\u52a0... menuLabel.ignore = \u5ffd\u7565(&I)... menuLabel.refreshStatus = \u5237\u65b0\u72b6\u6001 menuLabel.disconnect = \u65ad\u5f00\u8fde\u63a5 actionLabel.remove = \u4e0d\u505a\u7248\u672c\u63a7\u5236 actionLabel.removeTooltip = hg remove actionLabel.showHistory = \u663e\u793a\u5386\u53f2(&H) actionLabel.showHistoryTooltip = hg log actionLabel.revert = \u64a4\u9500(&R)... actionLabel.revertTooltip = hg revert actionLabel.compare.anotherChangeset = \u53e6\u5916\u4e00\u4e2a\u4fee\u8ba2\u96c6 actionLabel.compare.anotherChangesetTooltip = hg diff actionLabel.compare.parentChangeset = \u7236\u4fee\u8ba2\u96c6 actionLabel.compare.parentChangeSetTooltip = hg diff timeouts = \u8d85\u65f6 performance = \u6027\u80fd console = \u63a7\u5236\u53f0 cloneRepository = \u4f7f\u7528Mercurial\u514b\u9686\u7248\u672c\u5e93 importFile = \u4ece\u672c\u5730\u6587\u4ef6\u7cfb\u7edf\u5bfc\u5165\u6587\u4ef6\u5230\u5de5\u4f5c\u533a\u95f4. cloneRepository2 = \u4f7f\u7528Mercurial\u514b\u9686\u7248\u672c\u5e93 hgQuickDiff = Hg Quick Diff mergeViewName = \u5408\u5e76 repositoryViewName = \u5e93 patchQueueViewName = \u8865\u4e01\u961f\u5217 consoleName = Mercurial\u63a7\u5236\u53f0 shelveDescription = Shelve shelveName = Shelve unshelveDescription = Unshelve unshelveName = Unshelve commandLabel.shelve = Shelve commandLabel.unshelve = Unshelveeclipse-mercurialeclipse-1.9.4/plugin/resources/000077500000000000000000000000001173713500500220115ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/resources/search.xcf000066400000000000000000000117401173713500500237630ustar00rootroot00000000000000gimp xcf v001BB2gimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) { <Background copy     [oʭʏʏʏnȣnnn}n}}nnnnnnnnnnnMʫMMMVMVVMMMMMMMMMMM۲ ɛV.#?Jx'z Hg#1     =gimp-text-layer!(text "Hg") (font "Arial Bold") (font-size 8.000000) (font-size-unit pixels) (hinting yes) (antialias no) (language "en-us") (base-direction ltr) (color (color-rgb 0.000000 0.000000 0.000000)) (justify left) (box-mode fixed) (box-width 11.000000) (box-height 11.000000) (box-unit pixels) a u xxx Hg       xxx Background copy#2      ߪ(kĹI{ {䴭  bmߐoղ||Բyyt t᫣on}nrnon n ===>>>_poA햼AfBBbEENGG];JJ];MM];P P;㲫N;E\MEVMEQMɍNMɍ}M         cBackground copy#1        ѧʪL=~K/KiSS]#EVdѧʪL=~K/JiSS]"EVdѧʪL=~K/KiSS]#EVd۲ ɛV.#?Jx'zBackground (0ms) copy     0   𐲹ĹIIľomߐmoղԲ}ղ»rľon}nrnonn;Nbf;Wf;Wb;WN;W];_\];_ŽV];_ƿP];_N;9\M9VM9QMsɍNMɍ}M       Background (0ms)     ƲĹIľߐmoղ벥}ڥ»rѰn}nrnonn;bf;Wڳf;WЪb;W՞N;WΒ];_\];_ŽV;_ƿP]՗9\M9VM9QMsɍNMɍ}M        New Layer     Selection Mask copy 1  Reclipse-mercurialeclipse-1.9.4/plugin/src/000077500000000000000000000000001173713500500205665ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/000077500000000000000000000000001173713500500213445ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/000077500000000000000000000000001173713500500231405ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/000077500000000000000000000000001173713500500263705ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/AdapterFactory.java000066400000000000000000000032261173713500500321460ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Zsolt Koppany (Intland) - bug fixes * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.team.ui.history.IHistoryPageSource; import com.vectrace.MercurialEclipse.history.MercurialHistoryPageSource; import com.vectrace.MercurialEclipse.history.MercurialHistoryProvider; import com.vectrace.MercurialEclipse.model.HgRoot; public class AdapterFactory implements IAdapterFactory { @SuppressWarnings("unchecked") public MercurialHistoryPageSource getAdapter(Object adaptableObject, Class adapterType) { if((adaptableObject instanceof MercurialHistoryProvider) && adapterType == IHistoryPageSource.class) { return new MercurialHistoryPageSource((MercurialHistoryProvider) adaptableObject); } if((adaptableObject instanceof HgRoot) && adapterType == IHistoryPageSource.class) { return new MercurialHistoryPageSource(null); } return null; } @SuppressWarnings("unchecked") public Class[] getAdapterList() { return new Class[] { IHistoryPageSource.class }; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/DefaultConfiguration.java000066400000000000000000000073061173713500500333550ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan - implementation * Andrei Loskutov - bug fixes * Philip Graf - use default timeout from preferences *******************************************************************************/ package com.vectrace.MercurialEclipse; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import com.vectrace.MercurialEclipse.commands.IConfiguration; import com.vectrace.MercurialEclipse.commands.IConsole; import com.vectrace.MercurialEclipse.commands.IErrorHandler; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.preferences.TimeoutPreferencePage; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.views.console.HgConsoleHolder; /** * @author Stefan */ public class DefaultConfiguration implements IConsole, IErrorHandler, IConfiguration { public DefaultConfiguration() { } public String getExecutable() { if (!MercurialEclipsePlugin.getDefault().isHgUsable()) { MercurialUtilities.configureHgExecutable(); MercurialEclipsePlugin.getDefault().checkHgInstallation(); } return MercurialEclipsePlugin.getDefault().getPreferenceStore() .getString(MercurialPreferenceConstants.MERCURIAL_EXECUTABLE); } public String getPreference(String preferenceConstant, String defaultIfNotSet) { return MercurialUtilities.getPreference(preferenceConstant, defaultIfNotSet); } public void logError(Throwable e) { MercurialEclipsePlugin.logError(e); } public void logWarning(String message, Throwable e) { MercurialEclipsePlugin.logWarning(message, e); } public int getTimeOut(String commandId) { int timeout = TimeoutPreferencePage.DEFAULT_TIMEOUT; String pref = getPreference(commandId, String.valueOf(timeout)); try { timeout = Integer.parseInt(pref); if (timeout < 0) { throw new NumberFormatException(Messages.getString("DefaultConfiguration.timoutLessThanEqual")); //$NON-NLS-1$ } } catch (NumberFormatException e) { logWarning(Messages.getString("DefaultConfiguration.timeoutForCommand") + commandId //$NON-NLS-1$ + Messages.getString("DefaultConfiguration.notCorrectlyConfigured"), e); //$NON-NLS-1$ } return timeout; } /* * ====================================================== * * IConsole methods below * * ====================================================== */ public void commandCompleted(final int exitCode, final long timeInMillis, final String message, final Throwable error) { int severity = IStatus.OK; switch (exitCode) { case 0: severity = IStatus.OK; break; case 1: severity = IStatus.OK; break; default: severity = IStatus.ERROR; } HgConsoleHolder .getInstance() .getConsole() .commandCompleted(timeInMillis, new Status(severity, MercurialEclipsePlugin.ID, message), error); } public void commandInvoked(final String command) { HgConsoleHolder.getInstance().getConsole().commandInvoked(command); } public void printError(final String message, final Throwable root) { HgConsoleHolder.getInstance().getConsole().errorLineReceived(root.getMessage()); } public void printMessage(final String message, final Throwable root) { HgConsoleHolder.getInstance().getConsole().messageLineReceived(message); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/HgFeatures.java000066400000000000000000000161731173713500500313000ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import org.eclipse.jface.preference.IPreferenceStore; import org.osgi.framework.Version; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; /** * Features of the underlined mercurial executable. HgFeatures are version dependent and so will be * enabled/disabled based on the currently used mercurial binaries. *

* Note that the right enablement state will be set some time after plugin startup, so that in a * short time between plugin activation and {@link MercurialEclipsePlugin#checkHgInstallation()} * features might be not yet initialized properly. Initially all features are disabled. * * @author andrei */ public enum HgFeatures { BRANCH (new Version(1,5,0), "--branch", true), NEW_BRANCH (new Version(1,6,0), "--new-branch", false, MercurialPreferenceConstants.PREF_PUSH_NEW_BRANCH), LISTFILE (new Version(1,8,0), "listfile:", false), INSECURE (new Version(1,7,5), "--insecure", false); private final Version required; private final String[] optionalPreferenceKeys; private boolean enabled; private final String cmd; private final boolean mandatory; private HgFeatures(Version required, String cmd, boolean mandatory, String ... optionalPreferenceKeys) { this.required = required; this.cmd = cmd; this.mandatory = mandatory; this.optionalPreferenceKeys = optionalPreferenceKeys; } @Override public String toString() { return getHgCmd() + (isEnabled() ? "(enabled)" : "(disabled)") + ", requires " + getRequired() + " hg version"; } /** * @return true if this is a mandatory command and there is no chance to * workaround the absence of the required mercurial version */ public boolean isMandatory() { return mandatory; } public String getHgCmd() { return cmd; } /** * @return the (smallest) required version, never null */ public Version getRequired() { return required; } public void applyTo(IPreferenceStore store) { for (String key : optionalPreferenceKeys) { store.setDefault(key, enabled); if(!enabled) { store.setValue(key, false); } } } /** * @param enabled true if the option should be enabled */ public void setEnabled(boolean enabled) { this.enabled = enabled; } /** * Note that the right enablement state will be set some time after plugin startup, so that in a * short time between plugin activation and {@link MercurialEclipsePlugin#checkHgInstallation()} * features might be not yet initialized properly. Initially all features are disabled. * * @return true if the option is enabled (supported by mercurial) */ public boolean isEnabled() { return enabled; } /** * @param current observed mercurial version */ public static void setToVersion(Version current) { HgFeatures[] values = HgFeatures.values(); for (HgFeatures feature : values) { feature.setEnabled(doCompare(feature.getRequired(), current)<= 0); } } /** * @param current * observed mercurial version * @return true if mandatory options are satisfied with given version, false if at * least one requires greater mercurial version */ public static boolean isSupported(Version current) { HgFeatures[] values = HgFeatures.values(); boolean result = true; for (HgFeatures feature : values) { if(!feature.isMandatory()) { continue; } result &= doCompare(feature.getRequired(), current)<= 0; } return result; } /** * @param current * observed mercurial version * @return true if all features are satisfied with given version, false if at * least one requires greater mercurial version */ public static boolean isHappyWith(Version current) { HgFeatures[] values = HgFeatures.values(); boolean result = true; for (HgFeatures feature : values) { result &= doCompare(feature.getRequired(), current)<= 0; } return result; } public static void applyAllTo(IPreferenceStore store) { HgFeatures[] values = HgFeatures.values(); for (HgFeatures feature : values) { feature.applyTo(store); } } public static Version getPreferredVersion() { return Collections.max(Arrays.asList(HgFeatures.values()), new Comparator() { public int compare(HgFeatures o1, HgFeatures o2) { return doCompare(o1.getRequired(), o2.getRequired()); } }).getRequired(); } public static Version getLowestWorkingVersion() { return Collections.min(Arrays.asList(HgFeatures.values()), new Comparator() { public int compare(HgFeatures o1, HgFeatures o2) { if(o1.isMandatory() && !o2.isMandatory()) { return -1; } else if(!o1.isMandatory() && o2.isMandatory()){ return 1; } return doCompare(o1.getRequired(), o2.getRequired()); } }).getRequired(); } public static String printSummary() { StringBuilder sb = new StringBuilder(); HgFeatures[] values = HgFeatures.values(); for (HgFeatures feature : values) { sb.append(feature.toString()).append("\n"); } return sb.toString(); } /** * Support comparing versions without requiring a particular version of OSGi. * * See: http://computerfloss.com/2011/11/a-little-problem-in-the-osgi-version-class/ * * Remove after Eclipse 3.6 is not supported. * * @param v1 The left version * @param v2 The right version * @return The result of left.compareTo(right) * @see Version#compareTo(Version) * @see Version#compareTo(Object) */ protected static int doCompare(Version v1, Version v2) { Class versionClass = Version.class; Method compareToMethod = null; try { // Works on Eclipse 3.7 compareToMethod = versionClass.getMethod("compareTo", Version.class); } catch (NoSuchMethodException e1) { // "We're on Eclipse 3.6 or earlier. Fall back compareTo(Object)."; try { // Works on Eclipse 3.6 and earlier compareToMethod = versionClass.getMethod("compareTo", Object.class); } catch (NoSuchMethodException e2) { MercurialEclipsePlugin.logError("Unexpected error: cannot find compareTo() in Version", e2); return 0; } } try { return ((Integer)compareToMethod.invoke(v1, v2)).intValue(); } catch (IllegalArgumentException e) { MercurialEclipsePlugin.logError("Unexpected error: comparing version", e); } catch (IllegalAccessException e) { MercurialEclipsePlugin.logError("Unexpected error: comparing version", e); } catch (InvocationTargetException e) { MercurialEclipsePlugin.logError("Unexpected error: comparing version", e); } return 0; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/HgRevision.java000066400000000000000000000031371173713500500313140ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Charles O'Farrell - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse; public class HgRevision { public static final HgRevision TIP = new HgRevision("tip"); //$NON-NLS-1$ private final String changeset; private final int revision; protected HgRevision(String changeset) { this(changeset, -1); } public HgRevision(String changeset, int revision) { this.changeset = changeset; this.revision = revision; } public String getChangeset() { return changeset; } public int getRevision() { return revision; } @Override public boolean equals(Object obj) { if (obj instanceof HgRevision) { HgRevision r = (HgRevision) obj; return r.revision == revision || r.changeset.equals(changeset); } return false; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return changeset.hashCode(); } @Override public String toString() { return revision + ":" + changeset; //$NON-NLS-1$ } public static HgRevision parse(String s) { int i = s.indexOf(':'); return new HgRevision(s.substring(i + 1), Integer.parseInt(s.substring( 0, i))); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/MercurialEclipsePlugin.java000066400000000000000000000545571173713500500336620ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Jérôme Nègre - some fixes * Stefan C - Code cleanup * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) * Adam Berkes (Intland) - default encoding * Philip Graf - proxy support * Bastian Doetsch - bug fixes and implementation *******************************************************************************/ package com.vectrace.MercurialEclipse; import java.lang.reflect.InvocationTargetException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.net.proxy.IProxyService; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobManager; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DecorationOverlayIcon; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.ui.statushandlers.StatusManager; import org.osgi.framework.BundleContext; import org.osgi.framework.Version; import org.osgi.util.tracker.ServiceTracker; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgDebugInstallClient; import com.vectrace.MercurialEclipse.commands.RootlessHgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.utils.StringUtils; import com.vectrace.MercurialEclipse.views.console.HgConsoleHolder; /** * The main plugin class to be used in the desktop. */ public class MercurialEclipsePlugin extends AbstractUIPlugin { public static final String ID = "com.vectrace.MercurialEclipse"; //$NON-NLS-1$ public static final String ID_CHANGELOG_VIEW = "com.vectrace.MercurialEclipse.views.ChangeLogView"; //$NON-NLS-1$ public static final String BUNDLE_FILE_PREFIX = "bundlefile"; //$NON-NLS-1$ // The shared instance. private static MercurialEclipsePlugin plugin; private static final String HGENCODING; static { // next in line is HGENCODING in environment String enc = System.getProperty("HGENCODING"); // next is platform encoding as available in JDK if (!StringUtils.isEmpty(enc) && Charset.isSupported(enc)) { HGENCODING = enc; } else { if(Charset.isSupported("UTF-8")){ HGENCODING = Charset.forName("UTF-8").name(); } else { HGENCODING = Charset.defaultCharset().name(); } } } // the repository manager private static HgRepositoryLocationManager repoManager = new HgRepositoryLocationManager(); // the commit message manager private static HgCommitMessageManager commitMessageManager = new HgCommitMessageManager(); private boolean hgUsable = true; private ServiceTracker proxyServiceTracker; /** Observed hg version */ public /*final*/ Version hgVersion = Version.emptyVersion; private static final Pattern VERSION_PATTERN = Pattern.compile(".*version\\s+(\\d(\\.\\d)+)+.*", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$ public MercurialEclipsePlugin() { // should NOT do anything until started by OSGI } /** * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) */ @Override public void start(BundleContext context) throws Exception { super.start(context); plugin = this; DefaultConfiguration cfg = new DefaultConfiguration(); HgClients.initialize(cfg, cfg, cfg); proxyServiceTracker = new ServiceTracker(context, IProxyService.class.getName(), null); proxyServiceTracker.open(); final Job job = new Job(Messages.getString("MercurialEclipsePlugin.startingMercurialEclipse")) { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { try { monitor.beginTask(Messages .getString("MercurialEclipsePlugin.startingMercurialEclipse"), 3); //$NON-NLS-1$ monitor.subTask(Messages .getString("MercurialEclipsePlugin.checkingMercurialInstallation")); //$NON-NLS-1$ checkHgInstallation(); monitor.worked(1); // read known repositories monitor.subTask(Messages .getString("MercurialEclipsePlugin.loadingKnownMercurialRepositories")); //$NON-NLS-1$ repoManager.start(); monitor.worked(1); // read in commit messages from disk monitor.subTask(Messages .getString("MercurialEclipsePlugin.startingCommitMessageManager")); //$NON-NLS-1$ commitMessageManager.start(); monitor.worked(1); monitor.done(); return new Status(IStatus.OK, ID, Messages .getString("MercurialEclipsePlugin.startedSuccessfully")); //$NON-NLS-1$ } catch (Throwable e) { hgUsable = false; logError(Messages.getString("MercurialEclipsePlugin.unableToStart"), e); //$NON-NLS-1$ return new Status(IStatus.ERROR, ID, e.getLocalizedMessage(), e); } finally { // show console on startup if configured if (getPreferenceStore().getBoolean( MercurialPreferenceConstants.PREF_CONSOLE_SHOW_ON_STARTUP)) { // open console in SWT GUI Thread new SafeUiJob( Messages.getString("MercurialEclipsePlugin.openingMercurialConsole")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor2) { HgConsoleHolder.getInstance().showConsole(true); return super.runSafe(monitor2); } }.schedule(); } } } }; job.setPriority(Job.SHORT); job.schedule(); // Image registry must be initialized. See first stack trace in http://www.javaforge.com/issue/14327 // Why JFaceResources wasn't initialized I don't know. /*new SafeUiJob(Messages.getString("MercurialEclipsePlugin.startingMercurialEclipse")) { @Override protected IStatus runSafe(IProgressMonitor monitor) { try { getImageRegistry(); } finally { job.schedule(); } return super.runSafe(monitor); } }.schedule();*/ } /** * Checks if Mercurial is configured properly by issuing the hg debuginstall command. */ public void checkHgInstallation() { try { hgUsable = true; MercurialUtilities.getHGExecutable(true); String result = HgDebugInstallClient.debugInstall(); hgVersion = checkHgVersion(); if (!result.endsWith("No problems detected")) { //$NON-NLS-1$ logInfo(result, null); } } catch (Throwable e) { hgUsable = false; MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); hgVersion = Version.emptyVersion; } finally { AbstractShellCommand.hgInitDone(); if(isDebugging()) { System.out.println(HgFeatures.printSummary()); } } } /** * Plugin depends on native mercurial installation, which has to be checked at plugin startup. * Note that the right plugin state will be set only some time after plugin startup, so that in * a short time between plugin activation and * {@link MercurialEclipsePlugin#checkHgInstallation()} call plugin state might be not yet * initialized properly. * * @return true if we have already tried to identify mercurial version (independently if the * check fails or not), false if plugin is still not yet initialized properly */ public static boolean isVersionCheckDone() { MercurialEclipsePlugin mep = MercurialEclipsePlugin.getDefault(); return !mep.isHgUsable() || !mep.getHgVersion().equals(Version.emptyVersion); } private Version checkHgVersion() throws HgException { AbstractShellCommand command = new RootlessHgCommand("version", "Checking for required version") { { isInitialCommand = startSignal.getCount() > 0; } }; Version preferredVersion = HgFeatures.getPreferredVersion(); String version = new String(command.executeToBytes(Integer.MAX_VALUE)).trim(); String[] split = version.split("\\n"); //$NON-NLS-1$ version = split.length > 0 ? split[0] : ""; //$NON-NLS-1$ Matcher matcher = VERSION_PATTERN.matcher(version); boolean failedToParse = !matcher.matches() || matcher.groupCount() <= 0 || (version = matcher.group(1)) == null; if (failedToParse) { HgFeatures.setToVersion(preferredVersion); HgFeatures.applyAllTo(getPreferenceStore()); logWarning("Can't uderstand Mercurial version string: '" + version + "'. Assume that at least " + preferredVersion + " is available.", null); return preferredVersion; } Version detectedVersion = new Version(version); HgFeatures.setToVersion(detectedVersion); HgFeatures.applyAllTo(getPreferenceStore()); if (!HgFeatures.isSupported(detectedVersion)) { throw new HgException(Messages.getString("MercurialEclipsePlugin.unsupportedHgVersion") //$NON-NLS-1$ + version + Messages.getString("MercurialEclipsePlugin.expectedAtLeast") //$NON-NLS-1$ + HgFeatures.getLowestWorkingVersion() + "."); //$NON-NLS-1$ } if (!HgFeatures.isHappyWith(detectedVersion)) { logWarning("Can not use some of the new Mercurial features, " + "hg version greater equals " + preferredVersion + " required, but " + detectedVersion + " found. Features state:\n" + HgFeatures.printSummary() + ".", null); } return detectedVersion; } /** * @return the observer hg version, never null. Returns {@link Version#emptyVersion} in case the * hg version is either not detected yet or can't be parsed properly */ public Version getHgVersion() { return hgVersion; } /** * Gets the repository manager */ public static HgRepositoryLocationManager getRepoManager() { return repoManager; } public static HgCommitMessageManager getCommitMessageManager() { return commitMessageManager; } @Override public void stop(BundleContext context) throws Exception { try { repoManager.stop(); // save commit messages to disk commitMessageManager.stop(); proxyServiceTracker.close(); MercurialUtilities.disposeColorsAndFonts(); } finally { super.stop(context); } } /** * Returns the shared instance. */ public static MercurialEclipsePlugin getDefault() { return plugin; } /** * Returns an image descriptor for the image file at the given plug-in relative path. * * @param path * the path * @return the image descriptor */ public static ImageDescriptor getImageDescriptor(String path) { ImageDescriptor descriptor = getDefault().getImageRegistry().getDescriptor(path); if (descriptor == null) { descriptor = AbstractUIPlugin.imageDescriptorFromPlugin(ID, "icons/" + path); //$NON-NLS-1$ getDefault().getImageRegistry().put(path, descriptor); } return descriptor; } /** * Returns an image at the given plug-in relative path. * * @param path * the path * @return the image */ public static Image getImage(String path) { // make sure descriptor is created getImageDescriptor(path); return getDefault().getImageRegistry().get(path); } /** * Returns an image with overlay at given place at the given plug-in relative path. * * @param basePath * the base image plug-in relative path. * @param overlayPath * the overlay image plug-in relative path. * @param quadrant * the quadrant (one of {@link IDecoration} ({@link IDecoration#TOP_LEFT}, * {@link IDecoration#TOP_RIGHT}, {@link IDecoration#BOTTOM_LEFT}, * {@link IDecoration#BOTTOM_RIGHT} or {@link IDecoration#UNDERLAY}) * @return the image */ public static Image getImage(String basePath, String overlayPath, int quadrant) { getImageDescriptor(basePath, overlayPath, quadrant); return getDefault().getImageRegistry().get(basePath + overlayPath + quadrant); } /** * Returns an image with overlay at given place at the given plug-in relative path. * * @param basePath * the base image plug-in relative path. * @param overlayPath * the overlay image plug-in relative path. * @param quadrant * the quadrant (one of {@link IDecoration} ({@link IDecoration#TOP_LEFT}, * {@link IDecoration#TOP_RIGHT}, {@link IDecoration#BOTTOM_LEFT}, * {@link IDecoration#BOTTOM_RIGHT} or {@link IDecoration#UNDERLAY}) * @return the image */ public static ImageDescriptor getImageDescriptor(String basePath, String overlayPath, int quadrant) { String key = basePath + overlayPath + quadrant; ImageDescriptor descriptor = getDefault().getImageRegistry().getDescriptor(key); if(descriptor == null) { Image base = getImage(basePath); ImageDescriptor overlay = getImageDescriptor(overlayPath); descriptor = new DecorationOverlayIcon(base, overlay, quadrant); getDefault().getImageRegistry().put(key, descriptor); } return descriptor; } public static final void logError(String message, Throwable error) { getDefault().getLog().log(createStatus(message, 0, IStatus.ERROR, error)); } public static void showError(final Throwable error) { new ErrorJob(error).schedule(100); } public static final void logWarning(String message, Throwable error) { getDefault().getLog().log(createStatus(message, 0, IStatus.WARNING, error)); } public static final void logInfo(String message, Throwable error) { getDefault().getLog().log(createStatus(message, 0, IStatus.INFO, error)); } public static IStatus createStatus(String msg, int code, int severity, Throwable ex) { return new Status(severity, ID, code, msg, ex); } public static final void logError(Throwable ex) { logError(ex.getMessage(), ex); } /** * Creates a busy cursor and runs the specified runnable. May be called from a non-UI thread. * * @param parent * the parent Shell for the dialog * @param cancelable * if true, the dialog will support cancelation * @param runnable * the runnable * * @exception InvocationTargetException * when an exception is thrown from the runnable * @exception InterruptedException * when the progress monitor is cancelled */ public static void runWithProgress(Shell parent, boolean cancelable, final IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException { boolean createdShell = false; Shell myParent = parent; try { if (myParent == null || myParent.isDisposed()) { Display display = Display.getCurrent(); if (display == null) { // cannot provide progress (not in UI thread) runnable.run(new NullProgressMonitor()); return; } // get the active shell or a suitable top-level shell myParent = display.getActiveShell(); if (myParent == null) { myParent = new Shell(display); createdShell = true; } } // pop up progress dialog after a short delay final Exception[] holder = new Exception[1]; BusyIndicator.showWhile(myParent.getDisplay(), new Runnable() { public void run() { try { runnable.run(new NullProgressMonitor()); } catch (InvocationTargetException e) { holder[0] = e; } catch (InterruptedException e) { holder[0] = e; } } }); if (holder[0] != null) { if (holder[0] instanceof InvocationTargetException) { throw (InvocationTargetException) holder[0]; } throw (InterruptedException) holder[0]; } // new TimeoutProgressMonitorDialog(parent, TIMEOUT).run(true // /*fork*/, cancelable, runnable); } finally { if (createdShell) { parent.dispose(); } } } /** * Convenience method to get the currently active workbench page. Note that the active page may * not be the one that the usr perceives as active in some situations so this method of * obtaining the activae page should only be used if no other method is available. * * @return the active workbench page */ public static IWorkbenchPage getActivePage() { return getActiveWindow().getActivePage(); } /** * Convenience method to get the currently active shell. * * @return the active workbench shell. Never null, if there is at least one window open. */ public static Shell getActiveShell() { return getActiveWindow().getShell(); } /** * Convenience method to get the currently active workbench window. * * @return the active workbench window. Never null, if there is at least one window open. */ public static IWorkbenchWindow getActiveWindow() { IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (window != null) { return window; } return PlatformUI.getWorkbench().getWorkbenchWindows()[0]; } public boolean isHgUsable() { return hgUsable; } public static Display getStandardDisplay() { return PlatformUI.getWorkbench().getDisplay(); } public IProxyService getProxyService() { return (IProxyService) proxyServiceTracker.getService(); } /** * Show a dialog only if the user hasn't selected "don't show again" for it. * * @param title The title * @param message The message * @param type The type, for example MessageDialog.CONFIRM * @param key The preference key * @param shell The shell to use * @return True of ok was pressed */ public static boolean showDontShowAgainConfirmDialog(final String title, final String message, int type, String key, Shell shell) { IPreferenceStore store = getDefault().getPreferenceStore(); String pref = store.getString(key); if (MessageDialogWithToggle.PROMPT.equals(pref)) { String toggleMessage = Messages.getString("Dialogs.DontShowAgain"); MessageDialogWithToggle confirmDialog = MessageDialogWithToggle.open(type, shell, title, message, toggleMessage, false, store, key, SWT.NONE); int returnCode = confirmDialog.getReturnCode(); return returnCode == Window.OK; } return true; } /** * The default encoding which is used by the current environment. *

* Note: you probably want use {@link HgRoot#getEncoding()} instead, as each repository * may use it's own encoding *

* Note: Python's encoding isn't 1-1 with Charset.name() so do not store * {@link java.nio.charset.Charset}. * * @return a valid encoding name, never null. */ public static String getDefaultEncoding() { return HGENCODING; } /** * Job to show error dialogs. Avoids to show hunderts of dialogs by ussing an exclusive rule. * * @author Andrei */ private static final class ErrorJob extends SafeUiJob { static class ExclusiveRule implements ISchedulingRule { public boolean isConflicting(ISchedulingRule rule) { return contains(rule); } public boolean contains(ISchedulingRule rule) { return rule instanceof ExclusiveRule; } } final IStatus status; private ErrorJob(Throwable error) { super(Messages.getString("MercurialEclipsePlugin.showError")); //$NON-NLS-1$ if (error instanceof CoreException) { status = ((CoreException) error).getStatus(); } else { status = createStatus(error.getMessage(), 0, IStatus.ERROR, error); } setRule(new ExclusiveRule()); } @Override protected IStatus runSafe(IProgressMonitor monitor) { IJobManager jobManager = Job.getJobManager(); String title; IStatus errStatus; if (jobManager.find(plugin).length == 1) { // it's me alone there errStatus = status; } else { // o-ho, we have multiple errors waiting to be displayed... title = Messages.getString("MercurialEclipsePlugin.unexpectedErrors"); //$NON-NLS-1$ String message = Messages .getString("MercurialEclipsePlugin.unexpectedErrorsOccured"); //$NON-NLS-1$ // get the latest state Job[] jobs = jobManager.find(plugin); // discard all waiting now (we are not affected) jobManager.cancel(plugin); List stati = new ArrayList(); for (Job job : jobs) { if (job instanceof ErrorJob) { ErrorJob errorJob = (ErrorJob) job; stati.add(errorJob.status); } } IStatus[] array = stati.toArray(new IStatus[stati.size()]); errStatus = new MultiStatus(title, 0, array, message, null); } StatusManager.getManager().handle(errStatus, StatusManager.SHOW); return super.runSafe(monitor); } @Override public boolean belongsTo(Object family) { return plugin == family; } } /** * Find the object associated with the given object that is adapted to * the provided class. * * @param anyObject might be null * @param clazz class to get the adapter for * @return adapted object or null if no adapter provided or the given object is null */ public static V getAdapter(Object anyObject, Class clazz) { if (clazz.isInstance(anyObject)) { return clazz.cast(anyObject); } if (anyObject instanceof IAdaptable) { IAdaptable a = (IAdaptable) anyObject; return clazz.cast(a.getAdapter(clazz)); } return null; } /** * Unwrap and throw as a CoreException. Note: Never returns * @param e The exception to use * @throws CoreException */ public static void rethrow(Throwable e) throws CoreException { if (e instanceof CoreException) { throw (CoreException)e; } else if (e instanceof InvocationTargetException) { rethrow(((InvocationTargetException) e).getTargetException()); } throw new HgException(e.getLocalizedMessage(), e); } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/Messages.java000066400000000000000000000021071173713500500310020ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/SafeUiJob.java000066400000000000000000000025521173713500500310460ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * StefanC - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.progress.UIJob; public class SafeUiJob extends UIJob { /** * @param name */ public SafeUiJob(String name) { super(name); } /** * @param jobDisplay * @param name */ public SafeUiJob(Display jobDisplay, String name) { super(jobDisplay, name); } @Override public final IStatus runInUIThread(IProgressMonitor monitor) { try { return runSafe(monitor); } catch (RuntimeException error) { MercurialEclipsePlugin.logError(error); return Status.CANCEL_STATUS; } } /** * @param monitor * @return */ protected IStatus runSafe(IProgressMonitor monitor) { return Status.OK_STATUS; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/SafeWorkspaceJob.java000066400000000000000000000027611173713500500324310ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * StefanC - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; /** * @author StefanC * */ public class SafeWorkspaceJob extends WorkspaceJob { /** * @param name */ public SafeWorkspaceJob(String name) { super(name); } /* * (non-Javadoc) * * @see org.eclipse.core.resources.WorkspaceJob#runInWorkspace(org.eclipse.core.runtime.IProgressMonitor) */ @Override public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { try { return runSafe(monitor); } catch (RuntimeException ex) { handleException(ex); return Status.CANCEL_STATUS; } } /** * @return */ protected IStatus runSafe(IProgressMonitor monitor) { return Status.OK_STATUS; } protected void handleException(Throwable ex) { MercurialEclipsePlugin.logError(ex); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/TableColumnSorter.java000066400000000000000000000067421173713500500326500ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) See next comment * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan C - Copy code *******************************************************************************/ /******************************************************************************* * TableViewerSorting Example * * Adam Cabler * * revised example by Tom Schindl * http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jface.snippets/Eclipse%20JFace%20Snippets/org/eclipse/jface/snippets/viewers/Snippet040TableViewerSorting.java?view=markup * * removed ColumnViewer references * added ITableLabelProvider * used label provider for text compare * * minor change by Stefan Chysser * - only cycle between ASC and DESC, the go-back to None is confusing * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * *******************************************************************************/ package com.vectrace.MercurialEclipse; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.TableColumn; public abstract class TableColumnSorter extends ViewerComparator { public static final int ASC = 1; public static final int NONE = 0; public static final int DESC = -1; private int direction; private final TableColumn column; private final TableViewer viewer; public TableColumnSorter(TableViewer viewer, TableColumn column) { this.column = column; this.viewer = viewer; this.column.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (TableColumnSorter.this.viewer.getComparator() != null) { if (TableColumnSorter.this.viewer.getComparator() == TableColumnSorter.this) { int tdirection = TableColumnSorter.this.direction; if (tdirection == ASC) { setSorter(TableColumnSorter.this, DESC); } else if (tdirection == DESC) { setSorter(TableColumnSorter.this, ASC); } } else { setSorter(TableColumnSorter.this, ASC); } } else { setSorter(TableColumnSorter.this, ASC); } } }); } public void setSorter(TableColumnSorter sorter, int direction) { if (direction == NONE) { column.getParent().setSortColumn(null); column.getParent().setSortDirection(SWT.NONE); viewer.setComparator(null); } else { column.getParent().setSortColumn(column); sorter.direction = direction; if (direction == ASC) { column.getParent().setSortDirection(SWT.DOWN); } else { column.getParent().setSortDirection(SWT.UP); } if (viewer.getComparator() == sorter) { viewer.refresh(); } else { viewer.setComparator(sorter); } } } @Override public int compare(Viewer cViewer, Object e1, Object e2) { return direction * doCompare(cViewer, e1, e2); } protected abstract int doCompare(Viewer tableViewer, Object e1, Object e2); } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/000077500000000000000000000000001173713500500300305ustar00rootroot00000000000000AddToWorkspaceAction.java000066400000000000000000000117671173713500500346400ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - Implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.ui.actions.WorkspaceModifyOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgCloneClient; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.team.MercurialProjectSetCapability; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * This action adds projects to the workspace using their unique Mercurial * reference strings from projectsets * * @author Bastian Doetsch */ public class AddToWorkspaceAction extends WorkspaceModifyOperation { private String[] referenceStrings; private IProject[] projectsCreated; public AddToWorkspaceAction() { super(); } public AddToWorkspaceAction(ISchedulingRule rule) { super(rule); } @Override protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException { try { monitor.beginTask("Adding projects to workspace...", referenceStrings.length); IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot(); ArrayList projects = new ArrayList(referenceStrings.length); /* * iterate over all reference strings and use them to create * projects in the current workspace. * * A reference string uses underscore as delimiter and looks like * this: * * "MercurialEclipseProjectSet|ProjectName|RepositoryURLForClone" * */ for (String reference : referenceStrings) { if (monitor.isCanceled()) { break; } MercurialProjectSetCapability psc = MercurialProjectSetCapability.getInstance(); // Project name is stored in part 1 String projectName = psc.getProject(reference); IProject proj = wsRoot.getProject(projectName); // only new projects if (proj.exists() || proj.getLocation() != null) { MercurialEclipsePlugin.logInfo("Project" + proj.getName() + " not imported. Already exists.", null); monitor.worked(1); continue; } String rootRelativePath = psc.getRootRelativePath(reference); if(rootRelativePath != null){ MercurialEclipsePlugin.logInfo("Project" + proj.getName() + " not imported, as it was only a part of the hg repo.", null); // TODO somehow allow to clone multiple projects from ONE hg root break; } // Repository-URL is stored in part 2 HgRepositoryLocationManager repoManager = MercurialEclipsePlugin.getRepoManager(); IHgRepositoryLocation location = repoManager.getRepoLocation(psc .getPullRepo(reference), null, null); HgCloneClient.clone(wsRoot.getLocation().toFile(), location, false, false, false, false, null, projectName); proj.create(monitor); proj.open(monitor); // Register the project with Team. RepositoryProvider.map(proj, MercurialTeamProvider.class.getName()); RepositoryProvider.getProvider(proj, MercurialTeamProvider.class.getName()); projects.add(proj); HgRoot hgRoot = MercurialTeamProvider.getHgRoot(proj); if (hgRoot != null) { // store repo (will be set as default automatically) repoManager.addRepoLocation(hgRoot, location); } // refresh project to get decorations proj.refreshLocal(IResource.DEPTH_INFINITE, monitor); // increase monitor so we see at least a bit of a progress when // importing multiple projects monitor.worked(1); } projectsCreated = projects.toArray(new IProject[projects.size()]); } finally { monitor.done(); } } public String[] getReferenceStrings() { return referenceStrings; } public void setReferenceStrings(String[] referenceStrings) { this.referenceStrings = referenceStrings; } public IProject[] getProjectsCreated() { return projectsCreated; } public void setProjectsCreated(IProject[] projectsCreated) { this.projectsCreated = projectsCreated; } } CompareWithCurrentDelegate.java000066400000000000000000000054641173713500500360450ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.utils.CompareUtils; /** * This delegate is used for object contribution to context menus. * Object class must be FileFromChangeSet or be adaptable to it. */ public class CompareWithCurrentDelegate implements IObjectActionDelegate { private FileFromChangeSet fileFromChangeSet; public void run(IAction action) { if (fileFromChangeSet == null) { return; } ChangeSet cs = fileFromChangeSet.getChangeset(); MercurialRevisionStorage left = new MercurialRevisionStorage(fileFromChangeSet.getFile()); // TODO handle cases when file was renamed/copied // see com.vectrace.MercurialEclipse.history.CompareRevisionAction.getStorage() MercurialRevisionStorage right = new MercurialRevisionStorage(fileFromChangeSet.getFile(), cs.getChangeset()); CompareUtils.openEditor(left, right, false); } /** * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) */ public void selectionChanged(IAction action, ISelection newSelection) { action.setEnabled(false); if (newSelection instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) newSelection; if (sel.getFirstElement() instanceof FileFromChangeSet) { this.fileFromChangeSet = (FileFromChangeSet) sel.getFirstElement(); int diffKind = fileFromChangeSet.getDiffKind(); if ((diffKind & Differencer.CHANGE_TYPE_MASK) != Differencer.DELETION && fileFromChangeSet.getFile().exists()) { action.setEnabled(true); } } } else { this.fileFromChangeSet = null; } } /** * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart) */ public void setActivePart(IAction action, IWorkbenchPart targetPart) { } } CompareWithParentDelegate.java000066400000000000000000000057601173713500500356530ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.utils.CompareUtils; /** * This delegate is used for object contribution to context menus. * Object class must be FileFromChangeSet or be adaptable to it. */ public class CompareWithParentDelegate implements IObjectActionDelegate { private FileFromChangeSet fileFromChangeSet; public void run(IAction action) { if (fileFromChangeSet == null) { return; } ChangeSet cs = fileFromChangeSet.getChangeset(); MercurialRevisionStorage left = new MercurialRevisionStorage(fileFromChangeSet.getFile(), cs.getChangeset()); try { MercurialRevisionStorage right = MercurialUtilities.getParentRevision(cs, fileFromChangeSet.getFile()); CompareUtils.openEditor(left, right, false); } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } } /** * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) */ public void selectionChanged(IAction action, ISelection newSelection) { action.setEnabled(false); if (newSelection instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) newSelection; if (sel.getFirstElement() instanceof FileFromChangeSet) { this.fileFromChangeSet = (FileFromChangeSet) sel.getFirstElement(); int diffKind = fileFromChangeSet.getDiffKind(); if ((diffKind & Differencer.CHANGE_TYPE_MASK) != Differencer.CHANGE) { // parent or child is not available } else { action.setEnabled(true); } } } else { this.fileFromChangeSet = null; } } /** * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart) */ public void setActivePart(IAction action, IWorkbenchPart targetPart) { } } ExportAsBundleAction.java000066400000000000000000000124451173713500500346570ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgBundleClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.MercurialHistoryPage; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * @author Bastian */ public class ExportAsBundleAction extends Action { private final class ExportBundleJob extends Job { private final MercurialRevision rev; private ExportBundleJob(String name, MercurialRevision rev) { super(name); this.rev = rev; } @Override protected IStatus run(IProgressMonitor monitor) { try { monitor .beginTask( Messages.getString("ExportAsBundleAction.exportingRevision") + rev.getContentIdentifier() //$NON-NLS-1$ + Messages.getString("ExportAsBundleAction.toBundle"), 3); //$NON-NLS-1$ monitor.subTask(Messages .getString("ExportAsBundleAction.determiningRepositoryRoot")); //$NON-NLS-1$ HgRoot root = MercurialTeamProvider.getHgRoot(rev.getResource()); if(root == null) { MercurialEclipsePlugin.logError(new IllegalStateException("Hg root not found for: " + rev)); return Status.CANCEL_STATUS; } monitor.worked(1); monitor.subTask(Messages.getString("ExportAsBundleAction.callingMercurial")); //$NON-NLS-1$ determineFileAndBase(); if (file == null) { // user cancel monitor.setCanceled(true); return Status.CANCEL_STATUS; } HgBundleClient.bundle(root, rev.getChangeSet(), null, file, false, base); monitor.worked(1); final String message = Messages.getString("ExportAsBundleAction.theRevision") //$NON-NLS-1$ + rev.getContentIdentifier() + Messages .getString("ExportAsBundleAction.andAllPreviousRevisionsHaveBeenExported") //$NON-NLS-1$ + file; showMessage(message); } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } finally { monitor.done(); } return Status.OK_STATUS; } } private final MercurialHistoryPage mhp; private String file; private String base; private static final ImageDescriptor IMAGE_DESC = MercurialEclipsePlugin .getImageDescriptor("export.gif"); //$NON-NLS-1$ private void determineFileAndBase() { final Display display = MercurialEclipsePlugin.getStandardDisplay(); display.syncExec(new Runnable() { public void run() { Shell shell = MercurialEclipsePlugin.getActiveShell(); FileDialog fileDialog = new FileDialog(shell); fileDialog.setText(Messages .getString("ExportAsBundleAction.pleaseEnterTheNameOfTheBundleFile")); //$NON-NLS-1$ file = fileDialog.open(); if(file == null){ // user cancel return; } InputDialog d = new InputDialog(shell, "Please specify the base revision", "Please specify the base revision e.g. 1333", "0", null); d.open(); base = d.getValue(); } }); } private static void showMessage(final String message) { final Display display = MercurialEclipsePlugin.getStandardDisplay(); display.asyncExec(new Runnable() { public void run() { MessageDialog.openInformation(null, Messages .getString("ExportAsBundleAction.createdSuccessfully"), message); //$NON-NLS-1$ } }); } public ExportAsBundleAction(MercurialHistoryPage mhp) { super(Messages.getString("ExportAsBundleAction.exportSelectedRevisionAsBundle"), IMAGE_DESC); this.mhp = mhp; } @Override public void run() { final MercurialRevision rev = getRevision(); if (rev == null) { return; } new ExportBundleJob(Messages.getString("ExportAsBundleAction.exportingRevision") + rev.getContentIdentifier() + Messages.getString("ExportAsBundleAction.toBundle"), rev).schedule(); } private MercurialRevision getRevision() { MercurialRevision[] selectedRevisions = mhp.getSelectedRevisions(); if (selectedRevisions != null && selectedRevisions.length == 1) { return selectedRevisions[0]; } ChangeSet cs = mhp.getCurrentWorkdirChangeset(); return (MercurialRevision) mhp.getMercurialHistory().getFileRevision(cs.getChangeset()); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/HgOperation.java000066400000000000000000000031001173713500500331040ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Balm Consulting Inc (Peter Hunnisett ) - implementation * VecTrace (Zingo Andersen) - some updates * Stefan Groschupf - logError * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.team.ui.TeamOperation; import org.eclipse.ui.IWorkbenchPart; public abstract class HgOperation extends TeamOperation { protected String result; // constructors public HgOperation(IWorkbenchPart part) { super(part); } public HgOperation(IRunnableContext context) { super(context); } public HgOperation(IWorkbenchPart part, IRunnableContext context) { super(part, context); } // operations public String getResult() { return result; } // TODO: No background for now. @Override protected boolean canRunAsJob() { return false; } @Override protected String getJobName() { return getActionDescription(); } protected abstract String getActionDescription(); } MergeWithCurrentChangesetAction.java000066400000000000000000000105461173713500500370400ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.SafeWorkspaceJob; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.history.MercurialHistoryPage; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.menu.MergeHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * @author Bastian * */ public class MergeWithCurrentChangesetAction extends Action { private final MercurialHistoryPage mhp; private static final ImageDescriptor IMAGE_DESC = MercurialEclipsePlugin .getImageDescriptor("actions/merge.gif"); //$NON-NLS-1$ /** * */ public MergeWithCurrentChangesetAction(MercurialHistoryPage mhp) { super(Messages.getString("MergeWithCurrentChangesetAction.mergeSelectedChangesetWithCurrentChangeset"), IMAGE_DESC); //$NON-NLS-1$ this.mhp = mhp; } @Override public void run() { final MercurialRevision rev = getRevision(); new SafeWorkspaceJob(Messages.getString("MergeWithCurrentChangesetAction.0") + rev.getContentIdentifier() //$NON-NLS-1$ + Messages.getString("MergeWithCurrentChangesetAction.1")) { //$NON-NLS-1$ @Override protected org.eclipse.core.runtime.IStatus runSafe( org.eclipse.core.runtime.IProgressMonitor monitor) { try { monitor.beginTask(Messages.getString("MergeWithCurrentChangesetAction.2") + rev.getContentIdentifier() //$NON-NLS-1$ + Messages.getString("MergeWithCurrentChangesetAction.3"), 3); //$NON-NLS-1$ monitor.subTask(Messages.getString("MergeWithCurrentChangesetAction.4")); //$NON-NLS-1$ final HgRoot root = MercurialTeamProvider.getHgRoot(rev.getResource()); if(root == null) { MercurialEclipsePlugin.logError(new IllegalStateException("Hg root not found for: " + rev)); return Status.CANCEL_STATUS; } monitor.worked(1); monitor.subTask(Messages.getString("MergeWithCurrentChangesetAction.5")); //$NON-NLS-1$ new SafeUiJob("Merging...") { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor m) { Shell activeShell = getDisplay().getActiveShell(); try { if (HgStatusClient.isDirty(root)) { if (!MessageDialog .openQuestion(activeShell, Messages.getString("MergeWithCurrentChangesetAction.6"), //$NON-NLS-1$ Messages.getString("MergeWithCurrentChangesetAction.7"))) { //$NON-NLS-1$ return super.runSafe(m); } } MergeHandler.mergeAndCommit(root, activeShell, m, true, rev .getChangeSet(), true); } catch (Exception e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } return super.runSafe(m); } }.schedule(); } catch (Exception e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } monitor.done(); return super.runSafe(monitor); } }.schedule(); super.run(); } /** * @return */ private MercurialRevision getRevision() { MercurialRevision[] selectedRevisions = mhp.getSelectedRevisions(); if (selectedRevisions != null && selectedRevisions.length == 1) { return selectedRevisions[0]; } ChangeSet cs = mhp.getCurrentWorkdirChangeset(); return (MercurialRevision) mhp.getMercurialHistory().getFileRevision(cs.getChangeset()); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/Messages.java000066400000000000000000000021271173713500500324440ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.actions.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } OpenCurrentVersionDelegate.java000066400000000000000000000040111173713500500360550ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov implementation * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import org.eclipse.core.resources.IFile; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * This delegate is used for object contribution to context menus. * Object class must be FileFromChangeSet or be adaptable to it. */ public class OpenCurrentVersionDelegate implements IObjectActionDelegate { private FileFromChangeSet fileFromChangeSet; private IWorkbenchPart targetPart; public void run(IAction action) { ResourceUtils.openEditor(targetPart.getSite().getPage(), fileFromChangeSet.getFile()); } public void selectionChanged(IAction action, ISelection newSelection) { action.setEnabled(false); if (newSelection instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) newSelection; if (sel.getFirstElement() instanceof FileFromChangeSet) { this.fileFromChangeSet = (FileFromChangeSet) sel.getFirstElement(); IFile file = fileFromChangeSet.getFile(); if (file.exists()) { action.setEnabled(true); } } } else { this.fileFromChangeSet = null; } } public void setActivePart(IAction action, IWorkbenchPart targetPart) { this.targetPart = targetPart; } } OpenMercurialRevisionAction.java000066400000000000000000000213771173713500500362500ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ /** * Open an "old" revision in an editor from like "History" view. */ package com.vectrace.MercurialEclipse.actions; import java.io.IOException; import java.io.InputStream; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.core.runtime.content.IContentTypeManager; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.IPersistableElement; import org.eclipse.ui.IStorageEditorInput; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.BaseSelectionListenerAction; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.model.IWorkbenchAdapter; import org.eclipse.ui.part.Page; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class OpenMercurialRevisionAction extends BaseSelectionListenerAction { public static class MercurialRevisionEditorInput extends PlatformObject implements IWorkbenchAdapter, IStorageEditorInput { private final IFileRevision fileRevision; private final MercurialRevisionStorage storage; private final IEditorDescriptor descriptor; private final String fileName; public MercurialRevisionEditorInput(IFileRevision revision) { this.fileRevision = revision; MercurialRevisionStorage tmpStore = null; try { tmpStore = (MercurialRevisionStorage) revision.getStorage(new NullProgressMonitor()); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } finally { storage = tmpStore; } if(storage != null){ IFile file = storage.getResource(); if(file != null){ fileName = file.getName(); } else { fileName = storage.getName(); } } else { fileName = fileRevision.getName(); } IEditorDescriptor tmpId = null; try { tmpId = initDescriptor(); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } finally { descriptor = tmpId; } } public Object[] getChildren(Object o) { return new Object[0]; } public ImageDescriptor getImageDescriptor(Object object) { return descriptor.getImageDescriptor(); } public String getLabel(Object o) { if (storage != null) { return storage.getName(); } return fileRevision.getName(); } public Object getParent(Object o) { return null; } public IStorage getStorage() throws CoreException { return storage; } public boolean exists() { return true; } public ImageDescriptor getImageDescriptor() { return descriptor.getImageDescriptor(); } public String getName() { return fileName; } public IPersistableElement getPersistable() { return null; // Can to save editor changes } public String getToolTipText() { if (storage != null) { return "" + storage.getFullPath(); } return getName(); } @SuppressWarnings("unchecked") @Override public Object getAdapter(Class adapter) { if (adapter == IWorkbenchAdapter.class) { return this; } if (adapter == IFileRevision.class) { return fileRevision; } return super.getAdapter(adapter); } public String getEditorID() { if (descriptor == null || descriptor.isOpenExternal()) { return EditorsUI.DEFAULT_TEXT_EDITOR_ID; } return descriptor.getId(); } private IEditorDescriptor initDescriptor() throws CoreException { IContentType type = null; IContentTypeManager typeManager = Platform.getContentTypeManager(); if(storage != null){ InputStream contents = storage.getContents(); if (contents != null) { try { type = typeManager.findContentTypeFor(contents, fileName); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } finally { try { contents.close(); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } } } if (type == null) { type = typeManager.findContentTypeFor(fileName); } IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry(); return registry.getDefaultEditor(fileName, type); } } private IStructuredSelection selection; private Shell shell; private IWorkbenchPage wPage; public OpenMercurialRevisionAction(String text) { super(text); } @Override public void run() { IStructuredSelection structSel = selection; Object[] objArray = structSel.toArray(); for (int i = 0; i < objArray.length; i++) { Object tempRevision = objArray[i]; final IFileRevision revision = (IFileRevision) tempRevision; if (revision == null || !revision.exists()) { MessageDialog.openError(shell, Messages.getString("OpenMercurialRevisionAction.error.deletedRevision"), Messages.getString("OpenMercurialRevisionAction.error.cantOpen")); //$NON-NLS-1$ //$NON-NLS-2$ } else { SafeUiJob runnable = new SafeUiJob(Messages.getString("OpenMercurialRevisionAction.job.openingEditor")) { //$NON-NLS-1$ @Override public IStatus runSafe(IProgressMonitor monitor) { IStorage file; try { file = revision.getStorage(monitor); if (file instanceof IFile) { // if this is the current workspace file, open it ResourceUtils.openEditor(wPage, (IFile) file); } else { // not current revision MercurialRevisionEditorInput fileRevEditorInput = new MercurialRevisionEditorInput(revision); if (!editorAlreadyOpenOnContents(fileRevEditorInput)) { String id = fileRevEditorInput.getEditorID(); wPage.openEditor(fileRevEditorInput, id); } } return super.runSafe(monitor); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } } }; runnable.schedule(); } } } @Override protected boolean updateSelection(IStructuredSelection selection1) { this.selection = selection1; return shouldShow(); } public void setPage(Page page) { this.shell = page.getSite().getShell(); this.wPage = page.getSite().getPage(); } public void setPart(IWorkbenchPart part) { this.shell = part.getSite().getShell(); this.wPage = part.getSite().getPage(); } private boolean shouldShow() { if (selection.isEmpty()) { return false; } Object[] objArray = selection.toArray(); for (int i = 0; i < objArray.length; i++) { MercurialRevision revision = (MercurialRevision) objArray[i]; // check to see if any of the selected revisions are deleted revisions if (revision != null && (!revision.isFile() || !revision.exists())) { return false; } } return true; } private boolean editorAlreadyOpenOnContents( MercurialRevisionEditorInput input) { IEditorReference[] editorRefs = wPage.getEditorReferences(); IFileRevision inputRevision = (IFileRevision) input.getAdapter(IFileRevision.class); for (IEditorReference editorRef : editorRefs) { IEditorPart part = editorRef.getEditor(false); if (part != null && part.getEditorInput() instanceof MercurialRevisionEditorInput) { IFileRevision editorRevision = (IFileRevision) part .getEditorInput().getAdapter(IFileRevision.class); if (inputRevision.equals(editorRevision)) { // make the editor that already contains the revision // current wPage.activate(part); return true; } } } return false; } } OpenSelectedRevisionDelegate.java000066400000000000000000000057151173713500500363500ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.actions; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.resources.IFile; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.wizards.Messages; /** * This delegate is used for object contribution to context menus. * Object class must be FileFromChangeSet or be adaptable to it. */ public class OpenSelectedRevisionDelegate implements IObjectActionDelegate { private FileFromChangeSet fileFromChangeSet; private final OpenMercurialRevisionAction openMercurialRevisionAction; public OpenSelectedRevisionDelegate() { openMercurialRevisionAction = new OpenMercurialRevisionAction( Messages.getString("MercurialHistoryPage.openSelectedVersion")); } public void run(IAction action) { openMercurialRevisionAction.run(); } /** * @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection) */ public void selectionChanged(IAction action, ISelection newSelection) { action.setEnabled(false); if (newSelection instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) newSelection; if (sel.getFirstElement() instanceof FileFromChangeSet) { this.fileFromChangeSet = (FileFromChangeSet) sel.getFirstElement(); IFile file = fileFromChangeSet.getFile(); ChangeSet cs = fileFromChangeSet.getChangeset(); MercurialRevision rev = new MercurialRevision(cs, null, file, null, null); int diffKind = fileFromChangeSet.getDiffKind(); if ((diffKind & Differencer.CHANGE_TYPE_MASK) != Differencer.DELETION) { openMercurialRevisionAction.selectionChanged(new StructuredSelection(rev)); action.setEnabled(true); } } } else { this.fileFromChangeSet = null; } } /** * @see org.eclipse.ui.IObjectActionDelegate#setActivePart(org.eclipse.jface.action.IAction, org.eclipse.ui.IWorkbenchPart) */ public void setActivePart(IAction action, IWorkbenchPart targetPart) { openMercurialRevisionAction.setPart(targetPart); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/actions/messages.properties000066400000000000000000000035121173713500500337560ustar00rootroot00000000000000ExportAsBundleAction.andAllPreviousRevisionsHaveBeenExported=\ and all previous changesets have been exported to: \n\n ExportAsBundleAction.callingMercurial=Calling Mercurial bundle command... ExportAsBundleAction.createdSuccessfully=Bundle has been created successfully. ExportAsBundleAction.determineLocationForBundleFile=Determine location for bundle file ExportAsBundleAction.determiningRepositoryRoot=Determining repository root... ExportAsBundleAction.exportingRevision=Exporting changeset ExportAsBundleAction.exportSelectedRevisionAsBundle=Export All Changesets up to Selected as Bundle ExportAsBundleAction.pleaseEnterTheNameOfTheBundleFile=Please enter the name of the bundle file. ExportAsBundleAction.theRevision=The changeset ExportAsBundleAction.toBundle=\ to bundle... HgOperation.failed=\ failed: MergeWithCurrentChangesetAction.0=Merging changeset MergeWithCurrentChangesetAction.1=\ with current working directory changeset MergeWithCurrentChangesetAction.2=Merging changeset MergeWithCurrentChangesetAction.3=\ with current working directory changeset MergeWithCurrentChangesetAction.4=Getting repository information from changeset... MergeWithCurrentChangesetAction.5=Calling Mercurial merge command... MergeWithCurrentChangesetAction.6=Do you really want to switch changesets? MergeWithCurrentChangesetAction.7=The Mercurial repository has uncommitted changes. Do you want to continue and discard them? MergeWithCurrentChangesetAction.mergeSelectedChangesetWithCurrentChangeset=Merge Current with Selected OpenMercurialRevisionAction.error.cantOpen=Can't open a deleted changeset OpenMercurialRevisionAction.error.deletedRevision=Deleted Changeset OpenMercurialRevisionAction.job.openingEditor=Opening editor... StatusContainerAction.job.description.2=\ from the Mercurial repository. StatusContainerAction.job.description1=Mercurial get status eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotations/000077500000000000000000000000001173713500500307255ustar00rootroot00000000000000AnnotateBlock.java000066400000000000000000000041311173713500500342340ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotations/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Charles O'Farrell - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.annotations; import java.util.Date; import com.vectrace.MercurialEclipse.HgRevision; public class AnnotateBlock { private HgRevision revision = new HgRevision("", -1); //$NON-NLS-1$ private String user = ""; //$NON-NLS-1$ private final int startLine; private int endLine; private Date date; public AnnotateBlock(HgRevision revision, String user, Date date, int startLine, int endLine) { this.revision = revision; this.user = user; this.date = date; this.startLine = startLine; this.endLine = endLine; } /** * @return int the last source line of the receiver */ public int getEndLine() { return endLine; } /** * @param line */ public void setEndLine(int line) { endLine = line; } /** * @return the revision the receiver occured in. */ public HgRevision getRevision() { return revision; } /** * @return the first source line number of the receiver */ public int getStartLine() { return startLine; } /** * Answer true if the receiver contains the given line number, false otherwise. * @param i a line number * @return true if receiver contains a line number. */ public boolean contains(int i) { return i >= startLine && i <= endLine; } /** * @return Returns the date. */ public Date getDate() { return this.date; } /** * @param date The date to set. */ public void setDate(Date date) { this.date = date; } /** * @return Returns the user. */ public String getUser() { return this.user; } /** * @param user The user to set. */ public void setUser(String user) { this.user = user; } } AnnotateBlocks.java000066400000000000000000000024461173713500500344260ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotations/******************************************************************************* * Copyright (c) * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Charles O'Farrell - implementation (based on subclipse) * Stefan C - Code cleanup *******************************************************************************/ package com.vectrace.MercurialEclipse.annotations; import java.util.LinkedList; import java.util.List; public class AnnotateBlocks { private final List blocks = new LinkedList(); /** * Add an annotate block merging this block with the previous block if it is part of the same * change. * * @param aBlock */ public void add(AnnotateBlock aBlock) { int size = blocks.size(); if (size == 0) { blocks.add(aBlock); } else { AnnotateBlock lastBlock = blocks.get(size - 1); if (lastBlock.getRevision().equals(aBlock.getRevision())) { lastBlock.setEndLine(aBlock.getStartLine()); } else { blocks.add(aBlock); } } } public List getAnnotateBlocks() { return blocks; } } CommitterColors.java000066400000000000000000000046021173713500500346400ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotations/******************************************************************************* * Copyright (c) * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Charles O'Farrell - implementation (based on subclipse) * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.annotations; import java.util.HashMap; import java.util.Map; import org.eclipse.swt.graphics.RGB; /** * This was copied from internal CVS UI code * * Default implementation, assigns random colors to revisions based on committer id. * * @since 3.2 */ final class CommitterColors { private static CommitterColors fInstance; /** * Returns the committer color singleton. * * @return the committer color singleton */ public static CommitterColors getDefault() { if (fInstance == null) { fInstance= new CommitterColors(); } return fInstance; } /** The color map. */ private final Map fColors = new HashMap(); /** The number of colors that have been issued. */ private int fCount; private CommitterColors() { } /** * Returns a unique color description for each string passed in. Colors for new committers are * allocated to be as different as possible from the existing colors. * * @param committer the committers unique name * @return the corresponding color */ public RGB getCommitterRGB(String committer) { RGB rgb= fColors.get(committer); if (rgb == null) { rgb= computeRGB(fCount++); fColors.put(committer, rgb); } return rgb; } private RGB computeRGB(int ordinal) { float hue= computeHue(ordinal); RGB rgb= new RGB(hue, 1.0f, 1.0f); return rgb; } private float computeHue(int ordinal) { int base= 3; int l = ordinal < base ? 0 : (int) Math.floor(Math.log(ordinal / (double) base) / Math.log(2)); int m= ((int) Math.pow(2, l)) * base; int j= ordinal < base ? ordinal : ordinal - m; float offset= ordinal < base ? 0.0f : (float) (180.0f / base / Math.pow(2, l)); float delta= ordinal < base ? 120.0f : 2 * offset; float hue= (offset + j * delta) % 360; return hue; } } HgPristineCopyQuickDiffProvider.java000066400000000000000000000246611173713500500377320ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotations/******************************************************************************* * Copyright (c) Subclipse and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Charles O'Farrell - implementation (based on subclipse) * StefanC - jobs framework code cleenup * Bastian Doetsch - refactoring * Andrei Loskutov - made it finally working *******************************************************************************/ package com.vectrace.MercurialEclipse.annotations; import java.io.BufferedReader; import java.io.CharArrayWriter; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.editors.text.IStorageDocumentProvider; import org.eclipse.ui.ide.ResourceUtil; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.IElementStateListener; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.quickdiff.IQuickDiffReferenceProvider; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * * A QuickDiff provider that provides a reference to the pristine copy of a file * managed in the Hg repository. The provider notifies when the file's sync * state changes and the diff should be recalculated (e.g. commit, update...) or * when the file is changed (e.g. replace with). * * Here are the file states and what this provider does for each: * * 1. File is unmanaged : reference == empty document 2. Unmanaged file * transitions to managed : empty reference updated with new remote revision 3. * A managed file has new remote (commit, refresh remote) : reference updated * with new remote revision 4. A managed file cleaned, remote is the same * (replace with, update) : refresh diff bar with existing reference * * [Note: Currently an empty document must be returned for an unmanaged file. * This results in the entire document appearing as outgoing changes in the * quickdiff bar. This is required because the quickdiff support relies on * IDocument change events to update the quickdiff, and returning null for the * reference document doesn't allow the transition to later return a IDocument.] * * @since 3.0 */ public class HgPristineCopyQuickDiffProvider implements IQuickDiffReferenceProvider { public static final String HG_REFERENCE_PROVIDER = "com.vectrace.MercurialEclipse.annotatations.HgReferenceProvider"; //$NON-NLS-1$ // The editor showing this quickdiff and provides access to the editor input // and ultimatly the IFile. private ITextEditor editor; // The document containing the remote file. Can be null if the assigned // editor doesn't have a Hg remote resource associated with it. private IDocument referenceDocument; // Will be true when the document has been read and initialized. private boolean isReferenceInitialized; // Document provider allows us to register/deregister the element state // change listener. private IDocumentProvider documentProvider; // Unique id for this reference provider as set via setId(). private String id; // Job that re-creates the reference document. private Job fUpdateJob; /** * Updates the document if the document is changed (e.g. replace with) */ private final IElementStateListener documentListener = new IElementStateListener() { public void elementDirtyStateChanged(Object element, boolean isDirty) { } public void elementContentAboutToBeReplaced(Object element) { } public void elementContentReplaced(Object element) { if (editor != null && editor.getEditorInput() == element) { fetchContentsInJob(); } } public void elementDeleted(Object element) { } public void elementMoved(Object originalElement, Object movedElement) { } }; public IDocument getReference(IProgressMonitor monitor) throws CoreException { if (!isReferenceInitialized) { return null; } if (referenceDocument == null) { readDocument(monitor); } return referenceDocument; } public void setActiveEditor(ITextEditor targetEditor) { IEditorInput editorInput = targetEditor.getEditorInput(); if (editorInput == null || ResourceUtil.getFile(editorInput) == null) { return; } editor = targetEditor; documentProvider = editor.getDocumentProvider(); if (documentProvider != null) { documentProvider.addElementStateListener(documentListener); } isReferenceInitialized = true; } public boolean isEnabled() { if (!isReferenceInitialized) { return false; } return getManagedHgFile() != null; } public void dispose() { isReferenceInitialized = false; // stop update job if (fUpdateJob != null && fUpdateJob.getState() != Job.NONE) { fUpdateJob.cancel(); } // remove listeners if (documentProvider != null) { documentProvider.removeElementStateListener(documentListener); } } public void setId(String id) { this.id = id; } public String getId() { return id; } /** * Determine if the file represented by this quickdiff provider has changed * with respect to it's remote state. Return true if the remote contents * should be refreshed, and false if not. */ private boolean computeChange(IProgressMonitor monitor) { boolean needToUpdateReferenceDocument = false; if (isReferenceInitialized) { needToUpdateReferenceDocument = getFileFromEditor().isSynchronized( IResource.DEPTH_ONE); } return needToUpdateReferenceDocument; } /** * Creates a document and initializes it with the contents of a Hg file * resource. * * @param monitor * the progress monitor * @throws CoreException */ private void readDocument(IProgressMonitor monitor) throws CoreException { if (!isReferenceInitialized) { return; } if (referenceDocument == null) { referenceDocument = new Document(); } if (computeChange(monitor)) { IFile remoteFile = getFileFromEditor(); if (remoteFile != null && documentProvider instanceof IStorageDocumentProvider) { IStorageDocumentProvider provider = (IStorageDocumentProvider) documentProvider; String encoding = provider.getEncoding(editor.getEditorInput()); if (encoding == null) { encoding = provider.getDefaultEncoding(); } if (monitor.isCanceled()) { return; } InputStream stream; // if file is unchanged, simply read the content from current version on the disk if(MercurialStatusCache.getInstance().isClean(remoteFile)){ stream = remoteFile.getContents(); } else { // fetch the file version matching to the current hg root changeset MercurialRevisionStorage revision = new MercurialRevisionStorage(remoteFile); stream = revision.getContents(); } if (stream == null || monitor.isCanceled() || !isReferenceInitialized) { return; } setDocumentContent(referenceDocument, stream, encoding); } else { // the remote is null, so ensure that the document is null if (monitor.isCanceled()) { return; } referenceDocument.set(""); //$NON-NLS-1$ } } } /** * Intitializes the given document with the given stream using the given * encoding. * * @param document * the document to be initialized * @param contentStream * the stream which delivers the document content * @param encoding * the character encoding for reading the given stream * @exception CoreException * if the given stream can not be read */ private static void setDocumentContent(IDocument document, InputStream contentStream, String encoding) throws CoreException { Reader in = null; try { final int defaultFileSize = 15 * 1024; in = new BufferedReader(new InputStreamReader(contentStream, encoding), defaultFileSize); CharArrayWriter caw = new CharArrayWriter(defaultFileSize); char[] readBuffer = new char[2048]; int n = in.read(readBuffer); while (n > 0) { caw.write(readBuffer, 0, n); n = in.read(readBuffer); } document.set(caw.toString()); } catch (IOException x) { throw new HgException("Failed to read file content", x); //$NON-NLS-1$ } finally { if (in != null) { try { in.close(); } catch (IOException x) { throw new HgException("Failed to close stream", x); //$NON-NLS-1$ } } } } /** * Returns the HgFile associated with he active editor or null * if the provider doesn't not have access to a Hg managed file. * * @return the handle to a Hg file */ private File getManagedHgFile() { if (editor != null) { IFile file = getFileFromEditor(); if (file != null && MercurialTeamProvider.isHgTeamProviderFor(file)) { File hgFile = ResourceUtils.getFileHandle(file); if (hgFile.exists()) { return hgFile; } return null; } } return null; } private IFile getFileFromEditor() { if (editor != null) { IEditorInput input = editor.getEditorInput(); if (input != null) { return ResourceUtil.getFile(input); } } return null; } /** * Runs a job that updates the document. If a previous job is already * running it is stopped before the new job can start. */ private void fetchContentsInJob() { if (!isReferenceInitialized) { return; } if (fUpdateJob != null && fUpdateJob.getState() != Job.NONE) { fUpdateJob.cancel(); } fUpdateJob = new Job("Fetching last versioned file state") { //$NON-NLS-1$ @Override protected IStatus run(IProgressMonitor monitor) { try { readDocument(monitor); } catch (CoreException e) { // continue and return ok for now. The error will be reported // when the quick diff supports calls getReference() again. } return Status.OK_STATUS; } }; fUpdateJob.schedule(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotations/Messages.java000066400000000000000000000021371173713500500333420ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.annotations; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.annotations.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } ShowAnnotationOperation.java000066400000000000000000000256701173713500500363570ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotations/******************************************************************************* * Copyright (c) ? * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Charles O'Farrell - implementation (based on subclipse) * StefanC - jobs framework, code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.annotations; import java.lang.reflect.InvocationTargetException; import java.text.DateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.action.IAction; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlCreator; import org.eclipse.jface.text.revisions.Revision; import org.eclipse.jface.text.revisions.RevisionInformation; import org.eclipse.jface.text.source.LineRange; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Shell; import org.eclipse.team.ui.TeamOperation; import org.eclipse.team.ui.TeamUI; import org.eclipse.team.ui.history.IHistoryPage; import org.eclipse.team.ui.history.IHistoryView; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.ITextEditorExtension4; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.commands.HgAnnotateClient; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.MercurialHistoryPage; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class ShowAnnotationOperation extends TeamOperation { public static final class MercurialRevision extends Revision { private final CommitterColors colors; private final ChangeSet entry; private final String id; private final AnnotateBlock block; private MercurialRevision(CommitterColors colors, ChangeSet entry, String string, AnnotateBlock block) { this.colors = colors; this.entry = entry; this.id = string; this.block = block; Assert.isNotNull(colors); Assert.isNotNull(entry); Assert.isNotNull(string); Assert.isNotNull(block); } @Override public Object getHoverInfo() { return entry.getAuthor() + " " + id + " " + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT).format(block.getDate()) + "\n\n" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ (entry.getComment() != null ? entry.getComment() : ""); //$NON-NLS-1$ } /** * @return the entry */ public ChangeSet getChangeSet() { return entry; } @Override public String getAuthor() { return block.getUser(); } @Override public String getId() { return id; } @Override public Date getDate() { return block.getDate(); } @Override public RGB getColor() { return colors.getCommitterRGB(getAuthor()); } } private static final String DEFAULT_TEXT_EDITOR_ID = EditorsUI.DEFAULT_TEXT_EDITOR_ID; private final IResource res; public ShowAnnotationOperation(IWorkbenchPart part, IResource remoteFile) { super(part); this.res = remoteFile; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(null, 100); try { if (!MercurialStatusCache.getInstance().isSupervised(res)) { return; } final AnnotateBlocks annotateBlocks = HgAnnotateClient.execute(res); // this is not needed if there is no live annotate final RevisionInformation information = createRevisionInformation( annotateBlocks, monitor); // We aren't running from a UI thread new SafeUiJob(Messages.getString("ShowAnnotationOperation.job.name")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor moni) { moni.beginTask(Messages.getString("ShowAnnotationOperation.beginAnnotation"), //$NON-NLS-1$ IProgressMonitor.UNKNOWN); final ITextEditorExtension4 editor = getEditor(); if (editor != null) { editor .showRevisionInformation( information, HgPristineCopyQuickDiffProvider.HG_REFERENCE_PROVIDER); final IWorkbenchPage page= getPart().getSite().getPage(); showHistoryView(page, (ITextEditor)editor); page.activate((ITextEditor)editor); } moni.done(); return super.runSafe(moni); } }.schedule(); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } finally { monitor.done(); } } /** * Shows the history view, creating it if necessary, but does not give it focus. * * @param page the workbench page to operate in * @param editor the editor that is showing the file * @return the history view * @throws PartInitException */ private IHistoryView showHistoryView(IWorkbenchPage page, ITextEditor editor) { Object object = res; if (object == null) { object = editor.getEditorInput(); } IHistoryView historyView= TeamUI.showHistoryFor(page, object, null); IHistoryPage historyPage = historyView.getHistoryPage(); if (historyPage instanceof MercurialHistoryPage){ MercurialHistoryPage mercurialHistoryPage = (MercurialHistoryPage) historyPage; // We need to call link to ensure that the history page gets linked // even if the page input did not change mercurialHistoryPage.linkWithEditor(); } return historyView; } @Override protected IAction getGotoAction() { return super.getGotoAction(); } private ITextEditorExtension4 getEditor() { IEditorReference[] references = MercurialEclipsePlugin.getActivePage() .getEditorReferences(); IResource resource = res; if (resource == null) { return null; } IWorkbenchPage page = getPart().getSite().getPage(); for (int i = 0; i < references.length; i++) { IEditorReference reference = references[i]; try { if (resource.equals(reference.getEditorInput() .getAdapter(IFile.class))) { IEditorPart editor = reference.getEditor(false); if (editor instanceof ITextEditorExtension4) { return (ITextEditorExtension4) editor; } // editor opened is not a text editor - reopen file using // the // defualt text editor IEditorPart part = page .openEditor(new FileEditorInput((IFile) resource), DEFAULT_TEXT_EDITOR_ID, true, IWorkbenchPage.MATCH_NONE); if (part instanceof ITextEditorExtension4) { return (ITextEditorExtension4) part; } } } catch (PartInitException e) { MercurialEclipsePlugin.logError(e); } } // no existing editor references found, try to open a new editor for the // file try { IEditorDescriptor descrptr = IDE.getEditorDescriptor((IFile) resource); // try to open the associated editor only if its an internal // editor if (descrptr.isInternal()) { IEditorPart part = ResourceUtils.openEditor(page, (IFile) resource); if (part instanceof ITextEditorExtension4) { return (ITextEditorExtension4) part; } // editor opened is not a text editor - close it // NB: editor should not be closed as it could be opened by user before // page.closeEditor(part, false); } // open file in default text editor IEditorPart part = IDE.openEditor(page, (IFile) resource, DEFAULT_TEXT_EDITOR_ID); if (part instanceof ITextEditorExtension4) { return (ITextEditorExtension4) part; } } catch (PartInitException e) { MercurialEclipsePlugin.logError(e); } return null; } private RevisionInformation createRevisionInformation( final AnnotateBlocks annotateBlocks, IProgressMonitor monitor) throws HgException { Map logEntriesByRevision = new HashMap(); LocalChangesetCache.getInstance().refreshAllLocalRevisions( res, true); Iterable revisions = LocalChangesetCache.getInstance() .getOrFetchChangeSets(res); for (ChangeSet changeSet : revisions) { logEntriesByRevision.put(Integer.valueOf(changeSet.getRevision() .getRevision()), changeSet); } RevisionInformation info = new RevisionInformation(); final class AnnotationControlCreator implements IInformationControlCreator { private final String statusFieldText; public AnnotationControlCreator(String statusFieldText) { this.statusFieldText = statusFieldText; } public IInformationControl createInformationControl(Shell parent) { return new SourceViewerInformationControl(parent, SWT.TOOL, SWT.NONE, JFaceResources.DEFAULT_FONT, statusFieldText); } } info.setHoverControlCreator(new AnnotationControlCreator(Messages .getString("ShowAnnotationOperation.pressF2ForFocus"))); //$NON-NLS-1$ info.setInformationPresenterControlCreator(new AnnotationControlCreator(null)); final CommitterColors colors = CommitterColors.getDefault(); HashMap sets = new HashMap(); for (final AnnotateBlock block : annotateBlocks.getAnnotateBlocks()) { final String revisionString = block.getRevision().toString(); ChangeSet logEntry = logEntriesByRevision.get( Integer.valueOf(block.getRevision().getRevision())); // logEntriesByRevision may not contain transplanted changesets if (logEntry == null) { HgRoot root = MercurialRootCache.getInstance().getHgRoot(res); logEntry = HgLogClient.getChangeset(root, block.getRevision().getChangeset()); Assert.isNotNull(logEntry); logEntriesByRevision.put(Integer.valueOf(logEntry.getRevision().getRevision()), logEntry); } block.setUser(logEntry.getPerson()); Revision revision = sets.get(revisionString); if (revision == null) { revision = new MercurialRevision(colors, logEntry, revisionString, block); sets.put(revisionString, revision); info.addRevision(revision); } revision.addRange(new LineRange(block.getStartLine(), block .getEndLine() - block.getStartLine() + 1)); } return info; } } SourceViewerInformationControl.java000066400000000000000000000247761173713500500377220ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotations/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Charles O'Farrell - copy from subclipse * StefanC - code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.annotations; import java.util.Collections; import java.util.Map; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IInformationControl; import org.eclipse.jface.text.IInformationControlExtension; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; /** * Source viewer based implementation of {@link org.eclipse.jface.text.IInformationControl}. * Displays information in a source viewer. * * @since 3.0 * * This class is copied from org.eclipse.jface.text.source.projection.SourceViewerInformationControl * Several changes are made in order to handle hover for H annotations */ class SourceViewerInformationControl implements IInformationControl, IInformationControlExtension, DisposeListener { private static final class HgTextSourceViewerConfiguration extends TextSourceViewerConfiguration { private HgTextSourceViewerConfiguration(IPreferenceStore store) { super(store); } @Override protected Map getHyperlinkDetectorTargets(ISourceViewer sourceViewer) { return Collections.singletonMap("org.eclipse.ui.DefaultTextEditor", //$NON-NLS-1$ null); // new IAdaptable() { // public Object getAdapter(Class adapter) { // // return Platform.getAdapterManager().getAdapter(CVSHistoryPage.this, adapter); // return null; // } // }); } } /** Border thickness in pixels. */ private static final int BORDER= 1; /** The control's shell */ private Shell fShell; /** The control's text widget */ private StyledText fText; /** The control's source viewer */ private final SourceViewer fViewer; /** The optional status field. */ private Label fStatusField; /** The separator for the optional status field. */ private Label fSeparator; /** The font of the optional status text label.*/ private Font fStatusTextFont; /** The maximal widget width. */ private int fMaxWidth; /** The maximal widget height. */ private int fMaxHeight; /** * Creates a source viewer information control with the given shell as * parent and the given font. * * @param parent the parent shell * @param symbolicFontName the symbolic font name */ public SourceViewerInformationControl(Shell parent, String symbolicFontName) { this(parent, SWT.NO_TRIM | SWT.TOOL, SWT.NONE, symbolicFontName, null); } /** * Creates a source viewer information control with the given shell as * parent. The given shell styles are applied to the created shell. The * given styles are applied to the created styled text widget. The text * widget will be initialized with the given font. The status field will * contain the given text or be hidden. * * @param parent the parent shell * @param shellStyle the additional styles for the shell * @param style the additional styles for the styled text widget * @param symbolicFontName the symbolic font name * @param statusFieldText the text to be used in the optional status field * or null if the status field should be hidden */ public SourceViewerInformationControl(Shell parent, int shellStyle, int style, String symbolicFontName, String statusFieldText) { GridLayout layout; GridData gd; fShell= new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle); Display display= fShell.getDisplay(); fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); Composite composite= fShell; layout= new GridLayout(1, false); int border= ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER; layout.marginHeight= border; layout.marginWidth= border; composite.setLayout(layout); gd= new GridData(GridData.FILL_HORIZONTAL); composite.setLayoutData(gd); if (statusFieldText != null) { composite= new Composite(composite, SWT.NONE); layout= new GridLayout(1, false); layout.marginHeight= 0; layout.marginWidth= 0; composite.setLayout(layout); gd= new GridData(GridData.FILL_BOTH); composite.setLayoutData(gd); composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); } // Source viewer fViewer= new SourceViewer(composite, null, style); fViewer.setEditable(false); // configure hyperlink detectors // fViewer.configure(new SourceViewerConfiguration()); fViewer.configure(new HgTextSourceViewerConfiguration(EditorsUI.getPreferenceStore())); fText= fViewer.getTextWidget(); gd= new GridData(GridData.BEGINNING | GridData.FILL_BOTH); fText.setLayoutData(gd); fText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); fText.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); fText.setFont(JFaceResources.getFont(symbolicFontName)); fText.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { if (e.character == 0x1B) { fShell.dispose(); } } public void keyReleased(KeyEvent e) {} }); // Status field if (statusFieldText != null) { // Horizontal separator line fSeparator= new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT); fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // Status field label fStatusField= new Label(composite, SWT.RIGHT); fStatusField.setText(statusFieldText); Font font= fStatusField.getFont(); FontData[] fontDatas= font.getFontData(); for (int i= 0; i < fontDatas.length; i++) { fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10); } fStatusTextFont= new Font(fStatusField.getDisplay(), fontDatas); fStatusField.setFont(fStatusTextFont); GridData gd2= new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); fStatusField.setLayoutData(gd2); // Regarding the color see bug 41128 fStatusField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW)); fStatusField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); } addDisposeListener(this); } public void setInput(Object input) { if (input instanceof String) { setInformation((String) input); } else { setInformation(null); } } public void setInformation(String content) { if (content == null) { fViewer.setInput(null); return; } IDocument doc= new Document(content); fViewer.setInput(doc); // decorate text StyleRange styleRange = new StyleRange(); styleRange.start = 0; styleRange.length = content.indexOf('\n'); styleRange.fontStyle = SWT.BOLD; fViewer.getTextWidget().setStyleRange(styleRange); } public void setVisible(boolean visible) { fShell.setVisible(visible); } public void widgetDisposed(DisposeEvent event) { if (fStatusTextFont != null && !fStatusTextFont.isDisposed()) { fStatusTextFont.dispose(); } fStatusTextFont= null; fShell= null; fText= null; } public final void dispose() { if (fShell != null && !fShell.isDisposed()) { fShell.dispose(); } else { widgetDisposed(null); } } public void setSize(int width, int height) { if (fStatusField != null) { GridData gd= (GridData) fViewer.getTextWidget().getLayoutData(); Point statusSize= fStatusField.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); Point separatorSize= fSeparator.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); gd.heightHint= height - statusSize.y - separatorSize.y; } fShell.setSize(width, height); if (fStatusField != null) { fShell.pack(true); } } public void setLocation(Point location) { fShell.setLocation(location); } public void setSizeConstraints(int maxWidth, int maxHeight) { fMaxWidth= maxWidth; fMaxHeight= maxHeight; } public Point computeSizeHint() { // compute the preferred size int x= SWT.DEFAULT; int y= SWT.DEFAULT; Point size= fShell.computeSize(x, y); if (size.x > fMaxWidth) { x= fMaxWidth; } if (size.y > fMaxHeight) { y= fMaxHeight; } // recompute using the constraints if the preferred size is larger than the constraints if (x != SWT.DEFAULT || y != SWT.DEFAULT) { size= fShell.computeSize(x, y, false); } return size; } public void addDisposeListener(DisposeListener listener) { fShell.addDisposeListener(listener); } public void removeDisposeListener(DisposeListener listener) { fShell.removeDisposeListener(listener); } public void setForegroundColor(Color foreground) { fText.setForeground(foreground); } public void setBackgroundColor(Color background) { fText.setBackground(background); } public boolean isFocusControl() { return fText.isFocusControl(); } public void setFocus() { fShell.forceFocus(); fText.setFocus(); } public void addFocusListener(FocusListener listener) { fText.addFocusListener(listener); } public void removeFocusListener(FocusListener listener) { fText.removeFocusListener(listener); } public boolean hasContents() { return fText.getCharCount() > 0; } } messages.properties000066400000000000000000000002451173713500500345740ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/annotationsShowAnnotationOperation.beginAnnotation=Applying Annotation ShowAnnotationOperation.job.name=Hg Annotate ShowAnnotationOperation.pressF2ForFocus=Press F2 for focus. eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/000077500000000000000000000000001173713500500301715ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/AbstractClient.java000066400000000000000000000216211173713500500337400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - bug fixes * Philip Graf - proxy support *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.eclipse.core.net.proxy.IProxyData; import org.eclipse.core.net.proxy.IProxyService; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.HgFeatures; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * Base client class * @author bastian * */ public abstract class AbstractClient { private static final String HTTP_PATTERN_STRING = "[hH][tT][tT][pP]:.*[@]"; //$NON-NLS-1$ private static final String HTTPS_PATTERN_STRING = "[hH][tT][tT][pP][sS]:.*[@]"; //$NON-NLS-1$ private static final String SSH_PATTERN_STRING = "[sS][sS][hH]:.*[@]"; //$NON-NLS-1$ private static final String SVN_PATTERN_STRING = "[sS][vV][nN]:.*[@]"; //$NON-NLS-1$ private static final Pattern HTTP_PATTERN = Pattern.compile(HTTP_PATTERN_STRING); private static final Pattern HTTPS_PATTERN = Pattern.compile(HTTPS_PATTERN_STRING); private static final Pattern SSH_PATTERN = Pattern.compile(SSH_PATTERN_STRING); private static final Pattern SVN_PATTERN = Pattern.compile(SVN_PATTERN_STRING); protected AbstractClient() { super(); } public static String obfuscateLoginData(String line) { String myLine = line == null? "" : line; myLine = HTTP_PATTERN.matcher(myLine).replaceAll("http://***@"); //$NON-NLS-1$ if (myLine.equals(line)) { myLine = HTTPS_PATTERN.matcher(line).replaceAll("https://***@"); //$NON-NLS-1$ } if (myLine.equals(line)) { myLine = SSH_PATTERN.matcher(line).replaceAll("ssh://***@"); //$NON-NLS-1$ } if (myLine.equals(line)) { myLine = SVN_PATTERN.matcher(line).replaceAll("svn://***@"); //$NON-NLS-1$ } return myLine; } /** * @param resource * @return hg root as canonical file (see {@link File#getCanonicalFile()}) * @throws HgException */ static HgRoot getHgRoot(IResource resource) throws HgException { Assert.isNotNull(resource); return MercurialRootCache.getInstance().getHgRoot(resource); } /** * Checks if the specified resource is an HgRoot. If it is, the HgRoot is returned, otherwise null is returned. */ public static HgRoot isHgRoot(IResource res) throws HgException { Assert.isNotNull(res); if(!(res instanceof IContainer)){ return null; } IContainer container = (IContainer)res; if(container.findMember(".hg") != null){ return getHgRoot(container); } return null; } static List toFiles(List files) { List toFiles = new ArrayList(); for (IResource r : files) { IPath path = ResourceUtils.getPath(r); if(!path.isEmpty()) { toFiles.add(path.toFile()); } } return toFiles; } /** * Checks whether a command is available in installed Mercurial version by * issuing hg help . If Mercurial doesn't answer with * "hg: unknown command", it's available * * @param commandName * the name of the command, e.g. "rebase" * @param extensionEnabler * the enablement string for an extension, e.g. * "hgext.bookmarks=" * @return true, if command is available */ public static boolean isCommandAvailable(String commandName, String extensionEnabler) { boolean returnValue = false; // see bug http://bitbucket.org/mercurialeclipse/main/issue/224/ // If hg command uses non-null directory, which is NOT under the hg control, // MercurialTeamProvider.getAndStoreHgRoot() throws an exception AbstractShellCommand command = new RootlessHgCommand("help", "Checking availablility of " + commandName); if (extensionEnabler != null && extensionEnabler.length() != 0) { command.addOptions("--config", "extensions." + extensionEnabler); //$NON-NLS-1$ //$NON-NLS-2$ } command.addOptions(commandName); String result; try { result = new String(command.executeToBytes(10000, false)); if (result.startsWith("hg: unknown command")) { //$NON-NLS-1$ returnValue = false; } else { returnValue = true; } } catch (HgException e) { returnValue = false; } return returnValue; } public static String getHgResourceSearchPattern(IResource resource) throws HgException { HgRoot hgRoot = getHgRoot(resource); String pattern = null; IPath relPath = ResourceUtils.getPath(resource).makeRelativeTo(hgRoot.getIPath()); if (resource instanceof IStorage) { pattern = "glob:" + relPath.toOSString(); } else { String pathString = relPath.toOSString(); if (pathString.length() > 0) { pattern = "glob:" + pathString + System.getProperty("file.separator") + "**"; } else { pattern = "glob:**"; } } return pattern; } /** * Add the proxy-aware repository location to the command * @param repo not null * @param cmd not null * @throws HgException */ protected static void addRepoToHgCommand(IHgRepositoryLocation repo, AbstractShellCommand cmd) throws HgException { URI uri = repo.getUri(); String location; if (uri != null && uri.getHost() != null) { location = uri.toASCIIString(); addProxyToHgCommand(uri, cmd); } else { location = repo.getLocation(); } cmd.addOptions(location); } /** * If a proxy server is necessary to access the pull or push location, this method will add the * respective command options. * * @param repository * The URI of the repository, never null * @param command * not null */ protected static void addProxyToHgCommand(URI repository, AbstractShellCommand command) { IProxyService proxyService = MercurialEclipsePlugin.getDefault().getProxyService(); // Host can be null URI is a local path final String host = repository.getHost(); if (proxyService == null || host == null) { return; } // check if there is an applicable proxy for the location // TODO the method we calling is deprecated, but we have to use it // to be compatible with Eclipse 3.4 API... IProxyData proxy = proxyService.getProxyDataForHost(host, repository.getScheme()); if (proxy == null || proxy.getHost() == null) { return; } // set the host incl. port command.addOptions("--config", "http_proxy.host=" + getProxyHost(proxy)); //$NON-NLS-1$ //$NON-NLS-2$ // check if authentication is required if (proxy.isRequiresAuthentication()) { // set the user name if available if (proxy.getUserId() != null) { command.addOptions("--config", "http_proxy.user=" + proxy.getUserId()); //$NON-NLS-1$ //$NON-NLS-2$ } // set the password if available if (proxy.getPassword() != null) { command.addOptions("--config", "http_proxy.passwd=" //$NON-NLS-1$ //$NON-NLS-2$ + proxy.getPassword()); } } } /** * Returns the proxy host parameter for the {@code http_proxy.host} configuration. * * @param proxy * The proxy data. * @return The proxy host. */ private static String getProxyHost(IProxyData proxy) { StringBuilder host = new StringBuilder(proxy.getHost()); if (proxy.getPort() >= 0) { host.append(':').append(proxy.getPort()); } return host.toString(); } protected static void addMergeToolPreference(AbstractShellCommand command) { boolean useExternalMergeTool = Boolean.valueOf( HgClients.getPreference(MercurialPreferenceConstants.PREF_USE_EXTERNAL_MERGE, "false")).booleanValue(); //$NON-NLS-1$ if (!useExternalMergeTool) { command.addOptions("--config", "ui.merge=simplemerge"); //$NON-NLS-1$ //$NON-NLS-2$ } } protected static void addInsecurePreference(AbstractShellCommand command) { if(HgFeatures.INSECURE.isEnabled()) { boolean verify = Boolean.valueOf( HgClients.getPreference(MercurialPreferenceConstants.PREF_VERIFY_SERVER_CERTIFICATE, "true")).booleanValue(); //$NON-NLS-1$ if (!verify) { command.addOptions("--insecure"); //$NON-NLS-1$ } } } } AbstractParseChangesetClient.java000066400000000000000000000220601173713500500364740ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.StringReader; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.RemoteData; import com.vectrace.MercurialEclipse.team.cache.RemoteKey; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * This class helps HgClients to parse the changeset output of hg to Changeset objects. * * @author Bastian Doetsch */ public abstract class AbstractParseChangesetClient extends AbstractClient { private static final String OPEN_TAG = ""; private static final String CLOSE_TAG = ""; private static final int OPEN_CLOSE_TAG_SIZE = OPEN_TAG.length() + CLOSE_TAG.length(); private static final String STYLES = "/styles"; private static final String DEFAULT = "/log_style"; //$NON-NLS-1$ private static final String WITH_FILES = "/log_style_with_files"; //$NON-NLS-1$ private static final String WITH_FILES_FAST = "/log_style_fast"; //$NON-NLS-1$ private static final String TEMP_EXTN = ".tmpl"; //$NON-NLS-1$ public static final int STYLE_DEFAULT = 0; public static final int STYLE_WITH_FILES = 1; public static final int STYLE_WITH_FILES_FAST = 2; /** * Return a File reference to a copy of the required mercurial style file. * Two types are available, one that includes the files and one that * doesn't. Using the one with files can be very slow on large repos. *

* These style files are included in the plugin jar file and need to be * copied out of there into the plugin state area so a path can be given to * the hg command. * * @param styleBit * return one of the STYLE_ constants * @return a File reference to an existing file */ public static File getStyleFile(int styleBit) throws HgException { String style; switch (styleBit) { case STYLE_WITH_FILES: style = WITH_FILES; break; case STYLE_WITH_FILES_FAST: style = WITH_FILES_FAST; break; default: style = DEFAULT; break; } String styleTemplate = style + TEMP_EXTN; IPath sl = MercurialEclipsePlugin.getDefault().getStateLocation(); File stylefile = sl.append(style).toFile(); File tmplfile = sl.append(styleTemplate).toFile(); if (stylefile.canRead() && tmplfile.canRead()) { // Already have copies, return the file reference to the style file stylefile.deleteOnExit(); tmplfile.deleteOnExit(); return stylefile; } ClassLoader cl = AbstractParseChangesetClient.class.getClassLoader(); // Need to make copies into the state directory from the jar file. // set delete on exit so a new copy is made each time eclipse is started // so we don't use stale copies on plugin updates. InputStream styleistr = cl.getResourceAsStream(STYLES + style); InputStream tmplistr = cl.getResourceAsStream(STYLES + styleTemplate); OutputStream styleostr = null; OutputStream tmplostr = null; try { styleostr = new FileOutputStream(stylefile); tmplostr = new FileOutputStream(tmplfile); tmplfile.deleteOnExit(); byte[] buffer = new byte[1024]; int n; while ((n = styleistr.read(buffer)) != -1) { styleostr.write(buffer, 0, n); } while ((n = tmplistr.read(buffer)) != -1) { tmplostr.write(buffer, 0, n); } return stylefile; } catch (IOException e) { throw new HgException("Failed to setup hg style file", e); //$NON-NLS-1$ } finally { try { if(styleostr != null) { styleostr.close(); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } try { if(tmplostr != null) { tmplostr.close(); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } } /** * Parse log output into a set of changesets. *

* Format of input is defined in the two style files in /styles directory * * @param input * output from the hg log command * @param direction * Incoming, Outgoing or Local changesets * @param repository * @param bundleFile * @return map where the key is an absolute file path, never null * @throws HgException */ protected static Map> createLocalRevisions( IResource res, String input, Direction direction, IHgRepositoryLocation repository, File bundleFile, String branch) throws HgException { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(res); IPath path = ResourceUtils.getPath(res); return createLocalRevisions(path, input, direction, repository, bundleFile, branch, hgRoot); } protected static RemoteData createRemoteRevisions(RemoteKey key, String input, Direction direction, File bundleFile) throws HgException { if (input == null || input.length() == 0){ return new RemoteData(key, direction); } IPath path = new Path(key.getRoot().getAbsolutePath()); ChangesetContentHandler xmlHandler = parseInput(path, false, input, direction, key.getRepo(), bundleFile, key.getBranch(), key.getRoot()); return xmlHandler.createRemoteData(); } /** * @param path full absolute file path, which MAY NOT EXIST in the local file system * (because it is the original path of moved or renamed file) * * @return map where the key is an absolute file path, never null * @throws HgException */ protected static Map> createLocalRevisions(IPath path, String input, Direction direction, IHgRepositoryLocation repository, File bundleFile, String branch, HgRoot hgRoot) throws HgException { Map> fileRevisions = new HashMap>(); if (input == null || input.length() == 0 || hgRoot == null) { return fileRevisions; } ChangesetContentHandler xmlHandler = parseInput(path, true, input, direction, repository, bundleFile, branch, hgRoot); return xmlHandler.getFileRevisions(); } private static ChangesetContentHandler parseInput(IPath path, boolean withFiles, String input, Direction direction, IHgRepositoryLocation repository, File bundleFile, String branch, HgRoot hgRoot) throws HgException { StringBuilder sb = new StringBuilder(input.length() + OPEN_CLOSE_TAG_SIZE); sb.append(OPEN_TAG); sb.append(input); sb.append(CLOSE_TAG); String myInput = sb.toString(); ChangesetContentHandler xmlHandler = new ChangesetContentHandler(path, withFiles, direction, repository, bundleFile, branch, hgRoot); try { XMLReader reader = XMLReaderFactory.createXMLReader(); reader.setContentHandler(xmlHandler); reader.parse(new InputSource(new StringReader(myInput))); } catch (Exception e) { String nextTry = cleanControlChars(myInput); try { XMLReader reader = XMLReaderFactory.createXMLReader(); reader.setContentHandler(xmlHandler); reader.parse(new InputSource(new StringReader(nextTry))); } catch (Exception e1) { MercurialEclipsePlugin.logError(e); throw new HgException(e1.getLocalizedMessage(), e1); } } return xmlHandler; } /** * Clean the string of special chars that might be invalid for the XML * parser. Return the cleaned string (special chars replaced by ordinary * spaces). * * @param str * the string to clean * @return the cleaned string */ private static String cleanControlChars(String str) { final StringBuilder buf = new StringBuilder(); final int len = str.length(); boolean inString=false; for (int i = 0; i < len; i++) { final int ch = str.codePointAt(i); if (ch == '\r' || ch == '\n' || ch == '\t') { buf.appendCodePoint(ch); } else if (Character.isISOControl(ch)) { buf.append(' '); } else if (ch == '&') { buf.append("&"); } else if (ch == '"') { buf.append("\""); inString = !inString; } else if ((ch == '<') && inString) { buf.append("<"); } else if ((ch == '>') && inString) { buf.append(">"); } else { buf.appendCodePoint(ch); } } return buf.toString(); } } AbstractShellCommand.java000066400000000000000000000615621173713500500350210ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation (with lots of stuff pulled up from HgCommand) * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - bug fixes/restructure * Zsolt Koppany (Intland) - enhancements * Philip Graf - use default timeout from preferences * John Peberdy - refactoring *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import static com.vectrace.MercurialEclipse.MercurialEclipsePlugin.*; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.HgFeatures; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author bastian */ public abstract class AbstractShellCommand extends AbstractClient { private static final int BUFFER_SIZE = 32768; /** * File encoding to use. If not specified falls back to {@link HgRoot}'s encoding. */ private String encoding; /** * Should not be used by any command except commands needed for the initialization of hg * (debuginstall and version) * * @see MercurialEclipsePlugin#checkHgInstallation() */ protected boolean isInitialCommand; /** * should not be used by any code except initialization of hg * @see MercurialEclipsePlugin#checkHgInstallation() */ protected static final CountDownLatch startSignal = new CountDownLatch(1); /** * See http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx The maximum command line * length for the CreateProcess function is 32767 characters. This limitation comes from the * UNICODE_STRING structure. *

* See also http://support.microsoft.com/kb/830473: On computers running Microsoft Windows XP or * later, the maximum length of the string that you can use at the command prompt is 8191 * characters. On computers running Microsoft Windows 2000 or Windows NT 4.0, the maximum length * of the string that you can use at the command prompt is 2047 characters. *

* So here we simply allow maximal 100 file paths to be used in one command. Why 100? Why not? * TODO The right way would be to construct the command and then check if the full command line * size is >= 32767. * * @deprecated for the new features please check {@link HgFeatures#LISTFILE} enablement */ @Deprecated public static final int MAX_PARAMS = 100; static { // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=298795 // we must run this stupid code in the UI thread Display.getDefault().asyncExec(new Runnable() { public void run() { PlatformUI.getWorkbench().getProgressService().registerIconForFamily( getImageDescriptor("mercurialeclipse.png"), AbstractShellCommand.class); } }); } /** * This rule disallows hg commands run in parallel if the hg root is specified. * If the hg root is not set, then this rule allows parallel job execution. */ public static class DefaultExecutionRule implements ISchedulingRule { protected volatile HgRoot hgRoot; public DefaultExecutionRule() { super(); } public boolean isConflicting(ISchedulingRule rule) { return contains(rule); } public boolean contains(ISchedulingRule rule) { if(this == rule){ return true; } if(!(rule instanceof DefaultExecutionRule)){ return false; } DefaultExecutionRule rule2 = (DefaultExecutionRule) rule; return hgRoot != null && hgRoot.equals(rule2.hgRoot); } } /** * This rule disallows hg commands run in parallel on the same hg root */ public static class ExclusiveExecutionRule extends DefaultExecutionRule { /** * @param hgRoot must be not null */ public ExclusiveExecutionRule(HgRoot hgRoot) { super(); Assert.isNotNull(hgRoot); this.hgRoot = hgRoot; } } // should not extend threads directly, should use thread pools or jobs. // In case many threads created at same time, VM can crash or at least get OOM class ProzessWrapper extends Job { private final OutputStream output; private final ProcessBuilder builder; private final DefaultExecutionRule execRule; volatile IProgressMonitor monitor2; volatile boolean started; private Process process; long startTime; int exitCode = -1; Throwable error; public ProzessWrapper(String name, ProcessBuilder builder, OutputStream output) { super(name); execRule = getExecutionRule(); setRule(execRule); this.builder = builder; this.output = output; } @Override protected IStatus run(IProgressMonitor monitor) { if (monitor.isCanceled()) { return Status.CANCEL_STATUS; } if(debugExecTime) { startTime = System.currentTimeMillis(); } else { startTime = 0; } started = true; monitor2 = monitor; waitForHgInitDone(); InputStream stream = null; try { process = builder.start(); stream = process.getInputStream(); int length; byte[] buffer = new byte[BUFFER_SIZE]; while ((length = stream.read(buffer)) != -1) { output.write(buffer, 0, length); if(monitor.isCanceled()){ break; } } exitCode = process.waitFor(); } catch (IOException e) { if (!monitor.isCanceled()) { error = e; } return Status.CANCEL_STATUS; } catch (InterruptedException e) { if (!monitor.isCanceled()) { error = e; } return Status.CANCEL_STATUS; } finally { if(stream != null) { try { stream.close(); } catch (IOException e) { HgClients.logError(e); } } try { output.close(); } catch (IOException e) { HgClients.logError(e); } monitor.done(); monitor2 = null; if(process != null) { process.destroy(); } } return monitor.isCanceled()? Status.CANCEL_STATUS : Status.OK_STATUS; } /** * Waits until the gate is open (hg installation is checked etc) */ private void waitForHgInitDone() { if(!isInitialCommand) { try { startSignal.await(); } catch (InterruptedException e1) { MercurialEclipsePlugin.logError(e1); } } } private boolean isAlive() { // job is either not started yet (is scheduled and waiting), or it is not finished or cancelled yet return (!started && getResult() == null) || (monitor2 != null); } @Override public boolean belongsTo(Object family) { return AbstractShellCommand.class == family; } @Override protected void canceling() { super.canceling(); if(process != null) { process.destroy(); } // remove exclusive lock on the hg root execRule.hgRoot = null; } } protected String command; /** * Calculated commands. See {@link #getCommands()} */ private List commands; /** * Whether files should be preceded by "--" on the command line. * @see #files */ private final boolean escapeFiles; protected List options; /** * The working directory. May be null for default working directory. */ protected final File workingDir; protected final List files; private String timeoutConstant; private ProzessWrapper processWrapper; private boolean showOnConsole; private final boolean debugMode; private final boolean isDebugging; private final boolean debugExecTime; /** * Though this command might not invoke hg, it might get encoding information from it. May be * null. */ protected final HgRoot hgRoot; private DefaultExecutionRule executionRule; /** * Human readable name for this operation */ private final String uiName; /** * @param uiName * Human readable name for this command * @param hgRoot * Though this command might not invoke hg, it might get encoding information from * it. May be null. */ protected AbstractShellCommand(String uiName, HgRoot hgRoot, File workingDir, boolean escapeFiles) { super(); this.hgRoot = hgRoot; this.workingDir = workingDir; this.escapeFiles = escapeFiles; this.uiName = uiName; options = new ArrayList(); files = new ArrayList(); showOnConsole = true; isDebugging = Boolean.valueOf(Platform.getDebugOption(MercurialEclipsePlugin.ID + "/debug/commands")).booleanValue(); debugMode = Boolean.valueOf(HgClients.getPreference(PREF_CONSOLE_DEBUG, "false")).booleanValue(); //$NON-NLS-1$ debugExecTime = Boolean.valueOf(HgClients.getPreference(PREF_CONSOLE_DEBUG_TIME, "false")).booleanValue(); //$NON-NLS-1$ timeoutConstant = MercurialPreferenceConstants.DEFAULT_TIMEOUT; Assert.isNotNull(uiName); } protected AbstractShellCommand(String uiName, HgRoot hgRoot, List commands, File workingDir, boolean escapeFiles) { this(uiName, hgRoot, workingDir, escapeFiles); this.commands = commands; } /** * Should not be called by any code except for hg initialization job * Opens the command execution gate after hg installation is checked etc * @see MercurialEclipsePlugin#checkHgInstallation() */ public static void hgInitDone() { startSignal.countDown(); } /** * Per default, a non-exclusive rule is created * @return rule for hg job execution, never null */ protected DefaultExecutionRule getExecutionRule() { if(executionRule == null) { executionRule = new DefaultExecutionRule(); } return executionRule; } public void setExecutionRule(DefaultExecutionRule rule){ executionRule = rule; } public void addOptions(String... optionsToAdd) { for (String option : optionsToAdd) { options.add(option); } } public byte[] executeToBytes() throws HgException { return executeToBytes(getTimeOut()); } public byte[] executeToBytes(int timeout) throws HgException { return executeToBytes(timeout, true); } /** * Execute a command. * * @param timeout * -1 if no timeout, else the timeout in ms. */ public byte[] executeToBytes(int timeout, boolean expectPositiveReturnValue) throws HgException { ByteArrayOutputStream bos = new ByteArrayOutputStream(BUFFER_SIZE); if (executeToStream(bos, timeout, expectPositiveReturnValue)) { return bos.toByteArray(); } return null; } protected final boolean executeToStream(OutputStream output, int timeout, boolean expectPositiveReturnValue) throws HgException { List cmd = getCommands(); String jobName = obfuscateLoginData(getCommandInvoked(cmd)); File tmpFile = setupTmpFile(cmd); ProcessBuilder builder = setupProcess(cmd); try { // I see sometimes that hg has errors if it runs in parallel // using a job with exclusive rule here serializes all hg access from plugin. processWrapper = createProcessWrapper(output, uiName, builder); logConsoleCommandInvoked(jobName); // will start hg command as soon as job manager allows us to do it processWrapper.schedule(); try { waitForConsumer(timeout); } catch (InterruptedException e) { processWrapper.cancel(); throw new HgException("Process cancelled: " + jobName, e); } if (processWrapper.isAlive()) { // command timeout processWrapper.cancel(); throw new HgException("Process timeout: " + jobName); } IStatus result = processWrapper.getResult(); if (processWrapper.process == null) { // process is either not started or we failed to create it if(result == null){ // was not started at all => timeout? throw new HgException("Process timeout: " + jobName); } if(processWrapper.error == null && result == Status.CANCEL_STATUS) { throw new HgException(HgException.OPERATION_CANCELLED, "Process cancelled: " + jobName, null); } throw new HgException("Process start failed: " + jobName, processWrapper.error); } final String msg = getMessage(output); final int exitCode = processWrapper.exitCode; long timeInMillis = debugExecTime? System.currentTimeMillis() - processWrapper.startTime : 0; // everything fine if (exitCode != 0 && expectPositiveReturnValue) { Throwable rootCause = result != null ? result.getException() : null; final HgException hgex = new HgException(exitCode, msg, jobName, rootCause); logConsoleCompleted(timeInMillis, msg, exitCode, hgex); throw hgex; } if (debugExecTime || debugMode) { logConsoleCompleted(timeInMillis, msg, exitCode, null); } return true; } finally { if (tmpFile != null && tmpFile.isFile()) { tmpFile.delete(); } } } protected ProzessWrapper createProcessWrapper(OutputStream output, String jobName, ProcessBuilder builder) { return new ProzessWrapper(jobName, builder, output); } /** * @param cmd hg commands to run * @return temporary file path used to write {@link HgFeatures#LISTFILE} arguments */ private static File setupTmpFile(List cmd) { for (String line : cmd) { if (line.startsWith(HgFeatures.LISTFILE.getHgCmd())) { return new File(line.substring(HgFeatures.LISTFILE.getHgCmd().length())); } } return null; } private ProcessBuilder setupProcess(List cmd) { ProcessBuilder builder = new ProcessBuilder(cmd); // set locale to english have deterministic output Map env = builder.environment(); // From wiki: http://mercurial.selenic.com/wiki/UpgradeNotes // "If your tools look for particular English messages in Mercurial output, // they should disable translations with LC_ALL=C" env.put("LC_ALL", "C"); //$NON-NLS-1$ //$NON-NLS-2$ env.put("LANG", "C"); //$NON-NLS-1$ //$NON-NLS-2$ env.put("LANGUAGE", "C"); //$NON-NLS-1$ //$NON-NLS-2$ // HGPLAIN normalizes output in Mercurial 1.5+ env.put("HGPLAIN", "set by MercurialEclipse"); //$NON-NLS-1$ //$NON-NLS-2$ String charset = setupEncoding(cmd); if (charset != null) { env.put("HGENCODING", charset); //$NON-NLS-1$ } env.put("HGE_RUNDIR", getRunDir()); // removing to allow using eclipse merge editor builder.environment().remove("HGMERGE"); builder.redirectErrorStream(true); // makes my life easier if (workingDir != null) { builder.directory(workingDir); } return builder; } /** * Template method to add encoding options * @param cmd The list of commands to add to * @return The encoding for HGENCODING env var, or null */ protected String setupEncoding(List cmd) { return null; } private void waitForConsumer(int timeout) throws InterruptedException { if (timeout <= 0) { timeout = 1; } long start = System.currentTimeMillis(); long now = 0; while (processWrapper.isAlive()) { long delay = timeout - now; if (delay <= 0) { break; } synchronized (this){ wait(10); } now = System.currentTimeMillis() - start; } } protected void logConsoleCommandInvoked(final String commandInvoked) { if(isDebugging){ System.out.println(commandInvoked); } if (showOnConsole) { getConsole().commandInvoked(commandInvoked); } } private void logConsoleCompleted(final long timeInMillis, final String msg, final int exitCode, final HgException hgex) { if(isDebugging){ System.out.println(msg); if(hgex != null){ hgex.printStackTrace(); } } if (showOnConsole) { getConsole().commandCompleted(exitCode, timeInMillis, msg, hgex); } } private String getMessage(OutputStream output) { String msg = null; if (output instanceof FileOutputStream) { return null; } else if (output instanceof ByteArrayOutputStream) { ByteArrayOutputStream baos = (ByteArrayOutputStream) output; try { msg = baos.toString(getEncoding()); } catch (UnsupportedEncodingException e) { logError(e); msg = baos.toString(); } if(msg != null){ msg = msg.trim(); } } return msg; } /** * Sets the command output charset if the charset is available in the VM. */ public void setEncoding(String charset) { encoding = charset; } /** * @return never returns null */ private String getEncoding() { if(encoding == null){ if (hgRoot != null) { encoding = hgRoot.getEncoding(); } else { encoding = getDefaultEncoding(); } } return encoding; } public String executeToString() throws HgException { return executeToString(true); } public String executeToString(boolean expectPositiveReturnValue) throws HgException { byte[] bytes = executeToBytes(getTimeOut(), expectPositiveReturnValue); if (bytes != null && bytes.length > 0) { try { return new String(bytes, getEncoding()); } catch (UnsupportedEncodingException e) { throw new HgException(e.getLocalizedMessage(), e); } } return ""; //$NON-NLS-1$ } /** * Executes a command and writes its output to a file. * * @param file * The file to which the output is written. * @param expectPositiveReturnValue * If set to {@code true}, an {@code HgException} will be thrown if the command's * exit code is not zero. * @return Returns {@code true} iff the command was executed successfully. * @throws HgException * Thrown when the command could not be executed successfully. */ public boolean executeToFile(File file, boolean expectPositiveReturnValue) throws HgException { int timeout = HgClients.getTimeOut(MercurialPreferenceConstants.DEFAULT_TIMEOUT); FileOutputStream fos = null; try { fos = new FileOutputStream(file, false); return executeToStream(fos, timeout, expectPositiveReturnValue); } catch (FileNotFoundException e) { throw new HgException(e.getMessage(), e); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { throw new HgException(e.getMessage(), e); } } } } private List getCommands() { if (commands != null) { return commands; } List result = new ArrayList(); result.add(getExecutable()); result.add(command); result.addAll(options); String listFilesFile = null; if (HgFeatures.LISTFILE.isEnabled() && getCommandLineLength(files) > 8000) { listFilesFile = createListFilesFile(files); } if(listFilesFile != null){ result.add(listFilesFile); } else { if (escapeFiles && !files.isEmpty()) { result.add("--"); //$NON-NLS-1$ } result.addAll(files); } customizeCommands(result); return commands = result; } private static String createListFilesFile(List paths) { BufferedWriter bw = null; try { File listFile = File.createTempFile("listfile_", "txt"); bw = new BufferedWriter(new FileWriter(listFile)); for (String file : paths) { bw.write(file); bw.newLine(); } bw.flush(); return HgFeatures.LISTFILE.getHgCmd() + listFile.getAbsolutePath(); } catch (IOException ioe) { MercurialEclipsePlugin.logError(ioe); return null; } finally { if(bw != null) { try { bw.close(); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } } } private static int getCommandLineLength(List cmds) { int length = 0; for (String f : cmds) { length += f.getBytes().length; } return length; } /** * Can be used after execution to get a list of paths needed to be updated * @return a copy of file paths affected by this command, if any. Never returns null, * but may return empty list. The elements of the set are absolute file paths. */ public Set getAffectedFiles(){ Set fileSet = new HashSet(); fileSet.addAll(files); return fileSet; } /** * Template method to customize the commands to execute * @param cmd The list of commands to execute. */ protected void customizeCommands(List cmd) { } protected abstract String getExecutable(); private String getRunDir() { String sDir = getExecutable(); int i; if (sDir != null) { i = Math.max(sDir.lastIndexOf('\\'), sDir.lastIndexOf('/')); if (i >= 0) { return sDir.substring(0, i); } } return ""; } /** * Add a file. Need not be canonical, but will try transform to canonical. * * @param myfiles The files to add */ public void addFiles(Collection myfiles) { for (File file : myfiles) { addFile(file); } } /** * Add a file. Looks like we must keep the file path (do not resolve), * see issue #20854. * Mercurial can deal with links by itself, but only if the link target is * under the hg root. resolving the link can move the path outside the hg root * and so hg will deny to collaborate :-) * * @param file The file to add */ public void addFile(File file) { files.add(file.getAbsolutePath()); } public void addFiles(IResource... resources) { for (IResource resource : resources) { addResource(resource); } } public void addFiles(List resources) { for (IResource resource : resources) { addResource(resource); } } /** * Add all resources that are of type IResource.FILE */ public void addFilesWithoutFolders(List resources) { for (IResource resource : resources) { if (resource.getType() == IResource.FILE) { addResource(resource); } } } private void addResource(IResource resource) { // TODO This can be done faster without any file system calls by saving uncanonicalized hg // root locations (?). // files.add(resource.getLocation().toOSString()); IPath location = ResourceUtils.getPath(resource); if(!location.isEmpty()) { addFile(location.toFile()); } } public void setUsePreferenceTimeout(String cloneTimeout) { this.timeoutConstant = cloneTimeout; } public void terminate() { if (processWrapper != null) { processWrapper.cancel(); } } private static IConsole getConsole() { return HgClients.getConsole(); } public void setShowOnConsole(boolean b) { showOnConsole = b; } private String getCommandInvoked(List cmd) { if(cmd.isEmpty()){ // paranoia return ""; } StringBuilder sb = new StringBuilder(); if(workingDir != null){ sb.append(workingDir); sb.append(':'); } String exec = cmd.get(0); exec = exec.replace('\\', '/'); int lastSep = exec.lastIndexOf('/'); if(lastSep <= 0){ sb.append(exec); } else { // just the exec. name, not the full path if(exec.endsWith(".exe")){ sb.append(exec.substring(lastSep + 1, exec.length() - 4)); } else { sb.append(exec.substring(lastSep + 1)); } } for (int i = 1; i < cmd.size(); i++) { sb.append(" ").append(cmd.get(i)); } return sb.toString(); } @Override public String toString() { StringBuilder builder = new StringBuilder(getClass().getSimpleName()); builder.append(" ["); if (command != null) { builder.append("command="); builder.append(command); builder.append(", "); } if (commands != null) { builder.append("commands="); builder.append(commands); builder.append(", "); } if (options != null) { builder.append("options="); builder.append(options); builder.append(", "); } if (workingDir != null) { builder.append("workingDir="); builder.append(workingDir); builder.append(", "); } if (files != null) { builder.append("files="); builder.append(files); builder.append(", "); } builder.append("escapeFiles="); builder.append(escapeFiles); builder.append(", "); if (processWrapper != null) { builder.append("processWrapper="); builder.append(processWrapper); builder.append(", "); } builder.append("showOnConsole="); builder.append(showOnConsole); builder.append(", "); if (timeoutConstant != null) { builder.append("timeoutConstant="); builder.append(timeoutConstant); } builder.append("]"); return builder.toString(); } private int getTimeOut() { int timeout; if (timeoutConstant == null) { timeoutConstant = MercurialPreferenceConstants.DEFAULT_TIMEOUT; } timeout = HgClients.getTimeOut(timeoutConstant); return timeout; } } ChangesetContentHandler.java000066400000000000000000000266201173713500500355150ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.regex.Pattern; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.model.FileStatus.Action; import com.vectrace.MercurialEclipse.team.cache.RemoteData; /** * This class helps HgClients to parse the changeset output of hg to Changeset * objects. * * @author Bastian Doetsch */ final class ChangesetContentHandler implements ContentHandler { private static final String[] EMPTY = new String[0]; private static final Pattern LT = Pattern.compile("<"); private static final Pattern GT = Pattern.compile(">"); private static final Pattern AMP = Pattern.compile("&"); private static final Pattern NEWLINE_TAB = Pattern.compile("\n\t"); private static final Pattern WORDS = Pattern.compile(" "); private String branchStr; private String tags; private int rev; private String nodeShort; private String nodeLong; private String dateIso; private String author; private String parents; private String description; private StringBuilder cDataChars; private boolean readCdata; private final IPath res; private final Direction direction; private final IHgRepositoryLocation repository; private final File bundleFile; private final HgRoot hgRoot; private final Map> fileRevisions; private Set filesModified; private Set filesAdded; private Set filesRemoved; private Map filesCopied; // destination -> source private Map filesMoved; // destination -> source private Action action; private String prevNodeShort; private int prevRev; private final String expectedBranch; private final IPath repoPath; private final boolean withFiles; ChangesetContentHandler(IPath res, boolean withFiles, Direction direction, IHgRepositoryLocation repository, File bundleFile, String branch, HgRoot hgRoot) { this.res = res; this.withFiles = withFiles; this.direction = direction; this.repository = repository; this.bundleFile = bundleFile; this.hgRoot = hgRoot; this.expectedBranch = branch; repoPath = new Path(hgRoot.getPath()); fileRevisions = new HashMap>(); } private boolean hasFileData() { return filesModified != null; } private void initFileData() { if (!hasFileData()) { filesModified = new TreeSet(); filesAdded = new TreeSet(); filesRemoved = new TreeSet(); filesCopied = new TreeMap(); filesMoved = new TreeMap(); } } private static String replaceAll(Pattern p, String source, String replacement){ return p.matcher(source).replaceAll(replacement); } private static String unescape(String string) { String result = replaceAll(LT, string, "<"); result = replaceAll(GT, result, ">"); return replaceAll(AMP, result, "&"); } /** * Remove a leading tab on each line in the string. * * @param string * @return */ private static String untab(String string) { return replaceAll(NEWLINE_TAB, string, "\n"); } private static String[] splitWords(String string) { if (string == null || string.length() == 0) { return EMPTY; } return WORDS.split(string); } public void characters(char[] ch, int start, int length) { if(readCdata) { cDataChars.append(ch, start, length); } } public void endDocument() throws SAXException { } public void endElement(String uri, String localName, String name) throws SAXException { if ("de".equals(name)) { description = cDataChars.toString(); } else if ("br".equals(name)) { branchStr = cDataChars.toString(); } else if ("tg".equals(name)) { tags = cDataChars.toString(); } else if ("cs".equals(name)) { // only collect changesets from requested branch. Null is: collect everything. if(expectedBranch == null || Branch.same(branchStr, expectedBranch)){ ChangeSet.Builder csb = new ChangeSet.Builder(rev, nodeLong, branchStr, dateIso, unescape(author), hgRoot); csb.tags(tags); csb.nodeShort(nodeShort); csb.description(untab(unescape(description))); addParentsInfo(csb); csb.bundleFile(bundleFile); csb.direction(direction); csb.repository(repository); if (hasFileData()) { List list = new ArrayList( filesModified.size() + filesAdded.size() + filesRemoved.size()); for (String file : filesModified) { list.add(new FileStatus(FileStatus.Action.MODIFIED, file, hgRoot)); } for (String file : filesAdded) { list.add(new FileStatus(FileStatus.Action.ADDED, file, hgRoot)); } for (String file : filesRemoved) { list.add(new FileStatus(FileStatus.Action.REMOVED, file, hgRoot)); } for(Map.Entry entry : filesCopied.entrySet()){ list.add(new FileStatus(FileStatus.Action.COPIED, entry.getKey(), entry.getValue(), hgRoot)); } for(Map.Entry entry : filesMoved.entrySet()){ list.add(new FileStatus(FileStatus.Action.MOVED, entry.getKey(), entry.getValue(), hgRoot)); } csb.changedFiles(list.toArray(new FileStatus[list.size()])); } ChangeSet changeSet = csb.build(); // changeset to resources & project addChangesetToResourceMap(changeSet); } if (hasFileData()) { filesModified.clear(); filesAdded.clear(); filesRemoved.clear(); filesCopied.clear(); filesMoved.clear(); } prevRev = rev; prevNodeShort = nodeShort; } } /** * It seems that hg do not report parents if the parent changeset is printed out in * the same command output. So we guess: if parents are empty, we have to create them * from the revision + short node of the previous run. * @param csb */ private void addParentsInfo(ChangeSet.Builder csb) { String[] myParents = splitWords(parents); if(myParents.length == 0 && prevRev == rev - 1 && prevNodeShort != null){ myParents = new String[]{prevRev + ":" + prevNodeShort}; } csb.parents(myParents); } /** *

* Format of input is defined in the two style files in /styles and is as * follows for each changeset. * *

	 * <cs>
	 * <br v="{branches}"/>
	 * <tg v="{tags}"/>
	 * <rv v="{rev}"/>
	 * <ns v="{node|short}"/>
	 * <nl v="{node}"/>
	 * <di v="{date|isodate}"/>
	 * <da v="{date|age}"/>
	 * <au v="{author|person}"/>
	 * <pr v="{parents}"/>
	 * <de v="{desc|escape|tabindent}"/>
	 * <fl v="{files}"/>
	 * <fa v="{file_adds}"/>
	 * <fd v="{file_dels}"/>
	 * <f v="{root relative path}"/>
	 * </cs>
	 * 
* {@inheritDoc} */ public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException { /* *
* {desc|escape|tabindent} */ readCdata = false; if ("br".equals(name)) { branchStr = null; cDataChars = new StringBuilder(42); readCdata = true; } else if ("tg".equals(name)) { tags = null; cDataChars = new StringBuilder(42); readCdata = true; } else if ("rv".equals(name)) { rev = Integer.parseInt(atts.getValue(0)); } else if ("ns".equals(name)) { nodeShort = atts.getValue(0); } else if ("nl".equals(name)) { nodeLong = atts.getValue(0); } else if ("di".equals(name)) { dateIso = atts.getValue(0); } else if ("au".equals(name)) { author = atts.getValue(0); } else if ("pr".equals(name)) { parents = atts.getValue(0); } else if ("de".equals(name)) { description = null; cDataChars = new StringBuilder(42); readCdata = true; } else if ("fl".equals(name)) { initFileData(); action = FileStatus.Action.MODIFIED; } else if ("fa".equals(name)) { initFileData(); action = FileStatus.Action.ADDED; } else if ("fd".equals(name)) { initFileData(); action = FileStatus.Action.REMOVED; } else if ("fc".equals(name)) { initFileData(); action = FileStatus.Action.COPIED; } else if ("f".equals(name)) { if (action == Action.MODIFIED) { filesModified.add(atts.getValue("", "v")); } else if (action == Action.ADDED) { String value = atts.getValue("", "v"); filesAdded.add(value); } else if (action == Action.REMOVED) { String value = atts.getValue("", "v"); filesRemoved.add(value); } else if(action == Action.COPIED) { String dest = atts.getValue("", "v"); String src = atts.getValue("", "s"); if(filesRemoved.contains(src)){ filesMoved.put(dest, src); }else{ filesCopied.put(dest, src); } filesAdded.remove(dest); filesRemoved.remove(src); } } } private void addChangesetToResourceMap(final ChangeSet cs) { if(withFiles) { if (cs.getChangedFiles() != null) { for (FileStatus file : cs.getChangedFiles()) { IPath fileAbsPath = file.getAbsolutePath(); mapPathToChangeset(fileAbsPath, cs); } } mapPathToChangeset(res, cs); } else { mapPathToChangeset(repoPath, cs); } } private void mapPathToChangeset(IPath path, ChangeSet cs) { Set fileRevs = fileRevisions.get(path); if (fileRevs == null) { fileRevs = new HashSet(); } fileRevs.add(cs); fileRevisions.put(path, fileRevs); } /** * @return never null */ public Map> getFileRevisions() { return fileRevisions; } public RemoteData createRemoteData() { return new RemoteData(repository, hgRoot, expectedBranch, direction, fileRevisions); } //#################################################################################### public void endPrefixMapping(String prefix) throws SAXException { } public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { } public void processingInstruction(String target, String data) throws SAXException { } public void setDocumentLocator(Locator locator) { } public void skippedEntity(String name) throws SAXException { } public void startDocument() throws SAXException { } public void startPrefixMapping(String prefix, String uri) throws SAXException { } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/GpgCommand.java000066400000000000000000000024441173713500500330540ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.util.List; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; /** * @author bastian * */ public class GpgCommand extends AbstractShellCommand { public GpgCommand(HgRoot hgRoot, String uiName, List commands, File workingDir) { super(uiName, hgRoot, commands, workingDir, false); } /** * @see com.vectrace.MercurialEclipse.commands.AbstractShellCommand#getExecutable() */ @Override protected String getExecutable() { return MercurialEclipsePlugin.getDefault().getPreferenceStore() .getString(MercurialPreferenceConstants.GPG_EXECUTABLE); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgAddClient.java000066400000000000000000000051321173713500500331430ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.HgFeatures; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgAddClient extends AbstractClient { public static void addResources(List resources, IProgressMonitor monitor) throws HgException { Map> resourcesByRoot = ResourceUtils.groupByRoot(resources); for (Map.Entry> mapEntry : resourcesByRoot.entrySet()) { HgRoot hgRoot = mapEntry.getKey(); if (monitor != null) { monitor.subTask(Messages.getString("HgAddClient.addingResourcesFrom") + hgRoot.getName()); //$NON-NLS-1$ } // if there are too many resources, do several calls // From 1.8 hg can do it in one call if(!HgFeatures.LISTFILE.isEnabled()) { int size = mapEntry.getValue().size(); @SuppressWarnings("deprecation") int delta = AbstractShellCommand.MAX_PARAMS - 1; for (int i = 0; i < size; i += delta) { final int j = Math.min(i + delta, size); AbstractShellCommand command = new HgCommand("add", //$NON-NLS-1$ "Adding " + j + " resources", hgRoot, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.ADD_TIMEOUT); command.addFiles(mapEntry.getValue().subList(i, j)); command.executeToBytes(); } } else { AbstractShellCommand command = new HgCommand("add", //$NON-NLS-1$ "Adding resources", hgRoot, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.ADD_TIMEOUT); command.addFiles(mapEntry.getValue()); command.executeToBytes(); } } } } HgAnnotateClient.java000066400000000000000000000061011173713500500341420ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) Subclipse and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Charles O'Farrell - implementation (based on subclipse) * StefanC - remove empty lines, code cleenup * Jérôme Nègre - make it work * Bastian Doetsch - refactorings * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.annotations.AnnotateBlock; import com.vectrace.MercurialEclipse.annotations.AnnotateBlocks; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; public class HgAnnotateClient { private static final Pattern ANNOTATE = Pattern .compile("^\\s*(.+?)\\s+(\\d+)\\s+(\\w+)\\s+(\\w+ \\w+ \\d+ \\d+:\\d+:\\d+ \\d+ [\\+\\-]\\d+)"); //$NON-NLS-1$ private static final DateFormat DATE_FORMAT = new SimpleDateFormat( "EEE MMM dd HH:mm:ss yyyy Z", Locale.ENGLISH); //$NON-NLS-1$ public static AnnotateBlocks execute(IResource file) throws HgException { if (!MercurialTeamProvider.isHgTeamProviderFor(file)) { return null; } HgCommand command = new HgCommand("annotate", "Fetching annotations for resource", file, true); command.addOptions("--follow", "--user", "--number", "--changeset", "--date"); command.addFiles(file); return createFromStdOut(new StringReader(command.executeToString())); } public static AnnotateBlocks createFromStdOut(InputStream contents) { return createFromStdOut(new InputStreamReader(contents)); } protected static synchronized AnnotateBlocks createFromStdOut(Reader contents) { AnnotateBlocks blocks = new AnnotateBlocks(); try { BufferedReader reader = new BufferedReader(contents); int count = 0; String line; while ((line = reader.readLine()) != null) { Matcher matcher = ANNOTATE.matcher(line); if (!matcher.find()) { // ignore empty lines continue; } String author = matcher.group(1); int revision = Integer.parseInt(matcher.group(2)); String changeset = matcher.group(3); Date date = DATE_FORMAT.parse(matcher.group(4)); blocks.add(new AnnotateBlock( new HgRevision(changeset, revision), author, date, count, count)); count++; } } catch (Exception e) { throw new RuntimeException(e); } return blocks; } } HgBackoutClient.java000066400000000000000000000042451173713500500337700ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian * */ public class HgBackoutClient extends AbstractClient { /** * Backout of a changeset * * @param hgRoot * the project * @param backoutRevision * revision to backout * @param merge * flag if merge with a parent is wanted * @param msg * commit message */ public static String backout(final HgRoot hgRoot, ChangeSet backoutRevision, boolean merge, String msg, String user) throws HgException { HgCommand command = new HgCommand("backout", //$NON-NLS-1$ "Backing out changeset " + backoutRevision.getChangeset(), hgRoot, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); addMergeToolPreference(command); command.addOptions("-r", backoutRevision.getChangeset(), "-m", msg); //$NON-NLS-1$ //$NON-NLS-2$ command.addUserName(user); if (merge) { command.addOptions("--merge"); //$NON-NLS-1$ } String result = command.executeToString(); command.rememberUserName(); return result; } public static boolean isMergeError(HgException e) { // eg: (without --merge) // reverting src/file1.text // adding src/file2.txt // removing src/file22.txt // 0 files updated, 0 files merged, 0 files removed, 1 files unresolved // use 'hg resolve' to retry unresolved file merges. return HgUpdateClient.isWorkspaceUpdateConflict(e); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgBisectClient.java000066400000000000000000000106041173713500500336640ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan Chyssler implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; import java.util.Map; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author Stefan Chyssler * */ public final class HgBisectClient extends AbstractClient { public enum Status { GOOD, BAD } /** * Marks the specified changeset as a good revision. If no changeset is specified * bisect will use the "current" changeset. * * @param repository the repository to bisect * @param good the changeset to mark as good, or null for current * @return a message from the command * @throws HgException */ public static String markGood(HgRoot repository, ChangeSet good) throws HgException { AbstractShellCommand cmd = new HgCommand("bisect", "Bisect: marking revision as good", repository, true); //$NON-NLS-1$ cmd.addOptions("-g"); //$NON-NLS-1$ if(good != null) { cmd.addOptions(getRevision(good)); } return cmd.executeToString(); } /** * Marks the specified changeset as a bad revision. If no changeset is specified * bisect will use teh "current" changeset. * * @param repository the repository to bisect * @param bad the changeset to mark as bad, or null for current * @return a message from the command * @throws HgException */ public static String markBad(HgRoot repository, ChangeSet bad) throws HgException { AbstractShellCommand cmd = new HgCommand("bisect", //$NON-NLS-1$ "Bisect: marking revision as bad", repository, true); cmd.addOptions("-b"); //$NON-NLS-1$ if(bad != null) { cmd.addOptions(getRevision(bad)); } return cmd.executeToString(); } /** * Resets the bisect status for this repository. This command will not update the repository * to the head. * @param repository the repository to reset bisect status for * @return * @throws HgException */ public static String reset(HgRoot repository) throws HgException { AbstractShellCommand cmd = new HgCommand("bisect", //$NON-NLS-1$ "Reseting bisect", repository, true); cmd.addOptions("-r"); //$NON-NLS-1$ return cmd.executeToString(); } /** * Checks if the repository is currently being bisected */ public static boolean isBisecting(HgRoot hgRoot) { return getStatusFile(hgRoot).exists(); } /** * Gets a Status by Changeset map containing marked bisect statuses. * @param hgRoot * @return * @throws HgException */ public static Map getBisectStatus(HgRoot hgRoot) throws HgException { HashMap statusByRevision = new HashMap(); if(!isBisecting(hgRoot)) { return statusByRevision; } BufferedReader reader = null; try { File file = getStatusFile(hgRoot); reader = new BufferedReader(new FileReader(file)); String line = null; while(null != (line = reader.readLine())) { String[] statusChangeset = line.split("\\s"); //$NON-NLS-1$ if(statusChangeset[0].equalsIgnoreCase("bad")) { //$NON-NLS-1$ statusByRevision.put(statusChangeset[1].trim(), Status.BAD); } else { statusByRevision.put(statusChangeset[1].trim(), Status.GOOD); } } } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } return statusByRevision; } private static File getStatusFile(HgRoot hgRoot) { return new File(hgRoot, ".hg" + File.separator + "bisect.state"); //$NON-NLS-1$ //$NON-NLS-2$ } private static String getRevision(ChangeSet change) { return Integer.toString(change.getRevision().getRevision()); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgBranchClient.java000066400000000000000000000147771173713500500336670ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RemoteKey; import com.vectrace.MercurialEclipse.utils.StringUtils; public class HgBranchClient extends AbstractClient { /** * matches branch names which may also contain spaces or consist of only one letter. * Valid examples: * "a test 3:066ee3f79d2a" * "* 2:5a953790aa12 (inactive)" * "default 0:fd83cc49d230 (inactive)" */ private static final Pattern GET_BRANCHES_PATTERN = Pattern.compile( // (branch name) (version):(hash) (optional "inactive" flag) "^(.*[^ ]+) +([0-9]+):([a-f0-9]+)( +(.+))?$"); //$NON-NLS-1$ private static final Map KNOWN_BRANCHES = new ConcurrentHashMap(); /** * Returns all available (not closed) branches * @param hgRoot non null * @return never null, but possibly empty array * @throws HgException */ public static Branch[] getBranches(HgRoot hgRoot) throws HgException { AbstractShellCommand command = new HgCommand("branches", "Listing branches", hgRoot, false); //$NON-NLS-1$ command.addOptions("-v"); //$NON-NLS-1$ String[] lines = command.executeToString().split("\n"); //$NON-NLS-1$ List branches = new ArrayList(); for (String line : lines) { if(StringUtils.isEmpty(line)){ continue; } Branch branch = parseBranch(line); if (branch != null) { branches.add(branch); } else { HgException ex = new HgException("Failed to parse branch from '" + line + "'"); //$NON-NLS-1$ //$NON-NLS-2$ MercurialEclipsePlugin.logWarning("Failed to parse branch", ex); //$NON-NLS-1$ } } Collections.sort(branches, Branch.COMPARATOR); return branches.toArray(new Branch[branches.size()]); } protected static Branch parseBranch(String line) { Matcher m = GET_BRANCHES_PATTERN.matcher(line.trim()); if (m.matches()) { Branch branch = new Branch(m.group(1), Integer.parseInt(m.group(2)), m.group(3), !"(inactive)".equals(m.group(5))); //$NON-NLS-1$ return branch; } return null; } /** * @param user * if null, uses the default user * @throws HgException */ public static String addBranch(HgRoot hgRoot, String name, String user, boolean force) throws HgException { HgCommand command = new HgCommand("branch", "Creating branch " + name, hgRoot, false); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); if (force) { command.addOptions("-f"); //$NON-NLS-1$ } command.addOptions(name); return command.executeToString(); } /** * Get active branch of working directory * * @param workingDir * a file or a directory within the local repository * @return the branch name, never null * @throws HgException * if a hg error occurred */ public static String getActiveBranch(HgRoot workingDir) throws HgException { AbstractShellCommand command = new HgCommand("branch", "Retrieving current branch name", workingDir, false); //$NON-NLS-1$ return command.executeToString().replaceAll("\n", ""); } /** * @param key non null * @return true if the given branch is known at remote repository */ public static boolean isKnownRemote(RemoteKey key) { String branch = key.getBranch(); if(Branch.isDefault(branch)){ // default is always there return true; } Boolean result = KNOWN_BRANCHES.get(key); if(Boolean.TRUE.equals(result)){ return true; } // we are using "hg incoming" to check if remote repository knows the given branch // unfortunately I didn't found more elegant way to get this infor from hg for // REMOTE repository, because neither "hg branch" nor "hg branches" works then AbstractShellCommand command = new HgCommand("incoming", //$NON-NLS-1$ "Querying remote branch existence", key.getRoot(), false); command.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT); // limit to one version command.addOptions("-l", "1"); // try to access the the branch command.addOptions("-r", branch); IHgRepositoryLocation repository = key.getRepo(); URI uri; try { uri = repository.getUri(); } catch (HgException e) { MercurialEclipsePlugin.logError(e); return false; } if (uri != null) { command.addOptions(uri.toASCIIString()); } else { command.addOptions(repository.getLocation()); } try { command.executeToString(); // remember branch, don't ask each time. The probability that somebody "closes" it is very low KNOWN_BRANCHES.put(key, Boolean.TRUE); return true; } catch (HgException e) { String message = e.getMessage(); // not sure how reliable this is. On non-default language systems the first // part won't work. The second part (exit code) may rely on different OS implementations... // Incoming responds with an exception if there are no incoming changesets... // but exception is different if no branch exists on remote. So trying to // distinguish between "no changesets" and "unknown branch (== unknown revision)" if (message.contains("no changes found") && !message.contains("unknown revision") && e.getStatus().getCode() == 1) { KNOWN_BRANCHES.put(key, Boolean.TRUE); return true; } // TODO we should improve it later, if we can keep the "unknown branches" state up to date // right now don't save "unknown" state, as it may change at any time return false; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgBundleClient.java000066400000000000000000000040451173713500500336660ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. All rights * reserved. This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 which accompanies this * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: Bastian Doetsch - implementation ******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; public class HgBundleClient extends AbstractClient { public static String bundle(HgRoot root, ChangeSet rev, String targetRepo, String file, boolean all, String base) throws HgException { AbstractShellCommand cmd = new HgCommand("bundle", "Exporting revisions to bundle", root, true); cmd.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule( root)); cmd.setUsePreferenceTimeout(MercurialPreferenceConstants.PUSH_TIMEOUT); if (rev != null) { cmd.addOptions("-r", rev.getChangeset()); } if (all) { cmd.addOptions("-a"); } else if (base != null && base.length() > 0) { cmd.addOptions("--base", base); } cmd.addOptions(file); if (targetRepo != null && targetRepo.length() > 0) { cmd.addOptions(targetRepo); } return cmd.executeToString(); } public static String unbundle(HgRoot root, boolean update, String file) throws HgException { AbstractShellCommand cmd = new HgCommand("unbundle", "Importing revisions from bundle", root, true); cmd.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule( root)); cmd.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT); if (update) { cmd.addOptions("-u"); } cmd.addOptions(file); return cmd.executeToString(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgCatClient.java000066400000000000000000000063461173713500500331720ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.IOException; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.Assert; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgFile; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgCatClient extends AbstractClient { public static byte[] getContent(IFile resource, String revision) throws HgException { HgRoot hgRoot = getHgRoot(resource); File file = ResourceUtils.getFileHandle(resource); AbstractShellCommand command = new HgCommand("cat", "Retrieving file contents", hgRoot, true); if (revision != null && revision.length() != 0) { command.addOptions("-r", revision); //$NON-NLS-1$ } command.addOptions("--decode"); //$NON-NLS-1$ command.addOptions(hgRoot.toRelative(file)); return command.executeToBytes(); } public static byte[] getContent(IHgFile hgfile) throws HgException { HgRoot hgRoot = hgfile.getHgRoot(); AbstractShellCommand command = new HgCommand("cat", "Retrieving file contents", hgRoot, true); String revision = hgfile.getChangeSet() == null? null : hgfile.getChangeSet().getChangeset(); if (revision != null && revision.length() != 0) { command.addOptions("-r", revision); //$NON-NLS-1$ } command.addOptions("--decode"); //$NON-NLS-1$ command.addOptions(hgfile.getHgRootRelativePath()); return command.executeToBytes(); } public static byte[] getContentFromBundle(IFile resource, String revision, File overlayBundle) throws HgException, IOException { Assert.isNotNull(overlayBundle); HgRoot hgRoot = getHgRoot(resource); File file = ResourceUtils.getFileHandle(resource); HgCommand hgCommand = new HgCommand("cat", "Retrieving file contents from bundle", hgRoot, true); hgCommand.setBundleOverlay(overlayBundle); if (revision != null && revision.length() != 0) { hgCommand.addOptions("-r", revision); } hgCommand.addOptions("--decode", hgRoot.toRelative(file)); return hgCommand.executeToBytes(); } public static byte[] getContentFromBundle(IHgFile hgfile, String revision, File overlayBundle) throws HgException, IOException { Assert.isNotNull(overlayBundle); HgRoot hgRoot = hgfile.getHgRoot(); HgCommand hgCommand = new HgCommand("cat", "Retrieving file contents from bundle", hgRoot, true); hgCommand.setBundleOverlay(overlayBundle); if (revision != null && revision.length() != 0) { hgCommand.addOptions("-r", revision); } hgCommand.addOptions("--decode", hgfile.getHgRootRelativePath()); return hgCommand.executeToBytes(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgClients.java000066400000000000000000000037421173713500500327220ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * @author Stefan * */ public final class HgClients { private static IConsole console; private static IConfiguration config; private static IErrorHandler error; private HgClients() { // hide constructor of utility class. } public static void initialize(IConsole c, IErrorHandler errorHandler, IConfiguration configuration) { HgClients.config = configuration; HgClients.console = c; HgClients.error = errorHandler; } public static String getExecutable() { if (config == null) { throw new IllegalStateException( Messages.getString("HgClients.error.notInitializedWithConfig")); //$NON-NLS-1$ } return config.getExecutable(); } public static IConsole getConsole() { if (console == null) { throw new IllegalStateException( Messages.getString("HgClients.error.notInitializedWithConsole")); //$NON-NLS-1$ } return console; } public static void logError(Throwable e) { error.logError(e); } public static void logWarning(String message, Throwable e) { error.logWarning(message, e); MercurialEclipsePlugin.logWarning(message, e); } public static int getTimeOut(String commandId) { return config.getTimeOut(commandId); } public static String getPreference(String preferenceConstant, String defaultIfNotSet) { return config.getPreference(preferenceConstant, defaultIfNotSet); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgCloneClient.java000066400000000000000000000036061173713500500335170ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes * Philip Graf - proxy support *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; public class HgCloneClient extends AbstractClient { public static void clone(File parentDirectory, IHgRepositoryLocation repo, boolean noUpdate, boolean pull, boolean uncompressed, boolean timeout, String rev, String cloneName) throws HgException { AbstractShellCommand command = new RootlessHgCommand("clone", "Cloning", parentDirectory); //$NON-NLS-1$ addInsecurePreference(command); if (noUpdate) { command.addOptions("--noupdate"); //$NON-NLS-1$ } if (pull) { command.addOptions("--pull"); //$NON-NLS-1$ } if (uncompressed) { command.addOptions("--uncompressed"); //$NON-NLS-1$ } if (rev != null && rev.length() > 0) { command.addOptions("--rev", rev); //$NON-NLS-1$ } addRepoToHgCommand(repo, command); if (cloneName != null) { command.addOptions(cloneName); } if (timeout) { command .setUsePreferenceTimeout(MercurialPreferenceConstants.CLONE_TIMEOUT); command.executeToBytes(); } else { command.executeToBytes(Integer.MAX_VALUE); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgCommand.java000066400000000000000000000143341173713500500326760ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch * Andrei Loskutov - bug fixes * John Peberdy - refactoring *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * * @author Jerome Negre */ public class HgCommand extends AbstractShellCommand { private static final Set COMMANDS_CONFLICTING_WITH_USER_ARG = Collections.unmodifiableSet(new HashSet(Arrays.asList( "clone", "pull", "resolve", "showconfig", "status", "unbundle" ))); private String lastUserName; private String bundleFile; // constructors public HgCommand(String command, String uiName, HgRoot root, boolean escapeFiles) { super(uiName, root, root, escapeFiles); this.command = command; Assert.isNotNull(command); Assert.isNotNull(hgRoot); } /** * Invoke a hg command in the directory of the given resource using the resource to find the HgRoot. * * @param command The command to execute * @param uiName Human readable name for this command * @param resource The resource to use for working directory * @param escapeFiles Whether to escape files * @throws HgException */ public HgCommand(String command, String uiName, IResource resource, boolean escapeFiles) throws HgException { super(uiName, AbstractClient.getHgRoot(resource), ResourceUtils.getFirstExistingDirectory(ResourceUtils.getFileHandle(resource)), escapeFiles); this.command = command; Assert.isNotNull(command); Assert.isNotNull(hgRoot); } // operations public HgRoot getHgRoot() { return hgRoot; } /** * NOTE! this method works only for hg commands which knows "-u" argument * AND which understood "-u" as user name. There are commands which accept "-u" but * treat is differently: like "resolve" or "status" (see {@link #isConflictingWithUserArg()}). * * @param user might be null or empty. In such case, a default user name will be used. * @throws IllegalArgumentException if the command uses "-u" NOT as user name parameter */ public void addUserName(String user) throws IllegalArgumentException { // avoid empty user user = user != null ? user : MercurialUtilities.getDefaultUserName(); if(user != null) { user = user.trim(); if (user.length() == 0) { user = null; } else { user = quote(user); } } if(user != null) { if (isConflictingWithUserArg()) { throw new IllegalArgumentException("Command '" + command + "' uses '-u' argument NOT as user name!"); } options.add("-u"); //$NON-NLS-1$ options.add(user); this.lastUserName = user; } else { this.lastUserName = null; } } public void addStyleFile(int style) throws HgException { try { addOptions("--style", //$NON-NLS-1$ AbstractParseChangesetClient.getStyleFile(style).getCanonicalPath()); } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } } /** * Remembers the user name given as option (see {@link #addUserName(String)}) as the default * user name for current hg root. Should be called only after the command was successfully * executed. If no hg root or no user name option was given, does nothing. */ public void rememberUserName(){ if (lastUserName == null){ return; } String commitName = HgCommitMessageManager.getDefaultCommitName(hgRoot); if(!commitName.equals(lastUserName)) { HgCommitMessageManager.setDefaultCommitName(hgRoot, lastUserName); } } private boolean isConflictingWithUserArg() { if(command == null){ // TODO can it happen??? return false; } return COMMANDS_CONFLICTING_WITH_USER_ARG.contains(command); } public void setBundleOverlay(File file) throws IOException { if (file != null) { bundleFile = file.getCanonicalPath(); } else { bundleFile = null; } } /** * @param str non null, non empty string * @return non null string with escaped quotes (depending on the OS) */ private static String quote(String str) { if (!MercurialUtilities.isWindows()) { return str; } // escape quotes, otherwise commit will fail at least on windows return str.replace("\"", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$ } /** * @see com.vectrace.MercurialEclipse.commands.AbstractShellCommand#customizeCommands(java.util.List) */ @Override protected void customizeCommands(List cmd) { if (bundleFile != null) { // Add -R cmd.add(1, bundleFile); cmd.add(1, "-R"); } cmd.add(1, "-y"); } /** * @see com.vectrace.MercurialEclipse.commands.AbstractShellCommand#getExecutable() */ @Override protected String getExecutable() { return HgClients.getExecutable(); } /** * @see com.vectrace.MercurialEclipse.commands.AbstractShellCommand#setupEncoding(java.util.List) */ @Override protected String setupEncoding(List cmd) { String charset = hgRoot.getEncoding(); // Enforce strict command line encoding cmd.add(1, charset); cmd.add(1, "--encoding"); // Enforce fallback encoding for UI (command output) // Note: base encoding is UTF-8 for mercurial, fallback is only take into account // if actual platfrom don't support it. cmd.add(1, "ui.fallbackencoding=" + hgRoot.getFallbackencoding().name()); //$NON-NLS-1$ cmd.add(1, "--config"); //$NON-NLS-1$ return charset; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgCommitClient.java000066400000000000000000000153231173713500500337060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch * StefanC * Zsolt Koppany (Intland) * Adam Berkes (Intland) * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Collections; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgCommitClient extends AbstractClient { /** * Commit given resources and refresh the caches for the associated projects */ public static String commitResources(List resources, String user, String message, IProgressMonitor monitor, boolean closeBranch) throws HgException { Map> resourcesByRoot = ResourceUtils.groupByRoot(resources); StringBuilder commit = new StringBuilder(); for (Map.Entry> mapEntry : resourcesByRoot.entrySet()) { HgRoot root = mapEntry.getKey(); if (monitor != null) { if (monitor.isCanceled()) { break; } monitor.subTask(Messages.getString("HgCommitClient.commitJob.committing") + root.getName()); //$NON-NLS-1$ } List files = mapEntry.getValue(); commit.append(commit(root, AbstractClient.toFiles(files), user, message, closeBranch)); } for (HgRoot root : resourcesByRoot.keySet()) { new RefreshRootJob(root, RefreshRootJob.LOCAL_AND_OUTGOING).schedule(); } return commit.toString(); } /** * Commit given hg root with all checked out/added/deleted changes and refresh the caches for the assotiated projects */ public static String commitResources(HgRoot root, boolean closeBranch, String user, String message, IProgressMonitor monitor) throws HgException { monitor.subTask(Messages.getString("HgCommitClient.commitJob.committing") + root.getName()); //$NON-NLS-1$ List emptyList = Collections.emptyList(); try { return commit(root, emptyList, user, message, closeBranch); } finally { new RefreshRootJob(root, RefreshRootJob.LOCAL_AND_OUTGOING).schedule(); } } /** * Performs commit. No refresh of any cashes is done afterwards. * * Note clients should not use this method directly, it is NOT private * for tests only */ protected static String commit(HgRoot hgRoot, List files, String user, String message, boolean closeBranch) throws HgException { HgCommand command = new HgCommand("commit", "Committing resources", hgRoot, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.COMMIT_TIMEOUT); command.addUserName(user); if (closeBranch) { command.addOptions("--close-branch"); } File messageFile = addMessage(command, message); try { command.addFiles(files); String result = command.executeToString(); command.rememberUserName(); return result; } finally { deleteMessage(messageFile); } } /** * Add the message to the command. If possible a file is created to do this (assumes the command * accepts the -l parameter) * * @return The file that must be deleted * @see #deleteMessage(File) */ public static File addMessage(HgCommand command, String message) { File messageFile = saveMessage(message, command); if (messageFile != null && messageFile.isFile()) { command.addOptions("-l", messageFile.getAbsolutePath()); return messageFile; } // fallback in case of unavailable message file message = quote(message.trim()); if (message.length() != 0) { command.addOptions("-m", message); } else { command.addOptions("-m", com.vectrace.MercurialEclipse.dialogs.Messages .getString("CommitDialog.defaultCommitMessage")); } return messageFile; } /** * Commit given project after the merge and refresh the caches. * Implementation note: after merge, no files should be specified. */ public static String commit(HgRoot hgRoot, String user, String message) throws HgException { HgCommand command = new HgCommand("commit", "Committing all changes", hgRoot, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.COMMIT_TIMEOUT); command.addUserName(user); File messageFile = addMessage(command, message); try { String result = command.executeToString(); command.rememberUserName(); new RefreshRootJob(hgRoot, RefreshRootJob.LOCAL_AND_OUTGOING).schedule(); return result; } finally { deleteMessage(messageFile); } } private static String quote(String str) { if (str != null) { str = str.trim(); } if (str == null || str.length() == 0 || !MercurialUtilities.isWindows()) { return str; } // escape quotes, otherwise commit will fail at least on windows return str.replace("\"", "\\\""); //$NON-NLS-1$ //$NON-NLS-2$ } private static File saveMessage(String message, HgCommand command) { Writer writer = null; try { File messageFile = File.createTempFile("hgcommitmsg", ".txt"); writer = new OutputStreamWriter(new FileOutputStream(messageFile), command.getHgRoot().getEncoding()); writer.write(message.trim()); return messageFile; } catch (IOException ex) { MercurialEclipsePlugin.logError(ex); return null; } finally { if (writer != null) { try { writer.close(); } catch (IOException ex) { MercurialEclipsePlugin.logError(ex); } } } } public static void deleteMessage(File messageFile) { // Try to delete normally, and if not successful // leave it for the JVM exit - I use it in case // mercurial accidentally locks the file. if (messageFile != null && !messageFile.delete()) { messageFile.deleteOnExit(); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgConfigClient.java000066400000000000000000000021621173713500500336600ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import com.vectrace.MercurialEclipse.exception.HgException; /** * @author bastian * */ public class HgConfigClient extends AbstractClient { public static String getHgConfigLine(String key) throws HgException { String[] lines = getHgConfigLines(key); return lines[0]; } private static String[] getHgConfigLines(String key) throws HgException { AbstractShellCommand cmd = new RootlessHgCommand("showconfig", "Getting configuration information"); cmd.addOptions(key); String[] lines = cmd.executeToString().split("\n"); //$NON-NLS-1$ return lines; } } HgDebugInstallClient.java000066400000000000000000000045451173713500500347600ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.Collections; import java.util.HashMap; import java.util.Map; import com.vectrace.MercurialEclipse.exception.HgException; public class HgDebugInstallClient extends AbstractClient { /** * Key is the charset name, value is "true" if hg supports this charset encoding */ public static final Map ENCODINGS = Collections .synchronizedMap(new HashMap()); public static String debugInstall() throws HgException { AbstractShellCommand command = getDebugInstallCommand(); return new String(command.executeToBytes(Integer.MAX_VALUE)).trim(); } private static AbstractShellCommand getDebugInstallCommand() { return new RootlessHgCommand("debuginstall", "Checking Mercurial installation") { { isInitialCommand = startSignal.getCount() > 0; } }; } /** * @param defaultCharset non null * @return true if the given changeset is supported by the hg installation */ public static boolean hgSupportsEncoding(String defaultCharset) { Boolean b; synchronized(ENCODINGS){ b = ENCODINGS.get(defaultCharset); } if (b == null) { AbstractShellCommand cmd = getDebugInstallCommand(); cmd.addOptions("--encoding", defaultCharset); //$NON-NLS-1$ try { cmd.executeToString(); } catch (HgException e) { // there might have been an exception but it is not necessarily // related to the encoding. so only return false if the following // string is in the message if (e.getMessage().contains("unknown encoding:")) { //$NON-NLS-1$ synchronized(ENCODINGS){ ENCODINGS.put(defaultCharset, Boolean.FALSE); } return false; } } synchronized(ENCODINGS){ ENCODINGS.put(defaultCharset, Boolean.TRUE); } return true; } return b.booleanValue(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgGrepClient.java000066400000000000000000000053311173713500500333510ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.search.MercurialTextSearchMatchAccess; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * @author Bastian * */ public class HgGrepClient extends AbstractClient { /** * Greps given Hg repo with params -lnu -all for given pattern * * @param root * @param pattern * @param all * @param res * @return * @throws HgException */ public static List grep(HgRoot root, String pattern, List files, boolean all, final IProgressMonitor monitor) throws HgException { final AbstractShellCommand cmd = new HgCommand("grep", "Searching repository", root, true); cmd.addOptions("-nuf"); if (all) { cmd.addOptions("--all"); } if (StringUtils.isEmpty(pattern)) { return new ArrayList(); } cmd.addOptions(pattern); cmd.addFilesWithoutFolders(files); String result = null; if (monitor != null) { Timer t = new Timer("HG GREP watcher"); try { t.schedule(new TimerTask() { @Override public void run() { if (monitor.isCanceled()) { cmd.terminate(); cancel(); } } }, 100, 100); result = cmd.executeToString(false); } finally { t.cancel(); } } else { result = cmd.executeToString(false); } return getSearchResults(root, result, all); } /** * @param root * @param result * @return */ private static List getSearchResults(HgRoot root, String result, boolean all) { String[] lines = result.split("\n"); List list = new ArrayList(); for (String line : lines) { try { list.add(new MercurialTextSearchMatchAccess(root, line, all)); } catch (HgException e) { // skip parsing errors, add only successful matches } } return list; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgIdentClient.java000066400000000000000000000064151173713500500335230ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; public class HgIdentClient extends AbstractClient { public static final String VERSION_ZERO = "0000000000000000000000000000000000000000"; /** * @param b * byte array containing integer data * @param idx * start index to read integer from * @return integer value, corresponding to the 4 bytes from the given array at given position */ private static int getNextInt(byte[] b, int idx) { int result = 0; for(int i = 0; i < 4 && i + idx < b.length; i++) { result = (result << 8) + (b[i + idx] & 0xff); } return result; } static String getCurrentChangesetId(InputStream inputStream) throws HgException { StringBuilder id = new StringBuilder(20); byte[] first20bytes = new byte[20]; int read; try { read = inputStream.read(first20bytes); } catch (IOException e) { throw new HgException(e.getMessage(), e); } for (int i = 0; i < read; i += 4) { int next = getNextInt(first20bytes, i); String s = Integer.toHexString(next); int size = s.length(); while(size < 8) { id.append('0'); size++; } id.append(s); } return id.toString(); } /** * Returns the current node-id as a String * * @param repository * the root of the repository to identify * @return Returns the node-id for the current changeset * @throws HgException */ public static String getCurrentChangesetId(HgRoot repository) throws HgException { File file = new File(repository, ".hg" + File.separator + "dirstate"); if(!file.exists()){ // new repository with no files return VERSION_ZERO; } FileInputStream reader = null; try { reader = new FileInputStream(file); } catch (FileNotFoundException e) { // sometimes hg is writing the file at same time we trying to read from it // this happens especially if we run many add/remove operations synchronized (HgIdentClient.class) { try { HgIdentClient.class.wait(300); } catch (InterruptedException e1) { MercurialEclipsePlugin.logError(e1); } } try { reader = new FileInputStream(file); } catch (FileNotFoundException e1) { MercurialEclipsePlugin.logError(e1); } if(reader == null) { throw new HgException("Dirstate failed for the path: " + file, e); } } try { return getCurrentChangesetId(reader); } finally { try { reader.close(); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgIgnoreClient.java000066400000000000000000000075221173713500500337030ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgIgnoreClient extends AbstractClient { public static void addExtension(IFile file) throws HgException { HgRoot hgRoot = getHgRoot(file); addPattern(hgRoot, "regexp", escape("." + file.getFileExtension()) + "$"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } public static void addFile(IFile file) throws HgException { HgRoot hgRoot = getHgRoot(file); String regexp = "^" + getRelativePath(hgRoot, file) + "$"; //$NON-NLS-1$ //$NON-NLS-2$ addPattern(hgRoot, "regexp", regexp); //$NON-NLS-1$ } private static String getRelativePath(HgRoot hgRoot, IResource resource) { IPath path = ResourceUtils.getPath(resource); String relative = hgRoot.toRelative(path.toFile()); relative = relative.replace('\\', '/'); return escape(relative); } public static void addFolder(IFolder folder) throws HgException { HgRoot hgRoot = getHgRoot(folder); String regexp = "^" + getRelativePath(hgRoot, folder) + "$"; //$NON-NLS-1$ //$NON-NLS-2$ addPattern(hgRoot, "regexp", regexp); //$NON-NLS-1$ } public static void addRegexp(IProject project, String regexp) throws HgException { HgRoot hgRoot = getHgRoot(project); addPattern(hgRoot, "regexp", regexp); //$NON-NLS-1$ } public static void addGlob(IProject project, String glob) throws HgException { HgRoot hgRoot = getHgRoot(project); addPattern(hgRoot, "glob", glob); //$NON-NLS-1$ } private static String escape(String string) { StringBuilder result = new StringBuilder(); int len = string.length(); for(int i=0; i filter) throws HgException { HgRoot hgRoot = getHgRoot(resource); if (cs == null) { // local resource if (resource instanceof IFile) { return new HgFile(hgRoot, (IFile)resource); } if (resource instanceof IContainer) { return new HgFolder(hgRoot, (IContainer)resource, filter); } return null; } String revision = cs.getChangeset(); HgCommand command = new HgCommand("locate", "Retrieving repository contents", hgRoot, true); if (cs.getDirection() == Direction.INCOMING && cs.getBundleFile() != null) { try { command.setBundleOverlay(cs.getBundleFile()); } catch (IOException e) { throw new HgException("Unable to determine canonical path for " + cs.getBundleFile(), e); } } if (revision != null && revision.length() != 0) { command.addOptions("-r", revision); //$NON-NLS-1$ } IPath relpath = ResourceUtils.getPath(resource).makeRelativeTo(hgRoot.getIPath()); command.addOptions(getHgResourceSearchPattern(resource)); String[] lines = null; try { lines = command.executeToString().split("\n"); //$NON-NLS-1$ } catch (HgException e) { // it is normal that the resource does not exist. } if (resource instanceof IStorage) { if (lines == null || lines.length == 0) { return new NullHgFile(hgRoot, cs, relpath); } for (String line : lines) { return new HgFile(hgRoot, cs, new Path(line)); } } return new HgFolder(hgRoot, cs, relpath, lines, filter); } public static IHgResource getHgResources(IHgResource hgResource, String revision, SortedSet filter) { HgRoot hgRoot = hgResource.getHgRoot(); AbstractShellCommand command = new HgCommand("locate", "Retrieving repository contents", hgRoot, true); if (revision != null && revision.length() != 0) { command.addOptions("-r", revision); //$NON-NLS-1$ } if (hgResource instanceof IHgFile) { command.addOptions("glob:" + hgResource.getHgRootRelativePath()); } else { command.addOptions("glob:" + hgResource.getHgRootRelativePath() + System.getProperty("file.separator") + "**"); } String[] lines = null; try { lines = command.executeToString().split("\n"); //$NON-NLS-1$ } catch (HgException e) { // it is normal that the resource does not exist. MercurialEclipsePlugin.logWarning(e.getMessage(), e); } if (hgResource instanceof IStorage) { if (lines == null || lines.length == 0) { return new NullHgFile(hgRoot, revision, new Path(hgResource.getHgRootRelativePath())); } for (String line : lines) { return new HgFile(hgRoot, revision, new Path(line)); } } return new HgFolder(hgRoot, revision, hgResource.getIPath(), lines, filter); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgLogClient.java000066400000000000000000000365241173713500500332050ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. All rights * reserved. This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 which accompanies this * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: Bastian Doetsch - implementation * Andrei Loskutov - bugfixes * Zsolt Koppany (Intland) * Ilya Ivanov (Intland) ******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.MercurialHistory; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.HgRootContainer; import com.vectrace.MercurialEclipse.model.ChangeSet.Builder; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.utils.StringUtils; public class HgLogClient extends AbstractParseChangesetClient { private static final Map> EMPTY_MAP = Collections.unmodifiableMap(new HashMap>()); // "{rev}:{node} {date|isodate} {author|person}#{tags}**#{branches}**#{desc|firstline}\n" private static final Pattern GET_REVISIONS_PATTERN = Pattern .compile("^([-0-9]+):([a-f0-9]+) ([^ ]+ [^ ]+ [^ ]+) ([^#]*)#(.*)\\*\\*#(.*)\\*\\*#(.*)$"); //$NON-NLS-1$ public static final String NOLIMIT = "999999999999"; public static ChangeSet[] getHeads(HgRoot hgRoot) throws HgException { HgCommand command = new HgCommand("heads", "Listing heads", hgRoot, true); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); return getRevisions(command); } public static ChangeSet getTip(HgRoot hgRoot) throws HgException { HgCommand command = new HgCommand("log", "Finding tip revision", hgRoot, true); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); command.addOptions("-r", HgRevision.TIP.getChangeset()); ChangeSet[] sets = getRevisions(command); if(sets.length != 1){ throw new HgException("Unable to get changeset for 'tip' version"); } return sets[0]; } /** * @param command * a command with optionally its Files set */ private static ChangeSet[] getRevisions(HgCommand command) throws HgException { command.addOptions("--template", //$NON-NLS-1$ "{rev}:{node} {date|isodate} {author|person}#{tags}**#{branches}**#{desc|firstline}\n"); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); String[] lines = null; try { lines = command.executeToString().split("\n"); //$NON-NLS-1$ } catch (HgException e) { if (!e.getMessage() .contains( "abort: can only follow copies/renames for explicit file names")) { //$NON-NLS-1$ throw new HgException(e); } return null; } List changeSets = new ArrayList(); HgRoot hgRoot = command.getHgRoot(); for (String line : lines) { if(StringUtils.isEmpty(line)){ continue; } Matcher m = GET_REVISIONS_PATTERN.matcher(line); if (m.matches()) { Builder builder = new ChangeSet.Builder( Integer.parseInt(m.group(1)), // revisions m.group(2), // changeset m.group(6), // branch m.group(3), // date m.group(4), // user hgRoot).description(m.group(7)); builder.tags(m.group(5)); ChangeSet changeSet = builder.build(); changeSets.add(changeSet); } else { throw new HgException(Messages.getString("HgLogClient.parseException") + line + "'"); //$NON-NLS-1$ //$NON-NLS-2$ } } return changeSets.toArray(new ChangeSet[changeSets.size()]); } /** * @return map where the key is an absolute file path, never null */ public static Map> getCompleteProjectLog( IResource res, boolean withFiles) throws HgException { return getProjectLog(res, -1, Integer.MAX_VALUE, withFiles); } /** * @return map where the key is an absolute file path, never null */ public static Map> getCompleteRootLog( HgRoot hgRoot, boolean withFiles) throws HgException { return getRootLog(hgRoot, -1, Integer.MAX_VALUE, withFiles); } /** * @return map where the key is an absolute file path, never null */ public static Map> getProjectLogBatch( IResource res, int batchSize, int startRev, boolean withFiles) throws HgException { return getProjectLog(res, batchSize, startRev, withFiles); } /** * @return map where the key is an absolute file path, never null */ public static Map> getRecentProjectLog( IResource res, int limitNumber, boolean withFiles) throws HgException { return getProjectLogBatch(res, limitNumber, -1, withFiles); } /** * @return map where the key is an absolute file path, never null */ public static Map> getProjectLog(IResource res, int limitNumber, int startRev, boolean withFiles) throws HgException { HgCommand command = new HgCommand("log", "Retrieving history", //$NON-NLS-1$ res, false); command.setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); command.addStyleFile(withFiles ? AbstractParseChangesetClient.STYLE_WITH_FILES : AbstractParseChangesetClient.STYLE_DEFAULT); boolean isFile = res.getType() == IResource.FILE; addRange(command, startRev, limitNumber, isFile); if (isFile) { command.addOptions("-f"); //$NON-NLS-1$ } if (res.getType() != IResource.PROJECT) { IPath path = ResourceUtils.getPath(res); if(path.isEmpty()) { return EMPTY_MAP; } command.addOptions(path.toOSString()); } else { HgRoot hgRoot = command.getHgRoot(); File fileHandle = ResourceUtils.getFileHandle(res); if(!hgRoot.equals(fileHandle)){ // for multiple projects under same hg root we should return only current project history command.addOptions(fileHandle.getAbsolutePath()); } } String result = command.executeToString(); if (result.length() == 0) { return EMPTY_MAP; } Map> revisions = createLocalRevisions( res, result, Direction.LOCAL, null, null, null); return revisions; } /** * @return map where the key is an absolute file path, never null */ public static Map> getRootLog(HgRoot hgRoot, int limitNumber, int startRev, boolean withFiles) throws HgException { HgCommand command = new HgCommand("log", "Retrieving history", hgRoot, false); command.setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); command.addStyleFile(withFiles ? AbstractParseChangesetClient.STYLE_WITH_FILES : AbstractParseChangesetClient.STYLE_DEFAULT); addRange(command, startRev, limitNumber, false); String result = command.executeToString(); if (result.length() == 0) { return EMPTY_MAP; } Path path = new Path(hgRoot.getAbsolutePath()); Map> revisions = createLocalRevisions(path, result, Direction.LOCAL, null, null, null, hgRoot); return revisions; } /** * @return never null */ public static Map> getPathLog(boolean isFile, File path, HgRoot hgRoot, int limitNumber, int startRev, boolean withFiles) throws HgException { if(hgRoot == null) { return EMPTY_MAP; } HgCommand command = new HgCommand("log", "Retrieving history", hgRoot, false); command.setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); command.addStyleFile(withFiles ? AbstractParseChangesetClient.STYLE_WITH_FILES : AbstractParseChangesetClient.STYLE_DEFAULT); addRange(command, startRev, limitNumber, isFile); if (isFile) { command.addOptions("-f"); //$NON-NLS-1$ } command.addOptions(hgRoot.toRelative(path)); String result = command.executeToString(); if (result.length() == 0) { return EMPTY_MAP; } Map> revisions = createLocalRevisions( new Path(path.getAbsolutePath()), result, Direction.LOCAL, null, null, null, hgRoot); return revisions; } private static void addRange(AbstractShellCommand command, int startRev, int limitNumber, boolean isFile) { if (startRev >= 0 && startRev != Integer.MAX_VALUE) { // always advise to follow until 0 revision: the reason is that log limit // might be bigger then the difference of two consequent revisions on a specific resource command.addOptions("-r"); //$NON-NLS-1$ command.addOptions(startRev + ":" + 0); //$NON-NLS-1$ } if(isFile && startRev == Integer.MAX_VALUE) { // always start with the tip to get the latest version of a file too // seems that hg log misses some versions if the file working copy is not at the tip command.addOptions("-r"); //$NON-NLS-1$ command.addOptions("tip:0"); //$NON-NLS-1$ } setLimit(command, limitNumber); } public static void setLimit(AbstractShellCommand command, int limitNumber) { command.addOptions("--limit", (limitNumber > 0) ? limitNumber + "" : NOLIMIT); //$NON-NLS-1$ //$NON-NLS-2$ } /** * This method modifies given revision: it may change the revision's parent file * * @param rev non null * @param history non null * @param monitor non null * @return may return null */ public static ChangeSet getLogWithBranchInfo(MercurialRevision rev, MercurialHistory history, IProgressMonitor monitor) throws HgException { ChangeSet changeSet = rev.getChangeSet(); IResource resource = rev.getResource(); int limitNumber = 1; Map> map; if(resource instanceof HgRootContainer) { map = getRootLog(((HgRootContainer) resource).getHgRoot(), limitNumber, changeSet .getChangesetIndex(), true); } else { map = getProjectLog(resource, limitNumber, changeSet.getChangesetIndex(), true); } IPath location = ResourceUtils.getPath(resource); if(location.isEmpty()) { return null; } if(!map.isEmpty()) { return Collections.min(map.get(location)); } File possibleParent = rev.getParent(); MercurialRevision next = rev; if(possibleParent == null && !monitor.isCanceled()){ HgRoot hgRoot = changeSet.getHgRoot(); File file = location.toFile(); // try first to guess the parent (and avoid the while loop below), see issue #10302 possibleParent = HgStatusClient.guessPossibleSourcePath(hgRoot, file, rev.getRevision()); if(possibleParent != null && !possibleParent.equals(location.toFile())){ // got different parent, may be it's the right one? // validate if the possible parent IS the parent for this version map = getPathLog(resource.getType() == IResource.FILE, possibleParent, hgRoot, limitNumber, rev.getRevision(), true); } // go up one revision step by step, looking for the fist time "branch" occurence // this may take a long time... while(map.isEmpty() && (next = history.getNext(next)) != null && !monitor.isCanceled()){ if(next.getParent() == null) { int revision = next.getRevision(); possibleParent = HgStatusClient.getPossibleSourcePath(hgRoot, file, revision); } else { possibleParent = next.getParent(); } if(possibleParent != null){ // validate if the possible parent IS the parent for this version map = getPathLog(resource.getType() == IResource.FILE, possibleParent, hgRoot, limitNumber, rev.getRevision(), true); if(!map.isEmpty()) { // bingo, log is not null break; } // see issue 10302: file seems to be copied/renamed multiple times // restart the search from the beginning with the newly obtained path // if it is different to the original one if(possibleParent.equals(location.toFile())){ // give up possibleParent = null; break; } // restart next = rev; file = possibleParent; } } if(monitor.isCanceled()){ return null; } // remember parent for all visited versions if(possibleParent != null) { while(next != rev && (next = history.getPrev(next)) != rev){ if(next == null) { break; } next.setParent(possibleParent); } } } if(possibleParent != null){ rev.setParent(possibleParent); if(map.isEmpty() && !monitor.isCanceled()) { map = getPathLog(resource.getType() == IResource.FILE, possibleParent, MercurialTeamProvider.getHgRoot(resource), limitNumber, rev.getRevision(), true); } if(!map.isEmpty()) { return Collections.min(map.get(new Path(possibleParent.getAbsolutePath()))); } } return null; } public static ChangeSet getChangeset(IResource res, String nodeId, boolean withFiles) throws HgException { Assert.isNotNull(nodeId); HgRoot root = MercurialRootCache.getInstance().getHgRoot(res); HgCommand command = new HgCommand("log", "Retrieving history", //$NON-NLS-1$ root, false); command.setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); command.addStyleFile(withFiles ? AbstractParseChangesetClient.STYLE_WITH_FILES : AbstractParseChangesetClient.STYLE_DEFAULT); command.addOptions("--rev", nodeId); //$NON-NLS-1$ String result = command.executeToString(); Map> revisions = createLocalRevisions( res, result, Direction.LOCAL, null, null, null); IPath location = ResourceUtils.getPath(res); if(location.isEmpty()) { return null; } Set set = revisions.get(location); if (set != null) { return Collections.min(set); } return null; } /** * Tries to retrieve (possible not existing) changeset for the given id. * @param hgRoot non null * @param nodeId non null * @return might return null if the changeset is not known/existing in the repo */ public static ChangeSet getChangeset(HgRoot hgRoot, String nodeId) throws HgException { return getChangeset(hgRoot, nodeId, false); } public static ChangeSet getChangeset(HgRoot hgRoot, String nodeId, boolean withFiles) throws HgException { Assert.isNotNull(nodeId); HgCommand command = new HgCommand("log", "Retrieving history", hgRoot, false); command.setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); command.addStyleFile(withFiles ? AbstractParseChangesetClient.STYLE_WITH_FILES : AbstractParseChangesetClient.STYLE_DEFAULT); command.addOptions("--rev", nodeId); //$NON-NLS-1$ String result = command.executeToString(); Path path = new Path(hgRoot.getAbsolutePath()); Map> revisions = createLocalRevisions(path, result, Direction.LOCAL, null, null, null, hgRoot); Set set = revisions.get(path); if (set != null && !set.isEmpty()) { return Collections.min(set); } return null; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgMergeClient.java000066400000000000000000000031211173713500500335060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; public class HgMergeClient extends AbstractClient { public static String merge(HgRoot hgRoot, String revision, boolean forced) throws HgException { HgCommand command = new HgCommand("merge", "Merging", hgRoot, false); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.IMERGE_TIMEOUT); addMergeToolPreference(command); if (revision != null) { command.addOptions("-r", revision); //$NON-NLS-1$ } if (forced) { command.addOptions("-f"); //$NON-NLS-1$ } return command.executeToString(); } public static boolean isConflict(HgException e) { // if conflicts aren't resolved and no merge tool is started, hg // exits with 1 return e.getStatus().getCode() == 1; } } HgOutgoingClient.java000066400000000000000000000056121173713500500341720ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bugfixes * Philip Graf - proxy support *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RemoteData; import com.vectrace.MercurialEclipse.team.cache.RemoteKey; public class HgOutgoingClient extends AbstractParseChangesetClient { /** * @return never return null */ public static RemoteData getOutgoing(RemoteKey key) throws HgException { HgCommand command = getCommand(key); boolean computeFullStatus = MercurialEclipsePlugin.getDefault().getPreferenceStore().getBoolean(MercurialPreferenceConstants.SYNC_COMPUTE_FULL_REMOTE_FILE_STATUS); addInsecurePreference(command); command.addStyleFile(computeFullStatus ? AbstractParseChangesetClient.STYLE_WITH_FILES : AbstractParseChangesetClient.STYLE_WITH_FILES_FAST); if (key.isAllowUnrelated()) { command.addOptions("-f"); } addRepoToHgCommand(key.getRepo(), command); String result = getResult(command); if (result == null) { return new RemoteData(key, Direction.OUTGOING); } RemoteData revisions = createRemoteRevisions(key, result, Direction.OUTGOING, null); return revisions; } private static String getResult(AbstractShellCommand command) throws HgException { try { String result = command.executeToString(); if (result.endsWith("no changes found")) { //$NON-NLS-1$ return null; } return result; } catch (HgException hg) { if (hg.getStatus().getCode() == 1) { return null; } throw hg; } } private static HgCommand getCommand(RemoteKey key) { HgRoot hgRoot = key.getRoot(); HgCommand command = new HgCommand("outgoing", "Calculating outgoing changesets", hgRoot, false); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT); // see issue 10495, 11093: there can be many branch heads: "--rev branch" cannot be used if (key.getBranch() != null) { command.addOptions("--branch", key.getBranch()); } return command; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgParentClient.java000066400000000000000000000141621173713500500337070ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; public class HgParentClient extends AbstractClient { private static final Pattern ANCESTOR_PATTERN = Pattern .compile("^(-?[0-9]+):([0-9a-f]+)$"); //$NON-NLS-1$ private static final Pattern LINE_SEPERATOR_PATTERN = Pattern.compile("\n"); public static int[] getParents(HgRoot hgRoot) throws HgException { AbstractShellCommand command = new HgCommand("parents", //$NON-NLS-1$ "Finding parent revisions", hgRoot, false); command.addOptions("--template", "{rev}\n"); //$NON-NLS-1$ //$NON-NLS-2$ String[] lines = getLines(command.executeToString()); int[] parents = new int[lines.length]; for (int i = 0; i < lines.length; i++) { parents[i] = Integer.parseInt(lines[i]); } return parents; } public static String[] getParentNodeIds(HgRoot hgRoot) throws HgException { AbstractShellCommand command = new HgCommand("parents", "Finding parent revisions", hgRoot, false); command.addOptions("--template", "{node}\n"); //$NON-NLS-1$ //$NON-NLS-2$ return parseParentsCommand(command); } public static String[] getParentNodeIds(IResource file) throws HgException { AbstractShellCommand command = new HgCommand("parents", //$NON-NLS-1$ "Finding parent revisions", file, false); if(file instanceof IFile) { command.addFiles(file); } command.addOptions("--template", "{node}\n"); //$NON-NLS-1$ //$NON-NLS-2$ return parseParentsCommand(command); } public static String[] getParentNodeIds(ChangeSet cs, String template) throws HgException { AbstractShellCommand command = new HgCommand("parents", //$NON-NLS-1$ "Finding parent revisions", cs.getHgRoot(), false); command.addOptions("--template", template + "\n", "--rev", cs //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ .getChangeset()); return parseParentsCommand(command); } public static String[] getParentNodeIds(IResource resource, ChangeSet cs) throws HgException { AbstractShellCommand command = new HgCommand("parents", //$NON-NLS-1$ "Finding parent revisions", resource, false); command.addOptions("--template", "{node}\n", "--rev", cs //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ .getChangeset()); return parseParentsCommand(command); } private static String[] parseParentsCommand(AbstractShellCommand parentsCommand) throws HgException { String[] lines = getLines(parentsCommand.executeToString()); String[] parents = new String[lines.length]; for (int i = 0; i < lines.length; i++) { parents[i] = lines[i].trim(); } return parents; } /** * @param hgRoot The root that these nodes are in * @param node1 The first changeset id * @param node2 The second changeset id * @return An array of length 2 with the revision index at index 0 and the global node id at * index 1. The revision index is -1 for unrelated. * @throws HgException */ public static String[] findCommonAncestor(HgRoot hgRoot, String node1, String node2) throws HgException { AbstractShellCommand command = new HgCommand("debugancestor", //$NON-NLS-1$ "Finding common ancestor", hgRoot, false); command.addOptions(node1, node2); String result = command.executeToString().trim(); Matcher m = ANCESTOR_PATTERN.matcher(result); if (m.matches()) { String local = m.group(1); String global = m.group(2); String[] revision = {local, global}; return revision; } throw new HgException("Parse exception: '" + result + "'"); } /** * This methods finds the common ancestor of two changesets, supporting * overlays for using incoming changesets. Only one changeset may be * incoming. * * @param hgRoot * hg root * @param cs1 * first changeset * @param cs2 * second changeset * @return An array of length 2 with the revision index at index 0 and the global node id at * index 1. The revision index is -1 for unrelated. * @throws HgException */ public static String[] findCommonAncestor(HgRoot hgRoot, ChangeSet cs1, ChangeSet cs2) throws HgException { String result; try { HgCommand command = new HgCommand("debugancestor", "Finding common ancestor", hgRoot, false); if (cs1.getBundleFile() != null || cs2.getBundleFile() != null) { if (cs1.getBundleFile() != null) { command.setBundleOverlay(cs1.getBundleFile()); } else { command.setBundleOverlay(cs2.getBundleFile()); } } command.addOptions(cs1.getChangeset(), cs2.getChangeset()); result = command.executeToString().trim(); Matcher m = ANCESTOR_PATTERN.matcher(result); if (m.matches()) { String local = m.group(1); String global = m.group(2); String[] revision = {local, global}; return revision; } throw new HgException("Parse exception: '" + result + "'"); } catch (NumberFormatException e) { throw new HgException(e.getLocalizedMessage(), e); } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } } /** * Splits an output of a command into lines. Lines are separated by a newline character (\n). * * @param output * The output of a command. * @return The lines of the output. */ private static String[] getLines(String output) { if (output == null || output.length() == 0) { return new String[0]; } return LINE_SEPERATOR_PATTERN.split(output); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgPatchClient.java000066400000000000000000000136631173713500500335220ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Steeven Lee - import/export stuff * Bastian Doetsch - additions *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; public class HgPatchClient extends AbstractClient { public static final String PATCH_EXTENSION = ".diff"; /** * Import a patch. Throws an exception if there is a conflict * * @see #isPatchImportConflict(HgException) * * @param hgRoot non null * @param patchLocation non null * @param options non null */ public static String importPatch(HgRoot hgRoot, File patchLocation, ArrayList options) throws HgException { AbstractShellCommand command = new HgCommand("import", "Importing patch", hgRoot, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.addFile(patchLocation); command.addOptions(options.toArray(new String[options.size()])); return command.executeToString(); } /** * Determine if the given exception indicates a conflict occurred * * @param e * The exception to check * @return True if the exception indicates a conflict occurred */ public static boolean isPatchImportConflict(HgException e) { return e.getMessage().contains("patch failed to apply."); } /** * @param hgRoot non null hg root * @param resources non null set of files to export as diff to the latest state. If the set * is empty, a complete diff of the hg root is exported * @param patchFile non null target file for the diff * @param options non null list of options, may be empty * @throws HgException * @return True on success */ public static boolean exportPatch(HgRoot hgRoot, List resources, File patchFile, List options) throws HgException { AbstractShellCommand command = makeExportUncommittedCommand(hgRoot, options); command.addFiles(resources); return command.executeToFile(patchFile, false); } /** * export diff file to clipboard * * @param resources * @throws HgException */ public static String exportPatch(HgRoot root, List resources, List options) throws HgException { AbstractShellCommand command = makeExportUncommittedCommand(root, options); command.addFiles(resources); return command.executeToString(); } private static AbstractShellCommand makeExportUncommittedCommand(HgRoot root, List options) { AbstractShellCommand command = new HgCommand( "diff", "Exporting patch of uncommitted changes", root, true); //$NON-NLS-1$ command.addOptions(options.toArray(new String[options.size()])); return command; } /** * Export a changeset to a string * * @param root * The repository root * @param cs * The changeset * @param options * Options. May be null * @return The string as a patch * @throws HgException */ public static String exportPatch(HgRoot root, ChangeSet cs, List options) throws HgException { return makeExportPatchCommand(root, cs, options).executeToString(); } /** * Export a changeset to a file * * @param root * The repository root * @param cs * The changeset * @param patchFile * The file to output to * @param options * Options. May be null * @return True on success * @throws HgException */ public static boolean exportPatch(HgRoot root, ChangeSet cs, File patchFile, List options) throws HgException { return makeExportPatchCommand(root, cs, options).executeToFile(patchFile, false); } private static AbstractShellCommand makeExportPatchCommand(HgRoot root, ChangeSet cs, List options) { AbstractShellCommand command = new HgCommand("export", "Exporting changeset " + cs.getChangeset(), root, true); if (options != null) { command.addOptions(options.toArray(new String[options.size()])); } command.addOptions("--git"); command.addOptions("-r", cs.getChangeset()); return command; } /** * Get a diff for a single changeSet or a range for revisions. * * Use the extended diff format (--git) that shows renames and file attributes. * * @param hgRoot The root. Must not be null. * @param entry Revision of the changeset or first revision of changeset-range (if secondEntry != null). Must not be null. * @param secondEntry second revision of changeset range. If null entry a diff will be created for parameter entry a a single Changeset. * @return Diff as a string in extended diff format (--git). * @throws HgException */ public static String getDiff(HgRoot hgRoot, MercurialRevision entry, MercurialRevision secondEntry) throws HgException { HgCommand diffCommand = new HgCommand("diff", //$NON-NLS-1$ "Calculating diff between revisions", hgRoot, true); if( secondEntry == null ){ diffCommand.addOptions("-c", "" + entry.getChangeSet().getRevision().getChangeset()); } else { diffCommand.addOptions("-r", ""+entry.getChangeSet().getRevision().getChangeset()); diffCommand.addOptions("-r", ""+secondEntry.getChangeSet().getRevision().getChangeset()); } diffCommand.addOptions("--git"); return diffCommand.executeToString(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgPathsClient.java000066400000000000000000000027251173713500500335370ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Zsolt Koppany (Intland) - bug fixes * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.FileNotFoundException; import java.util.Map; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.HgRoot; public class HgPathsClient extends AbstractClient { public static final String DEFAULT = Branch.DEFAULT; public static final String DEFAULT_PULL = "default-pull"; //$NON-NLS-1$ public static final String DEFAULT_PUSH = "default-push"; //$NON-NLS-1$ /** * @param hgRoot non null * @return map with "logical name" : "url" pairs. May be empty. * @throws HgException */ public static Map getPaths(HgRoot hgRoot) throws HgException { try { return hgRoot.getPaths(); } catch (FileNotFoundException e) { throw new HgException("Unable to read paths for repository: " + hgRoot, e); } } } HgPushPullClient.java000066400000000000000000000151631173713500500341550ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch - added authentication to push * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.regex.Pattern; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.UpdateJob; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; public class HgPushPullClient extends AbstractClient { /** * matches ("number" "heads") message */ private static final Pattern HEADS_PATTERN = Pattern.compile("\\(\\+\\d+\\sheads\\)"); public static String push(HgRoot hgRoot, IHgRepositoryLocation repo, boolean force, ChangeSet changeset, int timeout) throws HgException { return push(hgRoot, repo, force, changeset, timeout, null); } public static String push(HgRoot hgRoot, IHgRepositoryLocation repo, boolean force, ChangeSet changeset, int timeout, String branch) throws HgException { AbstractShellCommand command = new HgCommand("push", //$NON-NLS-1$ makeDescription("Pushing", changeset, branch), hgRoot, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.PUSH_TIMEOUT); addInsecurePreference(command); if (force) { command.addOptions("--force"); //$NON-NLS-1$ } applyChangeset(command, changeset); boolean newBranch = MercurialEclipsePlugin.getDefault().getPreferenceStore() .getBoolean(MercurialPreferenceConstants.PREF_PUSH_NEW_BRANCH); if (newBranch) { command.addOptions("--new-branch"); } if (branch != null) { command.addOptions("--branch", branch); } addRepoToHgCommand(repo, command); return new String(command.executeToBytes(timeout)); } public static String pull(HgRoot hgRoot, ChangeSet changeset, IHgRepositoryLocation repo, boolean update, boolean rebase, boolean force, boolean timeout, boolean merge) throws HgException { return pull(hgRoot, changeset, repo, update, rebase, force, timeout, merge, null); } public static String pull(HgRoot hgRoot, ChangeSet changeset, IHgRepositoryLocation repo, boolean update, boolean rebase, boolean force, boolean timeout, boolean merge, String branch) throws HgException { boolean separateUpdate = false; HgCommand command = new HgCommand("pull", //$NON-NLS-1$ makeDescription("Pulling", changeset, branch), hgRoot, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); addInsecurePreference(command); // --update and --branch together will switch to latest of the branch rather than usual // branch crossing logic. See http://www.javaforge.com/issue/19520 // TODO: pull from bundle so --branch isn't necessary if (update && branch != null && changeset == null) { update = false; separateUpdate = true; } if (update) { command.addOptions("--update"); //$NON-NLS-1$ addMergeToolPreference(command); } else if (rebase) { command.addOptions("--config", "extensions.hgext.rebase="); //$NON-NLS-1$ //$NON-NLS-2$ command.addOptions("--rebase"); //$NON-NLS-1$ addMergeToolPreference(command); } if (force) { command.addOptions("--force"); //$NON-NLS-1$ } applyChangeset(command, changeset); if (branch != null) { command.addOptions("--branch", branch); } addRepoToHgCommand(repo, command); String result = null; try { if (timeout) { command.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT); result = new String(command.executeToBytes()); } else { result = new String(command.executeToBytes(Integer.MAX_VALUE)); } if (separateUpdate) { try { result += HgUpdateClient.updateWithoutRefresh(hgRoot, null, false); } catch (HgException e) { if (HgUpdateClient.isCrossesBranchError(e) || HgUpdateClient.isWorkspaceUpdateConflict(e)) { result += e.getMessage(); } else { // ?? throw e; } } } } finally { // TODO: detect workspace conflicts on update and notify user if ((update || separateUpdate) && result != null && !merge && !rebase) { // different messages from hg depending on if branch was set or not // TODO: clean up this detection if (result.contains("not updating, since new heads added") || result.contains("not updating: crosses branches") || (branch != null && HEADS_PATTERN.matcher(result).find())) { // inform user about new heads and ask if he wants to merge or rebase UpdateJob.handleMultipleHeads(hgRoot, false); } } // doesn't matter how far we were: we have to trigger update of caches in case // the pull was *partly* successful (e.g. pull was ok, but update not) refreshProjects((update || separateUpdate), hgRoot); } return result; } private static String makeDescription(String op, ChangeSet changeset, String branch) { if (changeset == null) { return op + " all changes" + ((branch == null) ? "" : " in " + branch); } return op + " changeset " + changeset.getChangeset(); } protected static void applyChangeset(AbstractShellCommand command, ChangeSet changeset) { if (changeset != null) { String cs = changeset.getChangeset(); if (cs != null && (cs = cs.trim()).length() > 0) { command.addOptions("-r", cs); //$NON-NLS-1$ } } } private static void refreshProjects(boolean update, final HgRoot hgRoot) { // The reason to use "all" instead of only "local + incoming", is that we can pull // from another repo as the sync clients for given project may use // in this case, we also need to update "outgoing" changesets final int flags = RefreshRootJob.ALL; if(update) { new RefreshWorkspaceStatusJob(hgRoot, flags).schedule(); } else { new RefreshRootJob(hgRoot, flags).schedule(); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgRemoveClient.java000066400000000000000000000116121173713500500337100ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch - removeResources() * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.HgFeatures; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgRemoveClient extends AbstractClient { public static void removeResource(IResource resource, IProgressMonitor monitor) throws HgException { if (monitor != null) { monitor.subTask(Messages.getString("HgRemoveClient.removeResource.1") + resource.getName() //$NON-NLS-1$ + Messages.getString("HgRemoveClient.removeResource.2")); //$NON-NLS-1$ } HgRoot root = MercurialRootCache.getInstance().getHgRoot(resource); HgCommand command = new HgCommand("remove", "Removing resource", root, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(command.getHgRoot())); command.addOptions("--force"); //$NON-NLS-1$ command.addFiles(resource); command.setUsePreferenceTimeout(MercurialPreferenceConstants.REMOVE_TIMEOUT); command.executeToBytes(); MercurialStatusCache.getInstance().refreshStatus(resource, monitor); } public static void removeResources(List resources) throws HgException { Map> resourcesByRoot = ResourceUtils.groupByRoot(resources); for (Map.Entry> mapEntry : resourcesByRoot.entrySet()) { HgRoot hgRoot = mapEntry.getKey(); // if there are too many resources, do several calls // From 1.8 hg can do it in one call if (!HgFeatures.LISTFILE.isEnabled()) { int size = mapEntry.getValue().size(); @SuppressWarnings("deprecation") int delta = AbstractShellCommand.MAX_PARAMS - 1; for (int i = 0; i < size; i += delta) { AbstractShellCommand command = new HgCommand( "remove", "Removing resource", hgRoot, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.REMOVE_TIMEOUT); command.addFiles(mapEntry.getValue().subList(i, Math.min(i + delta, size))); command.executeToBytes(); } } else { AbstractShellCommand command = new HgCommand("remove", "Removing resource", hgRoot, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.REMOVE_TIMEOUT); command.addFiles(mapEntry.getValue()); command.executeToBytes(); } } } public static void removeResourcesLater(Map> resourcesByRoot) throws HgException { for (Map.Entry> mapEntry : resourcesByRoot.entrySet()) { HgRoot hgRoot = mapEntry.getKey(); // if there are too many resources, do several calls // From 1.8 hg can do it in one call int size = mapEntry.getValue().size(); if (!HgFeatures.LISTFILE.isEnabled()) { @SuppressWarnings("deprecation") int delta = AbstractShellCommand.MAX_PARAMS - 1; for (int i = 0; i < size; i += delta) { final int j = Math.min(i + delta, size); AbstractShellCommand command = new HgCommand("remove", //$NON-NLS-1$ "Removing " + (j - i) + " resources", hgRoot, true); command.addOptions("-Af"); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.REMOVE_TIMEOUT); command.addFiles(mapEntry.getValue().subList(i, j)); command.executeToBytes(); } } else { AbstractShellCommand command = new HgCommand("remove", //$NON-NLS-1$ "Removing " + size + " resources", hgRoot, true); command.addOptions("-Af"); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.REMOVE_TIMEOUT); command.addFiles(mapEntry.getValue()); command.executeToBytes(); } } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgRenameClient.java000066400000000000000000000041741173713500500336670ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgRenameClient extends AbstractClient { public static void renameResource(IPath source, IPath dest, HgRoot hgRoot, IProgressMonitor monitor) throws HgException { if(!hgRoot.getIPath().isPrefixOf(source)) { throw new HgException("Cannot move: source ('" + source + "') is not inside the repository: '" + hgRoot + "'"); } if(!hgRoot.getIPath().isPrefixOf(dest)) { throw new HgException("Cannot move: destination ('" + dest + "') is not inside the repository: '" + hgRoot + "'"); } if (monitor != null) { monitor.subTask(Messages.getString("HgRenameClient.moving.1") + source.lastSegment() + Messages.getString("HgRenameClient.moving.2") //$NON-NLS-1$ + dest.lastSegment()); } HgCommand command = new HgCommand("rename", "Renaming resource", hgRoot, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.addOptions("--force"); //$NON-NLS-1$ command.addFile(source.toFile()); command.addFile(dest.toFile()); command.executeToBytes(); // see issue 14135: not versioned (new or derived) files may left after move // => move them manually (also allows "undo" in Eclipse to work properly) ResourceUtils.move(source.toFile(), dest.toFile()); } } HgResolveClient.java000066400000000000000000000166631173713500500340260ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.FlaggedAdaptable; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgResolveClient extends AbstractClient { /** * List merge state of files after merge */ public static List list(IResource res) throws HgException { AbstractShellCommand command = new HgCommand("resolve", //$NON-NLS-1$ "Calculating conflict status for resource", res, false); command .setUsePreferenceTimeout(MercurialPreferenceConstants.IMERGE_TIMEOUT); command.addOptions("-l"); //$NON-NLS-1$ String[] lines = command.executeToString().split("\n"); //$NON-NLS-1$ List result = new ArrayList(); if (lines.length != 1 || !"".equals(lines[0])) { //$NON-NLS-1$ HgRoot hgRoot = getHgRoot(res); IProject project = res.getProject(); for (String line : lines) { // Status line is always hg root relative. For those projects // which has different project root hg root relative path must // be converted to project relative IResource iFile = ResourceUtils.convertRepoRelPath(hgRoot, project, line.substring(2)); if(iFile != null){ FlaggedAdaptable fa = new FlaggedAdaptable(iFile, line.charAt(0)); result.add(fa); } } } return result; } /** * List merge state of files after merge */ public static List list(HgRoot hgRoot) throws HgException { AbstractShellCommand command = new HgCommand("resolve", "Listing conflict status", hgRoot, false); command.setUsePreferenceTimeout(MercurialPreferenceConstants.IMERGE_TIMEOUT); command.addOptions("-l"); //$NON-NLS-1$ String[] lines = command.executeToString().split("\n"); //$NON-NLS-1$ List result = new ArrayList(); if (lines.length != 1 || !"".equals(lines[0])) { //$NON-NLS-1$ for (String line : lines) { // Status line is always hg root relative. For those projects // which has different project root (always deeper than hg root) // hg root relative path must be converted String repoRelPath = line.substring(2); IResource iFile = ResourceUtils.getFileHandle(hgRoot.toAbsolute(new Path(repoRelPath))); if(iFile != null){ FlaggedAdaptable fa = new FlaggedAdaptable(iFile, line.charAt(0)); result.add(fa); } } } return result; } /** * Mark a resource as resolved ("R") */ public static String markResolved(IFile ifile) throws HgException { File file = ResourceUtils.getFileHandle(ifile); HgCommand command = new HgCommand("resolve", //$NON-NLS-1$ "Marking resource as resolved", ifile, false); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(command .getHgRoot())); command.setUsePreferenceTimeout(MercurialPreferenceConstants.IMERGE_TIMEOUT); try { command.addOptions("-m", file.getCanonicalPath()); //$NON-NLS-1$ String result = command.executeToString(); // cleanup .orig files left after merge File origFile = new File(file.getAbsolutePath() + ".orig"); if(origFile.isFile()){ IResource fileToDelete = ResourceUtils.convert(origFile); boolean deleted = origFile.delete(); if(!deleted){ MercurialEclipsePlugin.logInfo("Failed to cleanup " + origFile + " file after merge", null); } else { try { fileToDelete.refreshLocal(IResource.DEPTH_ZERO, null); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } refreshStatus(ifile); return result; } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } } /** * Mark a resource as unresolved ("U") */ public static String markUnresolved(IFile ifile) throws HgException { IPath path = ResourceUtils.getPath(ifile); if(path.isEmpty()) { throw new HgException("Failed to unresolve: location is unknown: " + ifile); } File file = path.toFile(); HgCommand command = new HgCommand("resolve", //$NON-NLS-1$ "Marking resource as unresolved", ifile, false); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(command .getHgRoot())); command.setUsePreferenceTimeout(MercurialPreferenceConstants.IMERGE_TIMEOUT); try { command.addOptions("-u", file.getCanonicalPath()); //$NON-NLS-1$ String result = command.executeToString(); refreshStatus(ifile); return result; } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } } private static void refreshStatus(IResource res) throws HgException { MercurialStatusCache.getInstance().refreshStatus(res, null); ResourceUtils.touch(res); } /** * Executes resolve command to find change sets necessary for merging *

* WARNING: This method potentially reverts changes! *

* Future: We should write some python to interface with the Mercurial API directly to get this * info so we don't have to do operations with side effects or rely on --debug output. * * @param file * The file to consider * @return An array of length 3 of changeset ids: result[0] - 'my' result[1] - 'other' result[2] * - 'base' * @throws HgException */ public static String[] restartMergeAndGetChangeSetsForCompare(IFile file) throws HgException { String[] results = new String[3]; HgCommand command = new HgCommand("resolve", "Invoking resolve to find parent information", file, false); command.addOptions("--config", "ui.merge=internal:mustfail", "--debug"); command.addFiles(file); String stringResult = ""; try { command.executeToString(); } catch (HgException e) { // exception is expected here stringResult = e.getMessage(); } String filename = file.getName(); String patternString = "my .*" + filename + "@?([0-9a-fA-F]*)\\+?[\\s]" + "other .*" + filename + "@?([0-9a-fA-F]*)\\+?[\\s]" + "ancestor .*" + filename + "@?([0-9a-fA-F]*)\\+?[\\s]"; Matcher matcher = Pattern.compile(patternString).matcher(stringResult); if (matcher.find() && matcher.groupCount() == 3) { results[0] = matcher.group(1); // my results[1] = matcher.group(2); // other results[2] = matcher.group(3); // ancestor } return results; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgRevertClient.java000066400000000000000000000113131173713500500337200ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 Andrei Loskutov and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.HgFeatures; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.Messages; /** * @author Andrei */ public class HgRevertClient extends AbstractClient { /** * @param monitor non null * @param hgRoot the root of all given resources * @param resources resources to revert * @param cs might be null * @return a copy of file paths affected by this command, if any. Never returns null, * but may return empty list. The elements of the set are absolute file paths. * @throws HgException */ public static Set performRevert(IProgressMonitor monitor, HgRoot hgRoot, List resources, ChangeSet cs) throws HgException { Set fileSet = new HashSet(); monitor.subTask(Messages.getString("ActionRevert.reverting") + " " + hgRoot.getName() + "..."); //$NON-NLS-1$ //$NON-NLS-2$ // if there are too many resources, do several calls int size = resources.size(); MercurialUtilities.setOfferAutoCommitMerge(true); if(size == 0) { return fileSet; } IResource firstFile = resources.get(0); if(size == 1 && cs != null && (cs.isMoved(firstFile) || cs.isRemoved(firstFile))) { HgRevision parentRevision = cs.getParentRevision(0, true); HgCommand command = createRevertCommand(hgRoot, "Reverting " + firstFile.getName()); command.addOptions("--rev", parentRevision.getChangeset()); command.addFiles(firstFile); if(cs.isMoved(firstFile)) { FileStatus status = cs.getStatus(firstFile); if(status != null) { IPath path = status.getAbsoluteCopySourcePath(); command.addFile(path.toFile()); } } command.executeToString(); fileSet.addAll(command.getAffectedFiles()); } else { // if there are too many resources, do several calls // From 1.8 hg can do it in one call if(!HgFeatures.LISTFILE.isEnabled()) { @SuppressWarnings("deprecation") int delta = AbstractShellCommand.MAX_PARAMS - 1; for (int i = 0; i < size && !monitor.isCanceled(); i += delta) { // the last argument will be replaced with a path HgCommand command = createRevertCommand(hgRoot, "Reverting resource " + i + " of " + size); if (cs != null) { command.addOptions("--rev", cs.getChangeset()); } command.addFiles(resources.subList(i, Math.min(i + delta, size))); command.executeToString(); fileSet.addAll(command.getAffectedFiles()); } } else { // the last argument will be replaced with a path HgCommand command = createRevertCommand(hgRoot, "Reverting " + size + " resources"); if (cs != null) { command.addOptions("--rev", cs.getChangeset()); } command.addFiles(resources); command.executeToString(); fileSet.addAll(command.getAffectedFiles()); } } monitor.worked(1); return fileSet; } public static void performRevertAll(IProgressMonitor monitor, HgRoot hgRoot) throws HgException { monitor.subTask(Messages.getString("ActionRevert.reverting") + " " + hgRoot.getName() + "..."); //$NON-NLS-1$ //$NON-NLS-2$ HgCommand command = createRevertCommand(hgRoot, "Reverting all resources"); command.addOptions("--all"); command.executeToString(); MercurialUtilities.setOfferAutoCommitMerge(true); } private static HgCommand createRevertCommand(HgRoot hgRoot, String message) { HgCommand command = new HgCommand("revert", message, hgRoot, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.COMMIT_TIMEOUT); command.addOptions("--no-backup"); return command; } } HgRollbackClient.java000066400000000000000000000024371173713500500341320ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import org.eclipse.core.runtime.CoreException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; public class HgRollbackClient extends AbstractClient { public static String rollback(final HgRoot hgRoot) throws CoreException { HgCommand command = new HgCommand("rollback", "Rolling back last transaction", hgRoot, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); String result = command.executeToString(); new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.ALL).schedule(); return result; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgRootClient.java000066400000000000000000000052451173713500500334030ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.FileFilter; import java.io.IOException; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * Calls hg root * * @author bastian * */ public class HgRootClient extends AbstractClient { /** * @param file * @return hg root as canonical path (see {@link File#getCanonicalPath()}) * @throws HgException */ public static HgRoot getHgRoot(File file) throws HgException { // get the canonical path of the first existing directory File dir = ResourceUtils.getFirstExistingDirectory(file); HgRoot hgRoot; try { hgRoot = new HgRoot(dir); } catch(IOException e) { throw new HgException(Messages.getString("HgRootClient.error.cannotGetCanonicalPath")+file.getName()); //$NON-NLS-1$ } // search up the parents recursive if we see .hg directory there File root = findHgDir(hgRoot); if (root == null) { throw new HgException(file.getName() + Messages.getString("HgRootClient.error.noRoot")); //$NON-NLS-1$ } // .hg parent dir found try { hgRoot = new HgRoot(root); } catch (IOException e) { throw new HgException(Messages.getString("HgRootClient.error.cannotGetCanonicalPath")+file.getName()); //$NON-NLS-1$ } return hgRoot; } /** * Searches the .hg directory up in all parents of the given file * @param startDir a directory * @return directory named ".hg" (in any case), or null if the given file does not * have parents wich contains .hg directory */ private static File findHgDir(File startDir) { FileFilter hg = new FileFilter() { public boolean accept(File path) { return path.getName().equalsIgnoreCase(".hg") && path.isDirectory(); //$NON-NLS-1$ } }; File root = startDir; File[] rootContent = root.listFiles(hg); while (rootContent != null && rootContent.length == 0) { root = root.getParentFile(); if (root == null) { return null; } rootContent = root.listFiles(hg); } if(rootContent != null) { return root; } return null; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgServeClient.java000066400000000000000000000117211173713500500335400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.OutputStream; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian * */ public class HgServeClient extends AbstractClient { /** * Rule which forbids running server on same port */ private static final class ServeRule implements ISchedulingRule { final int port; private ServeRule(int port) { super(); this.port = port; } public boolean isConflicting(ISchedulingRule rule) { return contains(rule); } public boolean contains(ISchedulingRule rule) { if(this == rule){ return true; } if(!(rule instanceof ServeRule)){ return false; } return this.port == ((ServeRule) rule).port; } } static class HgServeJob extends Job { private final HgRoot hgRoot; private final boolean ipv6; private final String name; private final String prefix; private final int port; private final String webdirConf; private final boolean stdio; private final IProgressMonitor progress; public HgServeJob(HgRoot hgRoot, int port, String prefix, String name, String webdirConf, boolean ipv6, boolean stdio) { super(Messages.getString("HgServeClient.serveJob.name") //$NON-NLS-1$ + hgRoot.getName() + "..."); //$NON-NLS-1$ this.hgRoot = hgRoot; this.port = port; this.prefix = prefix; this.name = name; this.webdirConf = webdirConf; this.ipv6 = ipv6; this.stdio = stdio; progress = getJobManager().createProgressGroup(); progress.beginTask("Local Mercurial Server on port " + port, IProgressMonitor.UNKNOWN); setProgressGroup(progress, IProgressMonitor.UNKNOWN); setPriority(LONG); setUser(false); setSystem(false); setRule(new ServeRule(port)); } @Override protected IStatus run(IProgressMonitor monitor) { final AbstractShellCommand command = getCommand(progress, hgRoot, port, prefix, name, webdirConf, stdio, ipv6); try { command.executeToBytes(Integer.MAX_VALUE, false); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } finally { command.terminate(); progress.done(); monitor.done(); } return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return HgServeClient.class == family; } } public static boolean serve(HgRoot hgRoot, int port, String prefixPath, String name, String webdirConf, boolean stdio, boolean ipv6) { Job[] jobs = Job.getJobManager().find(HgServeClient.class); for (Job job : jobs) { ServeRule rule = (ServeRule) job.getRule(); if(rule != null && rule.port == port && job.getState() == Job.RUNNING){ return false; } } new HgServeJob(hgRoot, port, prefixPath, name, webdirConf, ipv6, stdio) .schedule(); return true; } private static AbstractShellCommand getCommand(final IProgressMonitor progress, HgRoot hgRoot, final int port, String prefixPath, String name, String webdirConf, boolean stdio, boolean ipv6) { final AbstractShellCommand command = new HgCommand("serve", "Serving repository", hgRoot, true){ @Override protected ProzessWrapper createProcessWrapper(OutputStream output, String jobName, ProcessBuilder builder) { ProzessWrapper wrapper = super.createProcessWrapper(output, jobName, builder); wrapper.setProgressGroup(progress, IProgressMonitor.UNKNOWN); wrapper.setPriority(Job.LONG); wrapper.setUser(false); wrapper.setSystem(true); return wrapper; } }; command.setExecutionRule(new AbstractShellCommand.DefaultExecutionRule()); if (port != 8000) { command.addOptions("--port", String.valueOf(port)); //$NON-NLS-1$ } if (prefixPath != null && prefixPath.length() > 0) { command.addOptions("--prefix", prefixPath); //$NON-NLS-1$ } if (name != null && name.length() > 0) { command.addOptions("--name", name); //$NON-NLS-1$ } if (webdirConf != null && webdirConf.length() > 0) { command.addOptions("--webdir-conf", webdirConf); //$NON-NLS-1$ } if (stdio) { command.addOptions("--stdio"); //$NON-NLS-1$ } if (ipv6) { command.addOptions("--ipv6"); //$NON-NLS-1$ } // start daemon return command; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgStatusClient.java000066400000000000000000000333421173713500500337420ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - initial * Bastian Doetsch - changes * Brian Wallis - getMergeStatus * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.StringReader; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; public class HgStatusClient extends AbstractClient { // expected output for merge: // b63617c1e3460bd87eb51d2b8841b37fff1834d6+00838f86e1024072e715d31f477262d5162acd09+ default // match second part (the one we merge with) // output for "usual" state: // b63617c1e3460bd87eb51d2b8841b37fff1834d6+ default // OR b63617c1e3460bd87eb51d2b8841b37fff1834d6 hallo branch // + after the id is the "dirty" flag - if some files are not committed yet // // As well in Mercurial 1.6.0 during some rebases the following output: // filtering src/nexj/core/admin/platform/websphere/WebSphereInstaller.java through // filtering src/nexj/core/meta/j2ee/ibmconfig/cells/defaultCell/applications/defaultApp/deployments/defaultApp/deployment.xml through // filtering src/nexj/core/meta/sys/system.chtypes through // 02bfc05967b86ba65a0cb990178638e4c491c865+d35923c18f8f564c6205e722119d88c6daa3f56d+ default // These leading lines are ignored. private static final Pattern ID_MERGE_AND_BRANCH_IGNORE_PATTERN = Pattern.compile("^filtering\\s.+\\sthrough\\s*$"); // group 1 group 2 group 3 // (first parent, optional dirty flag)(merge parent, optional dirty flag) space (branch name) private static final Pattern ID_MERGE_AND_BRANCH_PATTERN = Pattern.compile("^([0-9a-z]+\\+?)([0-9a-z]+)?\\+?\\s+(.+)$"); public static String getStatusWithoutIgnored(HgRoot root, IResource res) throws HgException { AbstractShellCommand command = new HgCommand("status", "Calculating resource status", root, true); //$NON-NLS-1$ // modified, added, removed, deleted, unknown, ignored, clean command.addOptions("-marduc"); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); if (res.getType() == IResource.FILE) { command.addFiles(res); } return command.executeToString(); } public static String[] getStatus(HgRoot root, String revision1, String revision2, String filter, String inPattern, String exPattern) throws HgException { AbstractShellCommand command = new HgCommand("status", "Calculating resource status", root, true); //$NON-NLS-1$ // modified, added, removed, deleted, unknown command.addOptions(filter); if (revision1 != null && revision1 != "") { command.addOptions("--rev", revision1); //$NON-NLS-1$ } if (revision2 != null && revision2 != "") { command.addOptions("--rev", revision2); //$NON-NLS-1$ } if (inPattern != null && inPattern != "") { command.addOptions("--include", inPattern); //$NON-NLS-1$ } if (exPattern != null && exPattern != "") { command.addOptions("--exclude", exPattern); //$NON-NLS-1$ } command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); return command.executeToString().split("\n"); //$NON-NLS-1$ } public static TreeSet removeStatusIndicator(String[] status) { TreeSet set = new TreeSet(); for (String line : status) { if (line.length() > 2) { set.add(line.substring(2)); } } return set; } public static String getStatusWithoutIgnored(HgRoot root) throws HgException { AbstractShellCommand command = new HgCommand("status", "Calculating resource status", root, true); //$NON-NLS-1$ // modified, added, removed, deleted, unknown, ignored, clean command.addOptions("-marduc"); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); return command.executeToString(); } /** * @param hgRoot non null * @return non null, but probably empty array with root relative file paths with all * files under the given root, which are untracked by hg */ public static String[] getUntrackedFiles(HgRoot hgRoot) throws HgException { AbstractShellCommand command = new HgCommand("status", "Calculating untracked files", hgRoot, true); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); command.addOptions("-u", "-n"); //$NON-NLS-1$ //$NON-NLS-2$ return command.executeToString().split("\n"); //$NON-NLS-1$ } public static void assertClean(HgRoot root) throws HgException { if (isDirty(root)) { throw new HgException("Unexpected condition: " + root.getName() + " is dirty"); } } public static boolean isDirty(HgRoot root) throws HgException { AbstractShellCommand command = new HgCommand("status", "Calculating dirty state", root, true); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); command.addOptions("-mard"); // modified, added, removed, deleted //$NON-NLS-1$ return command.executeToBytes().length != 0; } /** * @param root non null * @return current changeset id, merge id and branch name for the working directory * @throws HgException */ public static String[] getIdMergeAndBranch(HgRoot root) throws HgException { AbstractShellCommand command = new HgCommand("id", "Identifying status", root, true); //$NON-NLS-1$ // Full global IDs + branch name command.addOptions("-ib", "--debug"); //$NON-NLS-1$ //$NON-NLS-2$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); String versionIds = null; BufferedReader br = new BufferedReader(new StringReader(command.executeToString().trim())); try { while ((versionIds = br.readLine()) != null) { if (!ID_MERGE_AND_BRANCH_IGNORE_PATTERN.matcher(versionIds).matches()) { break; } } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } finally { try { br.close(); } catch (IOException ex) { } } Matcher m = ID_MERGE_AND_BRANCH_PATTERN.matcher((versionIds == null) ? "" : versionIds); String mergeId = null; String branch = Branch.DEFAULT; // current working directory id String id = ""; if (m.matches() && m.groupCount() > 2) { id = m.group(1); mergeId = m.group(2); branch = m.group(3); } if (id.endsWith("+")) { id = id.substring(0, id.length() - 1); } return new String[] { id, mergeId, branch }; } public static String getStatusWithoutIgnored(HgRoot root, List files) throws HgException { AbstractShellCommand command = new HgCommand("status", //$NON-NLS-1$ "Calculating status for " + files.size() + " resources", root, true); command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); // modified, added, removed, deleted, unknown, ignored, clean command.addOptions("-marduc"); //$NON-NLS-1$ command.addFiles(files); return command.executeToString(); } /** * @return root relative paths of changed files, never null */ public static String[] getDirtyFiles(HgRoot root) throws HgException { AbstractShellCommand command = new HgCommand("status", "Calculating dirty resources", root, true); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); command.addOptions("-mard"); //$NON-NLS-1$ String result = command.executeToString(); if (result == null || result.length() == 0) { return new String[0]; } // now we will have status AND path info String[] status = result.split("\n"); for (int i = 0; i < status.length; i++) { // remove status info from status AND path line status[i] = status[i].substring(2); } return status; } public static Set getDirtyFilePaths(HgRoot root) throws HgException { String[] dirtyFiles = getDirtyFiles(root); IPath rootPath = new Path(root.getAbsolutePath()); Set resources = new HashSet(); for (String rootRelativePath : dirtyFiles) { // determine absolute path IPath path = rootPath.append(rootRelativePath); resources.add(path); } return resources; } /** * Returns possible ancestor of the given file, if given file is a result of * a copy or rename operation. *

* Note: this is a very inefficient algorithm, which may need a lot of time to * complete. * * @param file * successor path (as full absolute file path) * @param root * hg root * @param firstKnownRevision the version at which the information about possible * parent file should be retrieved * * @return full absolute file path which was the source of the given file one changeset * before given version, or null if the given file was not copied or renamed * at given version. * @throws HgException */ public static File getPossibleSourcePath(HgRoot root, File file, int firstKnownRevision) throws HgException{ return getPossibleSourcePath(root, file, firstKnownRevision - 1, "" + firstKnownRevision); } /** * Guesses a possible ancestor of the given file, if given file is a result of * a copy or rename operation. *

* Note: this is a fast but inaccurate algorithm, which may not return expected * information * * @param file * successor path (as full absolute file path) * @param root * hg root * @param firstKnownRevision the version at which the information about possible * parent file should be retrieved * @return full absolute file path which was the source of the given file one changeset * before given version, or null if the given file was not copied or renamed * at given version. * @throws HgException */ public static File guessPossibleSourcePath(HgRoot root, File file, int firstKnownRevision) throws HgException { // See issue #10302: we trying to cheat: "hg status -arC --rev firstKnownRevision:tip file" will return // A file // source_file // in case the given file was known between "firstKnownRevision" and "tip" // TODO not sure if "tip" works always as expected, but now it's my best guess for the upper limit return getPossibleSourcePath(root, file, firstKnownRevision, HgRevision.TIP.getChangeset()); } private static File getPossibleSourcePath(HgRoot root, File file, int firstRev, String secondRev) throws HgException{ AbstractShellCommand command = new HgCommand("status", "Finding resource status", root, true); //$NON-NLS-1$ command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); command.addOptions("-arC"); //$NON-NLS-1$ command.addOptions("--rev"); //$NON-NLS-1$ command.addOptions(firstRev + ":" + secondRev); //$NON-NLS-1$ command.addFile(file); String result = command.executeToString(); if (result == null || result.length() == 0) { return null; } String relativePath = root.toRelative(file); String[] statusAndFileNames = result.split("\n"); //$NON-NLS-1$ String prefixAdded = MercurialStatusCache.CHAR_ADDED + " "; String prefixRemoved = MercurialStatusCache.CHAR_REMOVED + " "; for (int i = 0; i < statusAndFileNames.length; i++) { // looks like: "A folder\foo" or "R folder\foo" or "folder\foo" String pathWithStatus = statusAndFileNames[i]; if(pathWithStatus.startsWith(prefixAdded) || pathWithStatus.startsWith(prefixRemoved)){ if(i + 1 < statusAndFileNames.length && pathWithStatus.endsWith(relativePath)){ // XXX should not just trim whitespace in the path, if it contains whitespaces, it will not work // on the other side it's just idiotic to have filenames with leading or trailing spaces String nextLine = statusAndFileNames[i + 1].trim(); if(!nextLine.startsWith(prefixAdded) && !nextLine.startsWith(prefixRemoved)) { return new File(root, nextLine); } } } } return null; } /** * Execute 'hg status --rev cs --rev csparent', with bundle overlay if applicable * * @param cs * The changeset to use * @return Status output * @throws HgException */ public static String getStatusForChangeset(ChangeSet cs) throws HgException { HgCommand command = new HgCommand( "status", //$NON-NLS-1$ "Calcuting resources changes in changeset " + cs.getChangeset(), cs.getHgRoot(), true); if (cs.getBundleFile() != null) { try { command.setBundleOverlay(cs.getBundleFile()); } catch (IOException e) { throw new HgException("Couldn't set bundle overlay", e); } } // modified, added, removed, deleted command.addOptions("-mard"); //$NON-NLS-1$ command.addOptions("--rev", cs.getParentRevision(0).getChangeset()); command.addOptions("--rev", cs.getRevision().getChangeset()); command.setUsePreferenceTimeout(MercurialPreferenceConstants.STATUS_TIMEOUT); return command.executeToString(); } } HgSubreposClient.java000066400000000000000000000076421173713500500342060ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * lordofthepigs - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.utils.IniFile; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author lordofthepigs * */ public class HgSubreposClient extends AbstractClient { private static final String HGSUB = ".hgsub"; private static final String HGDIR = ".hg"; /** * Returns the list of the subrepositories of the specified Hg repository that are cloned inside the working copy. */ public static Set findSubrepositories(HgRoot hgRoot){ File hgsub = new File(hgRoot, HGSUB); if(!hgsub.isFile()){ return new HashSet(); } Map subrepos; try { IniFile iniFile = new IniFile(hgsub.getAbsolutePath()); subrepos = iniFile.getSection(null); } catch (FileNotFoundException e) { // this shouldn't happen because we checked for existence of the file before, but who knows, // bad timing happens... MercurialEclipsePlugin.logError(e); return new HashSet(); } if(subrepos == null || subrepos.isEmpty()){ return new HashSet(); } Set result = new HashSet(); for(String subReposRootPath : subrepos.keySet()){ File subReposRootDir = new File(hgRoot, subReposRootPath); if(!subReposRootDir.isDirectory()){ // for some reason the subrepos was not cloned or disappeared, just ignore it continue; } File subRepoHg = new File(subReposRootDir, HGDIR); if(subRepoHg.isDirectory()){ // we are reasonably sure that an HgRoot really exists in subReposRootDir try{ result.add(new HgRoot(subReposRootDir)); } catch(IOException ioe){ MercurialEclipsePlugin.logError(ioe); } } } return result; } public static Set findSubrepositoriesRecursively(HgRoot root){ Set found = new HashSet(); doFindSubrepositoriesRecursively(root, found, Path.EMPTY); return found; } public static Set findSubrepositoriesRecursivelyWithin(HgRoot root, IResource container){ if(container.getType() == IResource.FILE){ // a file cannot contain a subrepo return new HashSet(); } Set found = new HashSet(); doFindSubrepositoriesRecursively(root, found, ResourceUtils.getPath(container)); return found; } /** * recursively finds all the subrepositories under the specified HgRoot and stores all the * discovered subrepos in the specified set. An IPath can optionally be specified, in which * case, all the returned subrepos will be children of that IPath. * * @param containerPath * non null. Use {@link Path#EMPTY} if the containerPath should be not used */ private static void doFindSubrepositoriesRecursively(HgRoot root, Set found, IPath containerPath){ Set subs = findSubrepositories(root); for(HgRoot sub : subs){ if(containerPath.isEmpty() || containerPath.isPrefixOf(sub.getIPath())) { found.add(sub); doFindSubrepositoriesRecursively(sub, found, containerPath); } } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgTagClient.java000066400000000000000000000076221173713500500331740ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation of remove * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.vectrace.MercurialEclipse.compare.TagComparator; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Tag; public class HgTagClient extends AbstractClient { private static final Pattern GET_TAGS_PATTERN = Pattern.compile("^(.*) ([-0-9]+):([a-f0-9]+)( local)?$"); //$NON-NLS-1$ /** * Fetches all tags for given root. The tags do NOT have full changeset info * attached. * @param hgRoot non null * @return never null, might be empty array * @throws HgException */ public static Tag[] getTags(HgRoot hgRoot) throws HgException { AbstractShellCommand command = new HgCommand("tags", "Retrieving tags", hgRoot, false); //$NON-NLS-1$ command.addOptions("-v"); //$NON-NLS-1$ String[] lines = command.executeToString().split("\n"); //$NON-NLS-1$ Collection tags = getTags(hgRoot, lines); Tag[] sortedTags = tags.toArray(new Tag[] {}); return sortedTags; } /** * @param hgRoot non null * @param withChangesets true to fetch corresponding changesets too * @return never null, might be empty array * @throws HgException */ public static Tag[] getTags(HgRoot hgRoot, boolean withChangesets) throws HgException { Tag[] tags = getTags(hgRoot); if(withChangesets) { for (Tag tag : tags) { // triggers changeset loading, if the local changeset cache // doesn't contain the tag version tag.getChangeSet(); } } return tags; } protected static Collection getTags(HgRoot hgRoot, String[] lines) throws HgException { List tags = new ArrayList(); for (String line : lines) { Matcher m = GET_TAGS_PATTERN.matcher(line); if (m.matches()) { String tagName = m.group(1).trim(); Tag tag = new Tag(hgRoot, tagName, Integer.parseInt(m.group(2)), m.group(3), m.group(4) != null); tags.add(tag); } else { throw new HgException(Messages.getString("HgTagClient.parseException") + line + "'"); //$NON-NLS-1$ //$NON-NLS-2$ } } Collections.sort(tags, new TagComparator()); return tags; } /** * @param user * if null, uses the default user * @throws HgException */ public static void addTag(HgRoot hgRoot, String name, String rev, String user, boolean local, boolean force) throws HgException { HgCommand command = new HgCommand( "tag", "Tagging revision " + ((rev == null) ? "" : rev + " ") + "as " + name, hgRoot, false); //$NON-NLS-1$ if (local) { command.addOptions("-l"); } if (force) { command.addOptions("-f"); } if (rev != null) { command.addOptions("-r", rev); } command.addUserName(user); command.addOptions(name); command.executeToBytes(); command.rememberUserName(); } public static String removeTag(HgRoot hgRoot, Tag tag, String user) throws HgException { HgCommand command = new HgCommand("tag", "Removing tag " + tag, hgRoot, false); //$NON-NLS-1$ command.addUserName(user); command.addOptions("--remove"); command.addOptions(tag.getName()); String result = command.executeToString(); command.rememberUserName(); return result; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/HgUpdateClient.java000066400000000000000000000066311173713500500337020ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; public class HgUpdateClient extends AbstractClient { public static void cleanUpdate(final HgRoot hgRoot, String revision) throws HgException { update(hgRoot, revision, true); } /** * Perform an update and refresh the workspace. Handles unresolved conflicts and shows the user a message */ public static void update(final HgRoot hgRoot, String revision, boolean clean) throws HgException { try { updateWithoutRefresh(hgRoot, revision, clean); } catch (HgException e) { if (isWorkspaceUpdateConflict(e)) { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { MessageDialog .openInformation(null, "Unresolved conflicts", "You have unresolved conflicts after update. Use Synchronize View to edit conflicts"); } }); } else { throw e; } } finally { new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.LOCAL).schedule(); } } /** * Perform an update. * * @param hgRoot * The root to use * @param revision * The revision, may be null * @param clean * Whether a clean update should be done * @return The result of the invocation */ public static String updateWithoutRefresh(HgRoot hgRoot, String revision, boolean clean) throws HgException { HgCommand command = new HgCommand("update", makeDescription(revision, clean), hgRoot, false); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.UPDATE_TIMEOUT); if (revision != null && revision.trim().length() > 0) { command.addOptions("-r", revision); //$NON-NLS-1$ } if (clean) { command.addOptions("-C"); //$NON-NLS-1$ } addMergeToolPreference(command); return command.executeToString(); } private static String makeDescription(String revision, boolean clean) { revision = (revision == null || revision.trim().length() == 0) ? null : revision.trim(); if (revision != null) { return ((clean) ? "Clean update" : "Updating") + " to " + revision; } return (clean) ? "Clean update" : "Updating working directory"; } public static boolean isWorkspaceUpdateConflict(HgException e) { return e.getMessage().contains("use 'hg resolve' to retry unresolved file merges"); } public static boolean isCrossesBranchError(HgException e) { return e.getMessage().contains("abort: crosses branches") && e.getStatus().getCode() == -1; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/IConfiguration.java000066400000000000000000000016231173713500500337560ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; /** * @author Stefan * */ public interface IConfiguration { /** * @return */ String getExecutable(); /** * @param commandId * @return */ int getTimeOut(String commandId); /** * @param preferenceConstant * @param defaultIfNotSet * @return */ String getPreference(String preferenceConstant, String defaultIfNotSet); } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/IConsole.java000066400000000000000000000015371173713500500325550ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; /** * @author Stefan * */ public interface IConsole { void commandInvoked(String command); void commandCompleted(int exitCode, long timeInMillis, String message, Throwable error); void printError(String message, Throwable root); void printMessage(String message, Throwable root); } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/IErrorHandler.java000066400000000000000000000014271173713500500335400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; /** * @author Stefan * */ public interface IErrorHandler { /** * @param e */ void logError(Throwable e); /** * @param message * @param e * @return */ void logWarning(String message, Throwable e); } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/Messages.java000066400000000000000000000021311173713500500326000ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.commands.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } RootlessHgCommand.java000066400000000000000000000026701173713500500343520ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.util.List; import org.eclipse.core.runtime.Assert; /** * A command to invoke hg definitely outside of an hg root. */ public class RootlessHgCommand extends AbstractShellCommand { public RootlessHgCommand(String command, String uiName) { this(command, uiName, null); } public RootlessHgCommand(String command, String uiName, File workingDir) { super(uiName, null, workingDir, false); Assert.isNotNull(command); this.command = command; } // operations /** * @see com.vectrace.MercurialEclipse.commands.AbstractShellCommand#customizeCommands(java.util.List) */ @Override protected void customizeCommands(List cmd) { cmd.add(1, "-y"); } /** * @see com.vectrace.MercurialEclipse.commands.AbstractShellCommand#getExecutable() */ @Override protected String getExecutable() { return HgClients.getExecutable(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/000077500000000000000000000000001173713500500323705ustar00rootroot00000000000000HgAtticClient.java000066400000000000000000000036671173713500500356520ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian * */ public class HgAtticClient extends AbstractClient { public static String shelve(HgRoot hgRoot, String commitMessage, boolean git, String user, String name) throws HgException { HgCommand cmd = new HgCommand("attic-shelve", "Invoking attic-shelve", hgRoot, false); if (commitMessage != null && commitMessage.length() > 0) { cmd.addOptions("-m", commitMessage); // $NON-NLS-1$ } if (git) { cmd.addOptions("--git"); // $NON-NLS-1$ } cmd.addUserName(user); cmd.addOptions("--currentdate", name); // $NON-NLS-1$ String result = cmd.executeToString(); cmd.rememberUserName(); return result; } public static String unshelve(HgRoot hgRoot, boolean guessRenamedFiles, boolean delete, String name) throws HgException { AbstractShellCommand cmd = new HgCommand("attic-unshelve", "Invoking attic-unshelve", hgRoot, false); if (guessRenamedFiles) { cmd.addOptions("--similarity"); // $NON-NLS-1$ } if (delete) { cmd.addOptions("--delete"); // $NON-NLS-1$ } cmd.addOptions(name); return cmd.executeToString(); } } HgBookmarkClient.java000066400000000000000000000055401173713500500363430ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import java.util.ArrayList; import java.util.List; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Bookmark; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian */ public class HgBookmarkClient extends AbstractClient { /** * @return a List of bookmarks */ public static List getBookmarks(HgRoot hgRoot) throws HgException { AbstractShellCommand cmd = new HgCommand("bookmarks", "Listing bookmarks", hgRoot, true); cmd.addOptions("--config", "extensions.hgext.bookmarks="); //$NON-NLS-1$ //$NON-NLS-2$ String result = cmd.executeToString(); return convert(result); } private static ArrayList convert(String result) { ArrayList bookmarks = new ArrayList(); if (!result.startsWith("no bookmarks set")) { //$NON-NLS-1$ String[] split = result.split("\n"); //$NON-NLS-1$ for (String string : split) { bookmarks.add(new Bookmark(string)); } } return bookmarks; } public static String create(HgRoot hgRoot, String name, String targetChangeset) throws HgException { AbstractShellCommand cmd = new HgCommand("bookmarks", "Adding bookmark", hgRoot, true); cmd.addOptions("--config", "extensions.hgext.bookmarks="); //$NON-NLS-1$ //$NON-NLS-2$ cmd.addOptions("--rev", targetChangeset, name); //$NON-NLS-1$ return cmd.executeToString(); } public static String rename(HgRoot hgRoot, String name, String newName) throws HgException { AbstractShellCommand cmd = new HgCommand("bookmarks", "Renaming bookmark", hgRoot, true); cmd.addOptions("--config", "extensions.hgext.bookmarks="); //$NON-NLS-1$ //$NON-NLS-2$ cmd.addOptions("--rename", name, newName); //$NON-NLS-1$ return cmd.executeToString(); } public static String delete(HgRoot hgRoot, String name) throws HgException { AbstractShellCommand cmd = new HgCommand("bookmarks", "Deleting bookmark", hgRoot, true); cmd.addOptions("--config", "extensions.hgext.bookmarks="); //$NON-NLS-1$ //$NON-NLS-2$ cmd.addOptions("--delete", name); //$NON-NLS-1$ return cmd.executeToString(); } } HgGLogClient.java000066400000000000000000000077001173713500500354260ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.GChangeSet; import com.vectrace.MercurialEclipse.model.GChangeSet.RowCount; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgGLogClient extends HgCommand { private final List sets = new ArrayList(); public HgGLogClient(IResource resource, int batchSize, int startRev) throws HgException { super("glog", "Retrieving revision graph for resource", resource, false); File fileHandle = ResourceUtils.getFileHandle(resource); if(fileHandle.getPath().length() == 0) { // unknown or virtual resource return; } if (resource.getType() == IResource.FILE) { addOptions(fileHandle.getAbsolutePath()); } else { if (resource.getType() != IResource.PROJECT){ // glog doesn't follow directories return; } if(!hgRoot.equals(fileHandle)){ // multiple projects under same hg root handled by glog as directories return; } } configureOptions(batchSize, startRev); load(executeToString()); } private void configureOptions(int batchSize, int startRev) { addOptions("--config", "extensions.graphlog="); //$NON-NLS-1$ //$NON-NLS-2$ addOptions("--template", "*{rev}\\n"); // Removes everything //$NON-NLS-1$ //$NON-NLS-2$ if(batchSize > 0) { addOptions("--limit", String.valueOf(batchSize)); //$NON-NLS-1$ } else { // set very high limit for log/glog when no limit is wanted to override limits set in user's .hgrc addOptions("--limit", HgLogClient.NOLIMIT); //$NON-NLS-1$ } if (startRev >= 0 && startRev != Integer.MAX_VALUE) { // always advise to follow until 0 revision: the reason is that log limit // might be bigger then the difference of two consequent revisions on a specific resource addOptions("-r"); addOptions(startRev + ":" + 0); } setUsePreferenceTimeout(MercurialPreferenceConstants.LOG_TIMEOUT); } public HgGLogClient(HgRoot hgRoot, int batchSize, int startRev) throws HgException { super("glog", "Retrieving revision graph", hgRoot, false); configureOptions(batchSize, startRev); load(executeToString()); } private void load(String s) { String[] split = s.split("\n"); //$NON-NLS-1$ // real changeset count as glog inserts a line between two changesets int length = split.length / 2; int lengthp1 = length; RowCount rowCount = new RowCount(); GChangeSet last = null; // Mercurial 1.9 glog issue workaround // TODO: redesign parsing algorithm and revision graph presentation int j=0; for (int i = 0; i < lengthp1; i++) { // adjust index for spacing int changeset = i * 2; String afterS = i != length ? split[changeset + 1] : ""; if(split[changeset].indexOf('*') == -1) { continue; } // add current changeset and next line GChangeSet newOne = new GChangeSet(rowCount, j++, split[changeset], afterS); newOne.clean(last); last = newOne; sets.add(last); } } public List getChangeSets() { return sets; } } HgRebaseClient.java000066400000000000000000000146501173713500500360010ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2005-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import java.io.File; import java.util.regex.Pattern; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; /** * @author bastian * */ public class HgRebaseClient extends AbstractClient { private static final Pattern REBASING_CONFLICT = Pattern.compile("^abort:.*unresolved conflicts", Pattern.MULTILINE); /** * Calls hg rebase. *

* Doesn't support supplying custom commit messages for collapse and continued collapse. * * @param hgRoot * a hg root that is to be rebased. * @param sourceRev * --source option, -1 if not set * @param baseRev * --base option, -1 if not set * @param destRev * --dest option, -1 if not set * @param collapse * true, if --collapse is to be used * @param cont * true, if --continue is to be used * @param abort * true, if --abort is to be used * @param keepBranches * @param useExternalMergeTool * @param user * The user to use for collapse and continued collapse. May be null * @return the output of the command * @throws HgException */ public static String rebase(HgRoot hgRoot, int sourceRev, int baseRev, int destRev, boolean collapse, boolean cont, boolean abort, boolean keepBranches, boolean keep, boolean useExternalMergeTool, String user) throws HgException { AbstractShellCommand c = new HgCommand("rebase", "Rebasing", hgRoot, false);//$NON-NLS-1$ c.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); c.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT); if (!useExternalMergeTool) { // we use (non-existent) simplemerge, so no tool is started. We // need this option, though, as we still want the Mercurial merge to // take place. c.addOptions("--config", "ui.merge=simplemerge"); //$NON-NLS-1$ //$NON-NLS-2$ // Do not invoke external editor for commit message // Future: Allow user to specify this c.addOptions("--config", "ui.editor=echo"); //$NON-NLS-1$ //$NON-NLS-2$ // Future: Delete this block and use addMergeToolPreference(command); } c.addOptions("--config", "extensions.hgext.rebase="); //$NON-NLS-1$ //$NON-NLS-2$ // User is only applicable for collapse and continued collapse invocations if (user != null) { c.addOptions("--config", "ui.username=" + user); //$NON-NLS-1$ //$NON-NLS-2$ } if (!cont && !abort) { if (sourceRev >= 0 && baseRev <= 0) { c.addOptions("--source", "" + sourceRev); //$NON-NLS-1$ //$NON-NLS-2$ } if (sourceRev < 0 && baseRev >= 0) { c.addOptions("--base", "" + baseRev); //$NON-NLS-1$ //$NON-NLS-2$ } if (destRev >= 0) { c.addOptions("--dest", "" + destRev); //$NON-NLS-1$ //$NON-NLS-2$ } if (collapse) { c.addOptions("--collapse"); //$NON-NLS-1$ } } if (cont && !abort) { c.addOptions("--continue"); //$NON-NLS-1$ } if (abort && !cont) { c.addOptions("--abort"); //$NON-NLS-1$ } if (keepBranches) { c.addOptions("--keepbranches"); //$NON-NLS-1$ } if (keep) { c.addOptions("--keep"); //$NON-NLS-1$ } MercurialUtilities.setOfferAutoCommitMerge(true); return c.executeToString(); } /** * Invoke hg rebase --abort. Note: Refreshes the workspace. * * @param hgRoot * The hg root to use * @return The result message * @throws HgException * On error */ public static String abortRebase(HgRoot hgRoot) throws HgException { try { return rebase(hgRoot, -1, -1, -1, false, false, true, false, false, false, null); } finally { new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.ALL).schedule(); } } /** * Check to see if we are in the middle of a rebase.
* Assume the presence of the /.hg/rebasestate file means that we are * * @param hgRoot * @return true if we are currently rebasing */ public static boolean isRebasing(HgRoot hgRoot) { return new File(hgRoot, ".hg" + File.separator + "rebasestate").exists(); } /** * Determine if the given exception indicates a rebase conflict occurred. *

* Warning: Will this work on non-English locales? *

* Warning: Will hg output change? * * @param e * The exception to check * @return True if the exception indicates a conflict occurred */ public static boolean isRebaseConflict(HgException e) { String message = e.getMessage(); // Conflicts are expected: // 1.6.x: // /bin/sh: simplemerge: command not found // merging file1.txt // merging file1.txt // merging file1.txt failed! // abort: fix unresolved conflicts with hg resolve then run hg rebase --continue. // Command line: /home/john/runtime-New_configuration/hgtest2/hg -y // rebase --config ui.merge=simplemerge --config ui.editor=echo --config // extensions.hgext.rebase= --config ui.username=john --base 8 --dest 5, error // code: 255 // 1.8.3 and 1.8.4 // merging file1-4.txt // /bin/sh: simplemerge: command not found // merging file1-4.txt failed! // abort: unresolved conflicts (see hg resolve, then hg rebase --continue). // Command line: /home/john/runtime-New_configuration/hgtest:hg -y rebase --config // ui.merge=simplemerge --config ui.editor=echo --config extensions.hgext.rebase= --source // 3442 --dest 3441, error code: 255 return (message != null && REBASING_CONFLICT.matcher(message).find()); } } HgSignClient.java000066400000000000000000000102671173713500500355000ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.ResourcesPlugin; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.GpgCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialUtilities; /** * Client for hg sign * * @author Bastian Doetsch * */ public final class HgSignClient { private HgSignClient() { // hide constructor of utility class. } /** * Calls hg sign. add a signature for the current or given revision If no * revision is given, the parent of the working directory is used, or tip if * no revision is checked out. * * @param hgRoot * the current hg root * @param cs * ChangeSet, may be null * @param key * the keyId to use * @param message * commit message * @param user * user name for commit * @param local * flag, if signing is only local * @param force * flag to even sign if sigfile is changed * @param noCommit * flag, if commit shall happen (invalidates params message and * user) * @param passphrase * the passphrase or null * @author Bastian Doetsch */ public static String sign(HgRoot hgRoot, ChangeSet cs, String key, String message, String user, boolean local, boolean force, boolean noCommit, String passphrase) throws HgException { HgCommand command = new HgCommand("sign", "Signing revision", hgRoot, true); //$NON-NLS-1$ File file = new File("me.gpg.tmp"); //$NON-NLS-1$ String cmd = "gpg.cmd=" + //$NON-NLS-1$ MercurialUtilities.getGpgExecutable(true) + " --batch --no-tty --armor"; //$NON-NLS-1$ if (passphrase != null && passphrase.length() > 0) { FileWriter fw = null; try { fw = new FileWriter(file); fw.write(passphrase.concat("\n")); //$NON-NLS-1$ fw.flush(); cmd = cmd + " --passphrase-file " + //$NON-NLS-1$ file.getCanonicalPath(); } catch (IOException e) { throw new HgException(e.getMessage()); } finally { if (fw != null) { try { fw.close(); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } } } } command.addOptions("-k", key, "--config", "extensions.gpg=", "--config", cmd); //$NON-NLS-1$ //$NON-NLS-2$ if (local) { command.addOptions("-l"); //$NON-NLS-1$ } if (force) { command.addOptions("-f"); //$NON-NLS-1$ } if (noCommit) { command.addOptions("--no-commit"); //$NON-NLS-1$ } else { command.addOptions("-m", message); //$NON-NLS-1$ command.addUserName(user); } command.addOptions(cs.getChangeset()); String result; try { result = command.executeToString(); command.rememberUserName(); return result; } finally { if (!file.delete()) { throw new HgException(file.getName()+" could not be deleted."); } } } public static String getPrivateKeyList(HgRoot hgRoot) throws HgException { List getKeysCmd = new ArrayList(); getKeysCmd.add(MercurialUtilities.getGpgExecutable(true)); getKeysCmd.add("--list-secret-keys"); //$NON-NLS-1$ GpgCommand command = new GpgCommand(hgRoot, "Retrieving GPG key list", getKeysCmd, ResourcesPlugin .getWorkspace().getRoot().getLocation().toFile()); return new String(command.executeToBytes()); } } HgSigsClient.java000066400000000000000000000062761173713500500355120ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.CoreException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Signature; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; /** * @author bastian */ public class HgSigsClient extends AbstractClient { private static HgException notAvailable; /** * Gets signed changesets * * @param hgRoot * @return the identifiers of signed changesets (rev:node) * @throws HgException */ public static List getSigs(HgRoot hgRoot) throws CoreException { try { List nodes = new ArrayList(); File sigFile = new File(hgRoot, ".hgsigs"); //$NON-NLS-1$ if (sigFile.exists()) { LineNumberReader reader = null; try { reader = new LineNumberReader(new FileReader(sigFile)); String line = reader.readLine(); while (line != null) { String nodeId = line.substring(0, line.indexOf(" 0 ")); //$NON-NLS-1$ Signature sig = new Signature(null, nodeId, hgRoot); nodes.add(sig); line = reader.readLine(); } } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } finally { if (reader != null) { reader.close(); } } } return nodes; } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } } /** * @return may return null, if "sigcheck" command is not available * @throws HgException if command failed */ public static String checkSig(HgRoot hgRoot, String nodeId) throws HgException { if(notAvailable != null){ return null; } try { AbstractShellCommand c = new HgCommand("sigcheck", //$NON-NLS-1$ "Checking signature", hgRoot, false); c.addOptions("--config", "extensions.gpg="); c.setUsePreferenceTimeout(MercurialPreferenceConstants.DEFAULT_TIMEOUT); c.addOptions(nodeId); return c.executeToString(); } catch (HgException e) { String message = e.getMessage(); if(message != null && message.contains("unknown") && message.contains("'sigcheck'")){ MercurialEclipsePlugin.logError(e); notAvailable = e; return null; } throw e; } } } HgStripClient.java000066400000000000000000000050711173713500500356760ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; /** * Calls hg strip * * @author bastian */ public final class HgStripClient { private HgStripClient() { // hide constructor of utility class. } public static String stripCurrent(final HgRoot hgRoot, boolean keep, boolean backup, boolean force) throws HgException { return strip(hgRoot, keep, backup, force, "."); } /** * strip a revision and all later revs on the same branch */ public static String strip(final HgRoot hgRoot, boolean keep, boolean backup, boolean force, ChangeSet changeset) throws HgException { return strip(hgRoot, keep, backup, force, changeset.getChangeset()); } private static String strip(final HgRoot hgRoot, boolean keep, boolean backup, boolean force, String changeset) throws HgException { HgCommand command = new HgCommand("strip", "Stripping revision " + changeset, hgRoot, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.COMMIT_TIMEOUT); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (keep) { command.addOptions("--keep"); //$NON-NLS-1$ } if (!backup) { command.addOptions("--no-backup"); //$NON-NLS-1$ } if (force) { command.addOptions("-f"); //$NON-NLS-1$ } command.addOptions(changeset); String result = command.executeToString(); new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.ALL).schedule(); return result; } } HgSvnClient.java000066400000000000000000000065511173713500500353470ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2005-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import java.io.File; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.commands.RootlessHgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author bastian * */ public class HgSvnClient extends AbstractClient { public static String pull(HgRoot hgRoot) throws HgException { HgCommand cmd = new HgCommand("svn", "Invoking svn pull", hgRoot, false); cmd.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT); cmd.addOptions("pull"); //$NON-NLS-1$ String result = cmd.executeToString(); // The reason to use "all" instead of only "local + incoming", is that we can pull // from another repo as the sync clients for given project may use // in this case, we also need to update "outgoing" changesets new RefreshRootJob(hgRoot, RefreshRootJob.ALL).schedule(); return result; } public static String push(HgRoot currentWorkingDirectory) throws HgException { AbstractShellCommand cmd = new HgCommand("svn", //$NON-NLS-1$ "Invoking svn push", currentWorkingDirectory, false); cmd.setUsePreferenceTimeout(MercurialPreferenceConstants.PUSH_TIMEOUT); cmd.addOptions("push"); //$NON-NLS-1$ return cmd.executeToString(); } public static String rebase(HgRoot hgRoot) throws HgException { HgCommand cmd = new HgCommand("svn", "Invoking svn rebase", hgRoot, false); cmd.setUsePreferenceTimeout(MercurialPreferenceConstants.PUSH_TIMEOUT); cmd.addOptions("--config", "extensions.hgext.rebase="); //$NON-NLS-1$ //$NON-NLS-2$ cmd.addOptions("rebase"); //$NON-NLS-1$ String result = cmd.executeToString(); new RefreshRootJob(hgRoot, RefreshRootJob.ALL).schedule(); return result; } public static void clone(File currentWorkingDirectory, IHgRepositoryLocation repo, boolean timeout, String cloneName) throws HgException { AbstractShellCommand cmd = new RootlessHgCommand("svnclone", //$NON-NLS-1$ "Invoking svnclone", ResourceUtils.getFirstExistingDirectory(currentWorkingDirectory)); cmd.setUsePreferenceTimeout(MercurialPreferenceConstants.CLONE_TIMEOUT); addRepoToHgCommand(repo, cmd); if (cloneName != null) { cmd.addOptions(cloneName); } if (timeout) { cmd.setUsePreferenceTimeout(MercurialPreferenceConstants.CLONE_TIMEOUT); cmd.executeToBytes(); } else { cmd.executeToBytes(Integer.MAX_VALUE); } } } HgTransplantClient.java000066400000000000000000000075501173713500500367270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions; import java.net.URI; import java.util.SortedSet; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; public final class HgTransplantClient { public static class TransplantOptions { public boolean all; public boolean branch; public boolean continueLastTransplant; public boolean filterChangesets; public boolean merge; public boolean prune; public String branchName; public String filter; public String mergeNodeId; public String pruneNodeId; /** changesets sorted in the ascending revision order */ public SortedSet nodes; /** * @return Human readable description */ public String getDescription() { if (continueLastTransplant) { return "Continuing transplant"; } else if (all) { return "Transplanting all revisions from source"; } else if (nodes == null) { return "Transplanting"; } else if (nodes.size() > 1) { return "Transplanting " + nodes.size() + " revisions"; } return "Transplanting revision " + nodes.first().getChangeset(); } } private HgTransplantClient() { // hide constructor of utility class. } /** * Cherrypicks given ChangeSets from repository or branch. */ public static String transplant(HgRoot hgRoot, IHgRepositoryLocation repo, TransplantOptions options) throws HgException { AbstractShellCommand command = new HgCommand("transplant", options.getDescription(), hgRoot, false); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(hgRoot)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT); command.addOptions("--config", "extensions.hgext.transplant="); //$NON-NLS-1$ //$NON-NLS-2$ command.addOptions("--log"); //$NON-NLS-1$ if (options.continueLastTransplant) { command.addOptions("--continue"); //$NON-NLS-1$ } else { if (options.branch) { command.addOptions("--branch"); //$NON-NLS-1$ command.addOptions(options.branchName); if (options.all) { command.addOptions("--all"); //$NON-NLS-1$ } else { // the exact revision will be specified below via changeset id } } else { command.addOptions("--source"); //$NON-NLS-1$ URI uri = repo.getUri(); if (uri != null) { command.addOptions(uri.toASCIIString()); } else { command.addOptions(repo.getLocation()); } } if (options.prune) { command.addOptions("--prune"); //$NON-NLS-1$ command.addOptions(options.pruneNodeId); } if (options.merge) { command.addOptions("--merge"); //$NON-NLS-1$ command.addOptions(options.mergeNodeId); } if (!options.all && options.nodes != null && options.nodes.size() > 0) { for (ChangeSet node : options.nodes) { command.addOptions(node.getChangeset()); } } if (options.filterChangesets) { command.addOptions("--filter", options.filter); //$NON-NLS-1$ } } return new String(command.executeToBytes()); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/forest/000077500000000000000000000000001173713500500336725ustar00rootroot00000000000000HgFcloneClient.java000066400000000000000000000044141173713500500373050ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/forest/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.forest; import java.io.File; import java.net.URI; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.RootlessHgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; /** * @author bastian * */ public class HgFcloneClient extends AbstractClient { public static void fclone(File parentDirectory, IHgRepositoryLocation repo, boolean noUpdate, boolean pull, boolean uncompressed, boolean timeout, String rev, String cloneName) throws HgException { AbstractShellCommand command = new RootlessHgCommand("fclone", "Invoking fclone", parentDirectory); //$NON-NLS-1$ // command.addOptions("--config", "extensions.hgext.forest="); //$NON-NLS-1$ //$NON-NLS-2$ if (noUpdate) { command.addOptions("--noupdate"); //$NON-NLS-1$ } if (pull) { command.addOptions("--pull"); //$NON-NLS-1$ } if (uncompressed) { command.addOptions("--uncompressed"); //$NON-NLS-1$ } if (rev != null && rev.length() > 0) { command.addOptions("--rev", rev); //$NON-NLS-1$ } URI uri = repo.getUri(); if (uri != null) { command.addOptions(uri.toASCIIString()); } else { command.addOptions(repo.getLocation()); } if (cloneName != null) { command.addOptions(cloneName); } if (timeout) { command .setUsePreferenceTimeout(MercurialPreferenceConstants.CLONE_TIMEOUT); command.executeToBytes(); } else { command.executeToBytes(Integer.MAX_VALUE); } } } HgFpushPullClient.java000066400000000000000000000077231173713500500400270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/forest/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.forest; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.Set; import org.eclipse.core.runtime.CoreException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgPushPullClient; import com.vectrace.MercurialEclipse.commands.RootlessHgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; public class HgFpushPullClient extends HgPushPullClient { public static String fpush(File forestRoot, IHgRepositoryLocation repo, ChangeSet changeset, int timeout, File snapFile) throws CoreException { AbstractShellCommand command = new RootlessHgCommand("fpush", "Invoking fpush", forestRoot); command.setUsePreferenceTimeout(MercurialPreferenceConstants.PUSH_TIMEOUT); if (snapFile != null) { try { command.addOptions("--snapfile", snapFile.getCanonicalPath()); } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } } HgPushPullClient.applyChangeset(command, changeset); URI uri = repo.getUri(); if (uri != null) { command.addOptions(uri.toASCIIString()); } else { command.addOptions(repo.getLocation()); } return new String(command.executeToBytes(timeout)); } public static String fpull(File forestRoot, IHgRepositoryLocation repo, boolean update, boolean timeout, ChangeSet changeset, boolean walkHg, File snapFile, boolean partial) throws HgException { URI uri = repo.getUri(); String pullSource; if (uri != null) { pullSource = uri.toASCIIString(); } else { pullSource = repo.getLocation(); } AbstractShellCommand command = new RootlessHgCommand("fpull", "Invoking fpull", forestRoot); if (update) { command.addOptions("--update"); } applyChangeset(command, changeset); if (snapFile != null) { try { command.addOptions("--snapfile", snapFile.getCanonicalPath()); } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } } if (walkHg) { command.addOptions("--walkhg", "true"); } if (partial) { command.addOptions("--partial"); } command.addOptions(pullSource); String result; if (timeout) { command.setUsePreferenceTimeout(MercurialPreferenceConstants.PULL_TIMEOUT); result = new String(command.executeToBytes()); } else { result = new String(command.executeToBytes(Integer.MAX_VALUE)); } Set roots = MercurialEclipsePlugin.getRepoManager().getAllRepoLocationRoots(repo); // The reason to use "all" instead of only "local + incoming", is that we can pull // from another repo as the sync clients for given project may use // in this case, we also need to update "outgoing" changesets final int flags = RefreshRootJob.ALL; for (final HgRoot hgRoot : roots) { if (update) { new RefreshWorkspaceStatusJob(hgRoot, flags).schedule(); } else { new RefreshRootJob(hgRoot, flags).schedule(); } } return result; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/000077500000000000000000000000001173713500500330055ustar00rootroot00000000000000HgQAppliedClient.java000066400000000000000000000041411173713500500367060ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import java.util.List; import org.eclipse.core.runtime.Assert; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Patch; /** * @author bastian * */ public class HgQAppliedClient extends AbstractClient { public static List getAppliedPatches(HgRoot root) throws HgException { Assert.isNotNull(root); AbstractShellCommand command = new HgCommand("qapplied", "Invoking qapplied", root, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ command.addOptions("-v"); //$NON-NLS-1$ command.addOptions("-s"); //$NON-NLS-1$ return HgQSeriesClient.parse(command.executeToString()); } public static List getUnappliedPatches(HgRoot root) throws HgException{ Assert.isNotNull(root); AbstractShellCommand command = new HgCommand("qunapplied", "Invoking qunapplied", root, true); //$NON-NLS-1$ command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ command.addOptions("-v"); //$NON-NLS-1$ command.addOptions("-s"); //$NON-NLS-1$ return HgQSeriesClient.parse(command.executeToString()); } } HgQDeleteClient.java000066400000000000000000000046571173713500500365460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.Assert; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Patch; /** * @author bastian * */ public class HgQDeleteClient extends AbstractClient { public static String delete(HgRoot root, boolean keep, String patch) throws HgException { List patches = new ArrayList(1); patches.add(patch); return doDelete(root, keep, null, patches); } public static String delete(HgRoot root, boolean keep, ChangeSet changeset, List patches) throws HgException { Assert.isNotNull(patches); List patcheNames = new ArrayList(patches.size()); for (Patch patch : patches) { patcheNames.add(patch.getName()); } return doDelete(root, keep, changeset, patcheNames); } private static String doDelete(HgRoot root, boolean keep, ChangeSet changeset, List patches) throws HgException { Assert.isNotNull(patches); Assert.isNotNull(root); AbstractShellCommand command = new HgCommand("qdelete", //$NON-NLS-1$ "Invoking qdelete", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (keep) { command.addOptions("--keep"); //$NON-NLS-1$ } if (changeset != null) { command.addOptions("--rev", changeset.getChangeset()); //$NON-NLS-1$ } else { for (String patch : patches) { command.addOptions(patch); } } return command.executeToString(); } } HgQFinishClient.java000066400000000000000000000037461173713500500365620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import java.util.List; import org.eclipse.core.runtime.Assert; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Patch; /** * @author bastian * */ public class HgQFinishClient extends AbstractClient { private static AbstractShellCommand makeCommand(HgRoot root) { Assert.isNotNull(root); AbstractShellCommand command = new HgCommand("qfinish", //$NON-NLS-1$ "Invoking qfinish", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ return command; } @SuppressWarnings("null") public static String finish(HgRoot root, List revs) throws HgException { Assert.isTrue(revs != null && revs.size() > 0); AbstractShellCommand command = makeCommand(root); for (Patch p : revs) { command.addOptions(p.getName()); } return command.executeToString(); } /** * Calls qfinish -a */ public static String finishAllApplied(HgRoot root) throws HgException { AbstractShellCommand command = makeCommand(root); command.addOptions("--applied"); return command.executeToString(); } } HgQFoldClient.java000066400000000000000000000052651173713500500362240ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.Assert; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.commands.HgCommitClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Patch; /** * @author bastian * */ public class HgQFoldClient extends AbstractClient { public static String fold(HgRoot root, boolean keep, String message, String patchName) throws HgException { List patchNames = new ArrayList(1); patchNames.add(patchName); return doFold(root, keep, message, patchNames); } public static String fold(HgRoot root, boolean keep, String message, List patches) throws HgException { Assert.isNotNull(patches); List patchNames = new ArrayList(patches.size()); for (Patch patch : patches) { patchNames.add(patch.getName()); } return doFold(root, keep, message, patchNames); } private static String doFold(HgRoot root, boolean keep, String message, List patches) throws HgException { Assert.isNotNull(patches); Assert.isNotNull(root); HgCommand command = new HgCommand("qfold", //$NON-NLS-1$ "Invoking qfold", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); File messageFile = null; command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (keep) { command.addOptions("--keep"); //$NON-NLS-1$ } if (message != null && message.length() > 0) { messageFile = HgCommitClient.addMessage(command, message); } for (String patch : patches) { command.addOptions(patch); } try { return command.executeToString(); } finally { HgCommitClient.deleteMessage(messageFile); } } public static boolean isPatchConflict(HgException e) { return e.getMessage().contains("patch failed, unable to continue"); } } HgQHeaderClient.java000066400000000000000000000031561173713500500365250ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Philip Graf implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * Client for {@code qheader}. * * @author Philip Graf */ public class HgQHeaderClient extends AbstractClient { /** * Returns the header of the topmost patch. This method calls {@code hg qheader} without a * specified patch and returns the result. * * @param resource * @return The header of the topmost patch. Never returns {@code null}. * @throws HgException * Thrown when the Hg command cannot be executed. */ public static String getHeader(HgRoot root) throws HgException { AbstractShellCommand command = new HgCommand("qheader", "Invoking qheader", root, false); //$NON-NLS-1$ command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ return command.executeToString().trim(); } } HgQImportClient.java000066400000000000000000000054521173713500500366100ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Philip Graf Fix for importing from a patch file *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; /** * @author bastian * */ public class HgQImportClient extends AbstractClient { /** * Import a changeset with a specific name */ public static String qimport(HgRoot root, boolean force, ChangeSet changeset, String name) throws HgException { return qimport(root, force, false, new ChangeSet[] { changeset }, null, name); } public static String qimport(HgRoot root, boolean force, boolean existing, ChangeSet[] changesets, IPath patchFile) throws HgException { return qimport(root, force, existing, changesets, patchFile, null); } private static String qimport(HgRoot root, boolean force, boolean existing, ChangeSet[] changesets, IPath patchFile, String name) throws HgException { Assert.isNotNull(root); AbstractShellCommand command = new HgCommand("qimport", //$NON-NLS-1$ "Invoking qimport", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.setUsePreferenceTimeout(MercurialPreferenceConstants.CLONE_TIMEOUT); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (force) { command.addOptions("--force"); //$NON-NLS-1$ } if (name != null) { command.addOptions("--name", name); //$NON-NLS-1$ } command.addOptions("--git"); //$NON-NLS-1$ if (changesets != null && changesets.length>0) { command.addOptions("--rev", changesets[changesets.length-1].getChangeset()+ ":" +changesets[0].getChangeset()); //$NON-NLS-1$ //$NON-NLS-2$ } else { Assert.isNotNull(patchFile); if (existing) { command.addOptions("--existing"); //$NON-NLS-1$ } command.addOptions(patchFile.toOSString()); } return command.executeToString(); } } HgQInitClient.java000066400000000000000000000025161173713500500362370ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; /** * @author bastian * */ public class HgQInitClient extends AbstractClient { public static String init(IResource resource, boolean repository) throws HgException { AbstractShellCommand command = new HgCommand("qinit", "Invoking qinit", resource, true); //$NON-NLS-1$ command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (repository) { command.addOptions("--create-repo"); //$NON-NLS-1$ } return command.executeToString(); } } HgQNewClient.java000066400000000000000000000054721173713500500360710ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import java.io.File; import java.util.List; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.commands.HgCommitClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian * */ public class HgQNewClient extends AbstractClient { public static String createNewPatch(HgRoot root, String commitMessage, String user, String date, String patchName) throws HgException { return createNewPatch(root, commitMessage, null, user, date, patchName, true); } public static String createNewPatch(HgRoot root, String commitMessage, List resources, String user, String date, String patchName) throws HgException { return createNewPatch(root, commitMessage, resources, user, date, patchName, false); } private static String createNewPatch(HgRoot root, String commitMessage, List resources, String user, String date, String patchName, boolean all) throws HgException { HgCommand command = new HgCommand("qnew", //$NON-NLS-1$ "Invoking qnew", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); File messageFile = null; command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (commitMessage != null && commitMessage.length() > 0) { messageFile = HgCommitClient.addMessage(command, commitMessage); } command.addOptions("--git"); //$NON-NLS-1$ if (user != null && user.length() > 0) { command.addOptions("--user", user); //$NON-NLS-1$ } else { command.addOptions("--currentuser"); //$NON-NLS-1$ } if (date != null && date.length() > 0) { command.addOptions("--date", date); //$NON-NLS-1$ } else { command.addOptions("--currentdate"); //$NON-NLS-1$ } if (!all) { if (resources.isEmpty()) { command.addOptions("--exclude", "*"); } else { command.addFiles(resources); } } command.addOptions(patchName); try { return command.executeToString(); } finally { HgCommitClient.deleteMessage(messageFile); } } } HgQPopClient.java000066400000000000000000000041201173713500500360630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import org.eclipse.core.runtime.Assert; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian */ public class HgQPopClient extends AbstractClient { public static String popAll(HgRoot root, boolean force) throws HgException { Assert.isNotNull(root); AbstractShellCommand command = new HgCommand("qpop", //$NON-NLS-1$ "Invoking qpop", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ command.addOptions("-a"); //$NON-NLS-1$ if (force) { command.addOptions("--force"); //$NON-NLS-1$ } return command.executeToString(); } public static String pop(HgRoot root, boolean force, String patchName) throws HgException { AbstractShellCommand command = new HgCommand("qpop", //$NON-NLS-1$ "Invoking qpop", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (force) { command.addOptions("--force"); //$NON-NLS-1$ } if (!"".equals(patchName)) { //$NON-NLS-1$ command.addOptions(patchName); } return command.executeToString(); } } HgQPushClient.java000066400000000000000000000050721173713500500362530ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian * */ public class HgQPushClient extends AbstractClient { public static String pushAll(HgRoot root, boolean force) throws HgException { AbstractShellCommand command = new HgCommand("qpush", //$NON-NLS-1$ "Invoking qpush", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ command.addOptions("-a"); //$NON-NLS-1$ if (force) { command.addOptions("--force"); //$NON-NLS-1$ } return command.executeToString(); } public static String push(HgRoot root, boolean force, String patchName) throws HgException { AbstractShellCommand command = new HgCommand("qpush", //$NON-NLS-1$ "Invoking qpush", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (force) { command.addOptions("--force"); //$NON-NLS-1$ } if (!"".equals(patchName)) { //$NON-NLS-1$ command.addOptions(patchName); } return command.executeToString(); } public static boolean isPatchApplyConflict(HgException e) { // Mercurial 2.0: // applying 3489.diff // patching file src/file1.text // Hunk #1 FAILED at 8 // 1 out of 1 hunks FAILED -- saving rejects to file src/file1.text.rej // patch failed, unable to continue (try -v) // patch failed, rejects left in working dir // errors during apply, please fix and refresh 3489.diff. return e.getMessage().contains("patch failed, rejects left in working dir") || HgPatchClient.isPatchImportConflict(e); } } HgQRefreshClient.java000066400000000000000000000061631173713500500367340ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import java.io.File; import java.util.List; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.commands.HgCommitClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian * */ public class HgQRefreshClient extends AbstractClient { public static String refresh(HgRoot root, boolean shortFlag, List files, String message, boolean currentDate) throws HgException { HgCommand command = new HgCommand("qrefresh", //$NON-NLS-1$ "Invoking qrefresh", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (shortFlag) { command.addOptions("-s"); //$NON-NLS-1$ } File messageFile = null; if (message != null && message.length() > 0) { messageFile = HgCommitClient.addMessage(command, message); } if (currentDate) { command.addOptions("--currentdate"); } command.addFiles(files); try { return command.executeToString(); } finally { HgCommitClient.deleteMessage(messageFile); } } public static String refresh(HgRoot root, String commitMessage, List resources, String user, String date) throws HgException { HgCommand command = new HgCommand("qrefresh", //$NON-NLS-1$ "Invoking qrefresh", root, true); command.setExecutionRule(new AbstractShellCommand.ExclusiveExecutionRule(root)); File messageFile = null; command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ if (commitMessage != null && commitMessage.length() > 0) { messageFile = HgCommitClient.addMessage(command, commitMessage); } command.addOptions("--git"); //$NON-NLS-1$ if (user != null && user.length() > 0) { command.addOptions("--user", user); //$NON-NLS-1$ } else { command.addOptions("--currentuser"); //$NON-NLS-1$ } if (date != null && date.length() > 0) { command.addOptions("--date", date); //$NON-NLS-1$ } else { command.addOptions("--currentdate"); //$NON-NLS-1$ } // TODO: this will refresh dirty files in the patch regardless of whether they're selected command.addOptions("-s"); command.addFiles(resources); try { return command.executeToString(); } finally { HgCommitClient.deleteMessage(messageFile); } } } HgQSeriesClient.java000066400000000000000000000052341173713500500365660ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/extensions/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands.extensions.mq; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.AbstractShellCommand; import com.vectrace.MercurialEclipse.commands.HgCommand; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Patch; /** * @author bastian * */ public class HgQSeriesClient extends AbstractClient { public static List getPatchesInSeries(HgRoot root) throws HgException { AbstractShellCommand command = new HgCommand("qseries", //$NON-NLS-1$ "Invoking qseries", root, true); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ command.addOptions("-v"); //$NON-NLS-1$ command.addOptions("--summary"); //$NON-NLS-1$ return parse(command.executeToString()); } protected static List parse(String executeToString) { List list = new ArrayList(); if (executeToString != null && executeToString.indexOf("\n") >= 0) { //$NON-NLS-1$ String[] patches = executeToString.split("\n"); //$NON-NLS-1$ int i = 1; for (String string : patches) { String[] components = string.split(":", 2); //$NON-NLS-1$ String[] patchData = components[0].trim().split(" ", 3); //$NON-NLS-1$ Patch p = new Patch(); p.setIndex(i++); p.setApplied("A".equals(patchData[1])); //$NON-NLS-1$ p.setName(patchData[2].trim()); if (components.length>1) { String summary = components[1].trim(); p.setSummary(summary); } list.add(p); } } return list; } public static List getPatchesNotInSeries(IResource resource) throws HgException { AbstractShellCommand command = new HgCommand("qseries", //$NON-NLS-1$ "Invoking qseries", resource, true); command.addOptions("--config", "extensions.hgext.mq="); //$NON-NLS-1$ //$NON-NLS-2$ command.addOptions("--summary", "--missing"); //$NON-NLS-1$ //$NON-NLS-2$ return parse(command.executeToString()); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/commands/messages.properties000066400000000000000000000017621173713500500341240ustar00rootroot00000000000000HgAddClient.addingResourcesFrom=Adding resources from HgClients.error.notInitializedWithConfig=HgClient has not been initialized with a configuration HgClients.error.notInitializedWithConsole=HgClients has not been initialized with a console HgCommitClient.commitJob.committing=Committing resources from HgIgnoreClient.failedToAddEntry=Failed to add an entry to .hgignore HgIgnoreClient.failedToAddHgIgnore=Failed to add an entry to .hgignore HgIgnoreClient.failedToCloseHgIgnore=Failed to close file .hgignore HgLogClient.parseException=Parse exception: ' HgRemoveClient.removeResource.1=Removing HgRemoveClient.removeResource.2=\ from repository HgRenameClient.moving.1=Moving HgRenameClient.moving.2=\ to HgRootClient.error.cannotGetCanonicalPath=Cannot get cannonical path for file HgRootClient.error.noRoot=\ does not have a hg root HgServeClient.serveJob.name=Controller thread for serving repository HgServeClient.serverThread.name=Server thread for: HgTagClient.parseException=Parse exception: ' eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/compare/000077500000000000000000000000001173713500500300165ustar00rootroot00000000000000HgCompareEditorInput.java000066400000000000000000000152461173713500500346460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/compare/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.compare; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.CompareNavigator; import org.eclipse.compare.ICompareNavigator; import org.eclipse.compare.INavigatable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.internal.ui.synchronize.SynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SyncInfoCompareInput; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.synchronize.cs.ChangesetGroup; public class HgCompareEditorInput extends CompareEditorInput { private static final HgDifferencer DIFFERENCER = new HgDifferencer(); private final RevisionNode left; private final RevisionNode ancestor; private final RevisionNode right; private final ISynchronizePageConfiguration syncConfig; /** * Does either a 2-way or 3-way compare, depending on if one is an ancestor * of the other. If they are divergent, then it finds the common ancestor * and does 3-way compare. * @param syncConfig */ public HgCompareEditorInput(CompareConfiguration configuration, RevisionNode left, RevisionNode right, RevisionNode ancestor, ISynchronizePageConfiguration syncConfig) { this(configuration, left, right, ancestor, true, syncConfig); setTitle("Compare " + left.getName()); } private HgCompareEditorInput(CompareConfiguration configuration, RevisionNode left, RevisionNode right, RevisionNode ancestor, boolean bLeftEditable, ISynchronizePageConfiguration syncConfig) { super(configuration); this.syncConfig = syncConfig; this.left = left; this.ancestor = ancestor; this.right = right; configuration.setLeftLabel(getLabel(left)); configuration.setLeftEditable(bLeftEditable); configuration.setRightLabel(getLabel(right)); configuration.setRightEditable(false); configuration.setAncestorLabel(getLabel(ancestor)); } private static String getLabel(RevisionNode node) { if (node != null) { return node.getLabel(); } return ""; } @Override protected Object prepareInput(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { byte[] content = null; RevisionNode parent = ancestor; if(parent != null){ content = parent.getContent(); } if(content == null || content.length == 0){ // See issue 11149: sometimes we fail to determine the ancestor version, but we // see it too late as the editor is opened with an "empty" parent node. // In such case ENTIRE file is considered as a huge merge conflict. // So as quick and dirty workaround we avoid using 3-way merge if parent content is unknown parent = null; } return DIFFERENCER.findDifferences(parent != null, monitor, null, parent, left, right); } @Override public String getOKButtonLabel() { if (getCompareConfiguration().isLeftEditable() || getCompareConfiguration().isRightEditable()) { return "Save Changes"; } return super.getOKButtonLabel(); } /** * Overriden to allow navigation through multiple changes in the sync view via shortcuts * "Ctrl + ." (Navigate->Next) or "Ctrl + ," (Navigate->Previous). * @see SyncInfoCompareInput */ @Override public synchronized ICompareNavigator getNavigator() { CompareNavigator navigator = (CompareNavigator) super.getNavigator(); if (syncConfig != null) { CompareNavigator nav = (CompareNavigator) syncConfig.getProperty( SynchronizePageConfiguration.P_NAVIGATOR); return new SyncNavigatorWrapper(navigator, nav); } return navigator; } private class SyncNavigatorWrapper extends CompareNavigator { private final CompareNavigator textDfiffDelegate; private final CompareNavigator syncViewDelegate; public SyncNavigatorWrapper(CompareNavigator textDfiffDelegate, CompareNavigator syncViewDelegate) { this.textDfiffDelegate = textDfiffDelegate; this.syncViewDelegate = syncViewDelegate; } @Override public boolean selectChange(boolean next) { boolean endReached = textDfiffDelegate.selectChange(next); if(endReached && syncViewDelegate != null && isSelectedInSynchronizeView()){ // forward navigation to the sync view return syncViewDelegate.selectChange(next); } return endReached; } @Override // This method won't be used by our implementation protected INavigatable[] getNavigatables() { return new INavigatable[0]; } @Override public boolean hasChange(boolean next) { return (textDfiffDelegate.hasChange(next) || syncViewDelegate.hasChange(next)); } } private boolean isSelectedInSynchronizeView() { if (syncConfig == null) { return false; } ISelection s = syncConfig.getSite().getSelectionProvider().getSelection(); if (!(s instanceof IStructuredSelection)) { return false; } IStructuredSelection ss = (IStructuredSelection) s; Object element = ss.getFirstElement(); if (element instanceof FileFromChangeSet || element instanceof ChangesetGroup) { return true; } return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((ancestor == null) ? 0 : ancestor.hashCode()); result = prime * result + ((left == null) ? 0 : left.hashCode()); result = prime * result + ((right == null) ? 0 : right.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof HgCompareEditorInput)) { return false; } HgCompareEditorInput other = (HgCompareEditorInput) obj; if (ancestor == null) { if (other.ancestor != null) { return false; } } else if (!ancestor.equals(other.ancestor)) { return false; } if (left == null) { if (other.left != null) { return false; } } else if (!left.equals(other.left)) { return false; } if (right == null) { if (other.right != null) { return false; } } else if (!right.equals(other.right)) { return false; } return true; } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/compare/HgDifferencer.java000066400000000000000000000056751173713500500333710ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ge.zhong implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.compare; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.eclipse.compare.ITypedElement; import org.eclipse.compare.structuremergeviewer.DiffNode; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.compare.structuremergeviewer.IDiffContainer; /** * Compare sparse trees for performance */ public class HgDifferencer extends Differencer { @Override protected Object visit(Object data, int result, Object ancestor, Object left, Object right) { DiffNode node = null; Object[] ancestorChildren = getChildren(ancestor); Object[] rightChildren = getChildren(right); Object[] leftChildren = getChildren(left); if ((left == null && rightChildren != null && rightChildren.length > 0) || (right == null && leftChildren != null && leftChildren.length > 0)) { node = new DiffNode((IDiffContainer) data, Differencer.CHANGE, (ITypedElement) ancestor, (ITypedElement) left, (ITypedElement) right); Set allSet = new HashSet(20); Map ancestorSet = null; Map rightSet = null; Map leftSet = null; if (ancestorChildren != null) { ancestorSet = new HashMap(10); for (int i = 0; i < ancestorChildren.length; i++) { Object ancestorChild = ancestorChildren[i]; ancestorSet.put(ancestorChild, ancestorChild); allSet.add(ancestorChild); } } if (rightChildren != null) { rightSet = new HashMap(10); for (int i = 0; i < rightChildren.length; i++) { Object rightChild = rightChildren[i]; rightSet.put(rightChild, rightChild); allSet.add(rightChild); } } if (leftChildren != null) { leftSet = new HashMap(10); for (int i = 0; i < leftChildren.length; i++) { Object leftChild = leftChildren[i]; leftSet.put(leftChild, leftChild); allSet.add(leftChild); } } Iterator e = allSet.iterator(); while (e.hasNext()) { Object keyChild = e.next(); Object ancestorChild = ancestorSet != null ? ancestorSet.get(keyChild) : null; Object leftChild = leftSet != null ? leftSet.get(keyChild) : null; Object rightChild = rightSet != null ? rightSet.get(keyChild) : null; visit(node, result, ancestorChild, leftChild, rightChild); } } else { node = new DiffNode((IDiffContainer) data, result, (ITypedElement) ancestor, (ITypedElement) left, (ITypedElement) right); } return node; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/compare/RevisionNode.java000066400000000000000000000136041173713500500332710ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.compare; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.eclipse.compare.CompareUI; import org.eclipse.compare.IEditableContent; import org.eclipse.compare.IEditableContentExtension; import org.eclipse.compare.IEncodedStreamContentAccessor; import org.eclipse.compare.IModificationDate; import org.eclipse.compare.ITypedElement; import org.eclipse.compare.structuremergeviewer.IStructureComparator; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IStorage; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgResource; import com.vectrace.MercurialEclipse.model.IHgFolder; import com.vectrace.MercurialEclipse.model.IHgResource; public class RevisionNode implements IEncodedStreamContentAccessor, IStructureComparator, ITypedElement, IEditableContent, IModificationDate, IEditableContentExtension { private final IHgResource resource; private List children; public RevisionNode(IHgResource resource) { this.resource = resource; } public IHgResource getHgResource() { return resource; } /** * @see org.eclipse.compare.ITypedElement#getName() */ public String getName() { if (resource != null) { return resource.getName(); } return null; } public String getLabel() { String name = resource.getName(); if (resource.getChangeSet() != null) { name = name + " [" + resource.getChangeSet().toString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } return name; } public InputStream getContents() throws CoreException { if (resource instanceof IStorage) { return ((IStorage) resource).getContents(); } return null; } public byte[] getContent() { if (resource instanceof HgResource) { return ((HgResource) resource).getContent(); } return null; } @Override public boolean equals(Object other) { if (other instanceof RevisionNode) { return this.resource.equals(((RevisionNode) other).getHgResource()); } return false; } @Override public int hashCode() { return resource.hashCode(); } public boolean isWorkingCopy() { return resource.getResource() != null; } /** * @see org.eclipse.compare.IEditableContentExtension#isReadOnly() */ public boolean isReadOnly() { return resource.isReadOnly(); } /** * @see org.eclipse.compare.IEditableContentExtension#validateEdit(org.eclipse.swt.widgets.Shell) */ public IStatus validateEdit(Shell shell) { IResource res = resource.getResource(); if (res instanceof IFile) { // See org.eclipse.compare.ResourceNode.validateEdit(Shell) if (isReadOnly()) { return ResourcesPlugin.getWorkspace().validateEdit(new IFile[] { (IFile)res}, shell); } return Status.OK_STATUS; } // Not in workspace return Status.CANCEL_STATUS; } /** * @see org.eclipse.compare.IEditableContent#isEditable() */ public boolean isEditable() { return !isReadOnly(); } /** * @see org.eclipse.compare.IEditableContent#replace(org.eclipse.compare.ITypedElement, org.eclipse.compare.ITypedElement) */ public ITypedElement replace(ITypedElement dest, ITypedElement src) { // TODO Auto-generated method stub return null; } /** * @see org.eclipse.compare.ITypedElement#getImage() */ public Image getImage() { return CompareUI.getImage(getType()); } /** * @see org.eclipse.compare.ITypedElement#getType() */ public String getType() { if (resource instanceof IHgFolder) { return ITypedElement.FOLDER_TYPE; } if (resource != null) { String s= resource.getFileExtension(); if (s != null) { return s; } } return ITypedElement.UNKNOWN_TYPE; } /** * @see org.eclipse.compare.structuremergeviewer.IStructureComparator#getChildren() */ public Object[] getChildren() { if (children == null) { children = new ArrayList(); if (resource instanceof IHgFolder) { IHgResource[] members = ((IHgFolder) resource).members(); for (int i = 0; i < members.length; i++) { IStructureComparator child = new RevisionNode(members[i]); children.add(child); } } } return children.toArray(); } /** * @see org.eclipse.compare.IEncodedStreamContentAccessor#getCharset() */ public String getCharset() throws CoreException { return resource.getHgRoot().getEncoding(); } /** * @see org.eclipse.compare.IModificationDate#getModificationDate() */ public long getModificationDate() { IResource res = resource.getResource(); if (res != null) { return res.getLocalTimeStamp(); } // Future: get timestamp from commit time? return 0; } /** * @see org.eclipse.compare.IEditableContent#setContent(byte[]) */ public void setContent(byte[] newContent) { if (resource.getResource() instanceof IFile) { InputStream is = new ByteArrayInputStream(newContent); try { // update cache ((HgResource) resource).setContent(newContent); // update local file ((IFile) resource.getResource()).setContents(is, true, true, null); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/compare/TagComparator.java000066400000000000000000000024421173713500500334260ustar00rootroot00000000000000/******************************************************************************* * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package com.vectrace.MercurialEclipse.compare; import java.util.Comparator; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.model.Tag; /** * Thsi class can be used to compare Tags by names. * * @author Zsolt Koppany * @version $Id$ */ public class TagComparator implements Comparator { private static final String TIP = HgRevision.TIP.getChangeset(); public int compare(Tag tag1, Tag tag2) { /* "tip" must be always the first in the collection */ if (tag1 == null || tag1.getName() == null || TIP.equals(tag1.getName())) { return -1; } if (TIP.equals(tag2.getName())) { return 1; } // sort by name int cmp = tag1.getName().compareToIgnoreCase(tag2.getName()); if (cmp == 0) { // Check it case sensitive cmp = tag1.getName().compareTo(tag2.getName()); } return cmp; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/000077500000000000000000000000001173713500500300125ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/BookmarkDialog.java000066400000000000000000000210651173713500500335460ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.TrayDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.extensions.HgBookmarkClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.BookmarkTable; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author bastian */ public class BookmarkDialog extends TrayDialog { private final HgRoot hgRoot; private ChangesetTable csTable; private Text bmNameTextBox; private Button renameCheckBox; private BookmarkTable bookmarkTable; private Text newBmNameTextBox; private Button deleteCheckBox; private boolean modifyTab; private Label renameLabel; public BookmarkDialog(Shell parentShell, HgRoot hgRoot) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); this.hgRoot = hgRoot; } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.getString("BookmarkDialog.shell.text")); //$NON-NLS-1$ } @Override protected IDialogSettings getDialogBoundsSettings() { IDialogSettings dialogSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); String sectionName = getClass().getSimpleName(); IDialogSettings section = dialogSettings.getSection(sectionName); if (section == null) { dialogSettings.addNewSection(sectionName); } return section; } @Override protected Control createDialogArea(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 1); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); TabFolder tabFolder = new TabFolder(composite, SWT.FILL); tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); createCreateTabItem(tabFolder); createModifyTabItem(tabFolder); return composite; } protected TabItem createCreateTabItem(TabFolder folder) { // setup control TabItem item = new TabItem(folder, folder.getStyle()); item.setText(Messages.getString("BookmarkDialog.createTab.name")); //$NON-NLS-1$ Composite c = SWTWidgetHelper.createComposite(folder, 2); GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); c.setLayoutData(layoutData); item.setControl(c); Listener tabSl = new Listener() { public void handleEvent(Event event) { if (event.type == SWT.Show) { modifyTab = false; } } }; item.addListener(SWT.Show, tabSl); // create widgets Group tipGroup = SWTWidgetHelper.createGroup(c, Messages.getString("BookmarkDialog.createGroup.label")); //$NON-NLS-1$ SWTWidgetHelper.createLabel(tipGroup, Messages.getString("BookmarkDialog.bookmarkName")); //$NON-NLS-1$ this.bmNameTextBox = SWTWidgetHelper.createTextField(tipGroup); Group revGroup = SWTWidgetHelper.createGroup(c, Messages.getString("BookmarkDialog.selectRevision")); //$NON-NLS-1$ revGroup.setLayoutData(layoutData); this.csTable = new ChangesetTable(revGroup, hgRoot); csTable.setLayoutData(layoutData); this.csTable.setEnabled(true); SelectionListener sl = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { modifyTab = false; } }; csTable.addSelectionListener(sl); return item; } protected TabItem createModifyTabItem(TabFolder folder) { // setup control TabItem item = new TabItem(folder, folder.getStyle()); item.setText(Messages.getString("BookmarkDialog.modifyTab.name")); //$NON-NLS-1$ Composite c = SWTWidgetHelper.createComposite(folder, 2); GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); c.setLayoutData(layoutData); item.setControl(c); Listener tabSl = new Listener() { public void handleEvent(Event event) { if (event.type == SWT.Show) { modifyTab = true; } } }; item.addListener(SWT.Show, tabSl); // create widgets Group selGroup = SWTWidgetHelper.createGroup(c, Messages.getString("BookmarkDialog.selectBookmark")); //$NON-NLS-1$ selGroup.setLayoutData(layoutData); bookmarkTable = new BookmarkTable(selGroup); bookmarkTable.setLayoutData(layoutData); bookmarkTable.updateTable(hgRoot); SelectionListener sl = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { modifyTab = true; } }; this.bookmarkTable.addSelectionListener(sl); Group renameGroup = SWTWidgetHelper.createGroup(c, Messages.getString("BookmarkDialog.renameGroup.label")); //$NON-NLS-1$ this.setDeleteCheckBox(SWTWidgetHelper.createCheckBox(renameGroup, Messages.getString("BookmarkDialog.option.delete"))); //$NON-NLS-1$ SelectionListener delSl = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { boolean selection = deleteCheckBox.getSelection(); if (selection) { renameCheckBox.setSelection(false); renameLabel.setEnabled(false); bmNameTextBox.setEnabled(false); modifyTab = true; } } }; this.deleteCheckBox.addSelectionListener(delSl); this.renameCheckBox = SWTWidgetHelper.createCheckBox(renameGroup, Messages.getString("BookmarkDialog.option.rename")); //$NON-NLS-1$ renameLabel = SWTWidgetHelper.createLabel(renameGroup, Messages.getString("BookmarkDialog.newName")); //$NON-NLS-1$ this.newBmNameTextBox = SWTWidgetHelper.createTextField(renameGroup); this.newBmNameTextBox.setEnabled(false); renameLabel.setEnabled(false); SelectionListener renSl = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { boolean selection = renameCheckBox.getSelection(); if (selection) { deleteCheckBox.setSelection(false); modifyTab = true; } renameLabel.setEnabled(selection); newBmNameTextBox.setEnabled(selection); } }; renameCheckBox.addSelectionListener(renSl); return item; } @Override protected void okPressed() { try { if (!modifyTab) { // create new bookmark String targetRev = HgRevision.TIP.getChangeset(); if (csTable.getSelection() != null) { targetRev = csTable.getSelection().getChangeset(); } HgBookmarkClient.create(hgRoot, bmNameTextBox.getText(), targetRev); } else { if (renameCheckBox.getSelection()) { HgBookmarkClient.rename(hgRoot, bookmarkTable.getSelection().getName(), newBmNameTextBox.getText()); } else if (deleteCheckBox.getSelection()) { HgBookmarkClient.delete(hgRoot, bookmarkTable.getSelection().getName()); } } } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } super.okPressed(); } public ChangesetTable getCsTable() { return csTable; } public Text getBmNameTextBox() { return bmNameTextBox; } public Button getRenameCheckBox() { return renameCheckBox; } public BookmarkTable getBookmarkTable() { return bookmarkTable; } public void setDeleteCheckBox(Button deleteCheckBox) { this.deleteCheckBox = deleteCheckBox; } public Button getDeleteCheckBox() { return deleteCheckBox; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/CommitDialog.java000066400000000000000000001001031173713500500332200ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eclipse.org - see CommitWizardCommitPage * Software Balm Consulting Inc (Peter Hunnisett ) - implementation * Bastian Doetsch - Added spellchecking and some other stuff * StefanC - many updates * Zingo Andersen - some updates * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.TextEvent; import org.eclipse.jface.text.source.AnnotationModel; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.ProgressMonitorPart; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Sash; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgAddClient; import com.vectrace.MercurialEclipse.commands.HgCommitClient; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.commands.HgRemoveClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.commands.extensions.HgStripClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQAppliedClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQDeleteClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQFinishClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQFoldClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQImportClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQNewClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQPopClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQPushClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQRefreshClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.SwitchHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.mylyn.MylynFacadeFactory; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.team.ActionRevert; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.ui.ChangesetInfoTray; import com.vectrace.MercurialEclipse.ui.CommitFilesChooser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * A commit dialog box allowing choosing of what files to commit and a commit message for those * files. Untracked files may also be chosen. */ public class CommitDialog extends TitleAreaDialog { public static final String FILE_MODIFIED = Messages.getString("CommitDialog.modified"); //$NON-NLS-1$ public static final String FILE_ADDED = Messages.getString("CommitDialog.added"); //$NON-NLS-1$ public static final String FILE_REMOVED = Messages.getString("CommitDialog.removed"); //$NON-NLS-1$ public static final String FILE_UNTRACKED = Messages.getString("CommitDialog.untracked"); //$NON-NLS-1$ public static final String FILE_DELETED = Messages.getString("CommitDialog.deletedInWorkspace"); //$NON-NLS-1$ public static final String FILE_CLEAN = Messages.getString("CommitDialog.clean"); //$NON-NLS-1$ private static final String DEFAULT_COMMIT_MESSAGE = Messages .getString("CommitDialog.defaultCommitMessage"); //$NON-NLS-1$ private ISourceViewer commitTextBox; protected CommitFilesChooser commitFilesList; private List resourcesToAdd; private List resourcesToCommit; private List resourcesToRemove; private final IDocument commitTextDocument; private SourceViewerDecorationSupport decorationSupport; private final List inResources; private Text userTextField; private String user; private Button revertCheckBox; protected final HgRoot root; private String commitResult; private Button closeBranchCheckBox; private Button amendCheckbox; private ChangeSet currentChangeset; private ProgressMonitorPart monitor; private Sash sash; private ChangesetInfoTray tray; private Label leftSeparator; private Label rightSeparator; private Control trayControl; protected Options options; public static class Options { public boolean showDiff = true; public boolean showAmend = true; public boolean showCloseBranch = true; public boolean showRevert = true; public boolean filesSelectable = true; public String defaultCommitMessage = DEFAULT_COMMIT_MESSAGE; public boolean showCommitMessage = true; public boolean allowEmptyCommit = false; /** optional to use if no files are specified and allowEmptyCommit is true */ public HgRoot hgRoot = null; } /** * @param hgRoot * non null * @param resources * might be null */ public CommitDialog(Shell shell, HgRoot hgRoot, List resources) { super(shell); Assert.isNotNull(hgRoot); this.root = hgRoot; setShellStyle(getShellStyle() | SWT.RESIZE | SWT.TITLE); options = new Options(); setBlockOnOpen(false); inResources = resources; commitTextDocument = new Document(); } public String getCommitMessage() { return commitTextDocument.get(); } public List getResourcesToCommit() { return resourcesToCommit; } public List getResourcesToAdd() { return resourcesToAdd; } @Override protected IDialogSettings getDialogBoundsSettings() { IDialogSettings dialogSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); String sectionName = getClass().getSimpleName(); IDialogSettings section = dialogSettings.getSection(sectionName); if (section == null) { dialogSettings.addNewSection(sectionName); } return section; } /** * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsStrategy() */ @Override protected int getDialogBoundsStrategy() { int strategy = super.getDialogBoundsStrategy(); // When amend is set it changes the dialog size if (trayControl != null) { strategy &= ~DIALOG_PERSISTSIZE; } return strategy; } @Override protected Control createDialogArea(Composite parent) { Composite container = SWTWidgetHelper.createComposite(parent, 1); GridData gd = SWTWidgetHelper.getFillGD(400); gd.minimumWidth = 500; container.setLayoutData(gd); super.createDialogArea(parent); container.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { if (e.character == SWT.CR && e.stateMask == SWT.MOD1) { okPressed(); e.doit = false; } } public void keyPressed(KeyEvent e) { } }); createCommitTextBox(container); createOldCommitCombo(container); createUserCommitCombo(container); createCloseBranchCheckBox(container); createAmendCheckBox(container); createRevertCheckBox(container); commitFilesList = createFilesList(container); getShell().setText(Messages.getString("CommitDialog.window.title")); //$NON-NLS-1$ setTitle(Messages.getString("CommitDialog.title")); //$NON-NLS-1$"; monitor = new ProgressMonitorPart(container, null); monitor.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); monitor.setVisible(false); return container; } @Override protected Control createContents(Composite parent) { Control control = super.createContents(parent); final String initialCommitMessage = getInitialCommitMessage(); setCommitMessage(initialCommitMessage); if (commitTextBox != null) { commitTextBox.getTextWidget().setFocus(); commitTextBox.getTextWidget().selectAll(); } return control; } protected String getInitialCommitMessage() { return MylynFacadeFactory.getMylynFacade() .getCurrentTaskComment( inResources == null ? null : inResources.toArray(new IResource[0])); } private boolean isDefaultCommitMessage() { String message = commitTextBox.getDocument().get(); return StringUtils.isEmpty(message) || DEFAULT_COMMIT_MESSAGE.equals(message); } private void validateControls() { if (isDefaultCommitMessage()) { setErrorMessage(Messages.getString("CommitDialog.commitMessageRequired")); // "; getButton(IDialogConstants.OK_ID).setEnabled(false); } else if (commitFilesList.getCheckedResources().size() == 0 && !options.allowEmptyCommit && commitFilesList.isSelectable() && (amendCheckbox == null || !amendCheckbox.getSelection()) && !isCloseBranchSelected()) { setErrorMessage(Messages.getString("CommitDialog.noResourcesSelected")); // "; getButton(IDialogConstants.OK_ID).setEnabled(false); } else { setErrorMessage(null); // "; setMessage(Messages.getString("CommitDialog.readyToCommit")); // "; getButton(IDialogConstants.OK_ID).setEnabled(true); } } private void createRevertCheckBox(Composite container) { if(!options.showRevert){ return; } revertCheckBox = SWTWidgetHelper.createCheckBox(container, Messages .getString("CommitDialog.revertCheckBoxLabel.revertUncheckedResources")); //$NON-NLS-1$ } private void createCloseBranchCheckBox(Composite container) { if(!options.showCloseBranch){ return; } closeBranchCheckBox = SWTWidgetHelper.createCheckBox(container, Messages .getString("CommitDialog.closeBranch")); closeBranchCheckBox.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { validateControls(); if (closeBranchCheckBox.getSelection() && isDefaultCommitMessage()) { commitTextDocument.set(Messages.getString("CommitDialog.closingBranch", MercurialTeamProvider.getCurrentBranch(root))); } } public void widgetDefaultSelected(SelectionEvent e) { } }); } private void createAmendCheckBox(Composite container) { if(!options.showAmend){ return; } try { currentChangeset = LocalChangesetCache.getInstance().getChangesetForRoot(root); } catch (HgException e) { MercurialEclipsePlugin.logError(e); setErrorMessage(e.getLocalizedMessage()); } if (currentChangeset == null){ return; } String branch = MercurialTeamProvider.getCurrentBranch(root); String label = Messages.getString("CommitDialog.amendCurrentChangeset1") + currentChangeset.getChangesetIndex() + ":" + currentChangeset.getNodeShort() + "@" + branch + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ amendCheckbox = SWTWidgetHelper.createCheckBox(container, label); amendCheckbox.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { if (amendCheckbox.getSelection() && currentChangeset != null) { try { openSash(); } catch (HgException e1) { setErrorMessage("Cannot amend."); closeSash(); amendCheckbox.setSelection(false); amendCheckbox.setEnabled(false); } } else { closeSash(); } validateControls(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); } protected CommitFilesChooser createFilesList(Composite container) { SWTWidgetHelper.createLabel(container, Messages.getString("CommitDialog.selectFiles")); CommitFilesChooser chooser = new CommitFilesChooser(container, areFilesSelectable(), inResources, true, true, false); chooser.addStateListener(new Listener() { public void handleEvent(Event event) { validateControls(); } }); IResource[] mylynTaskResources = MylynFacadeFactory.getMylynFacade() .getCurrentTaskResources(); if (mylynTaskResources != null) { chooser.setSelectedResources(Arrays.asList(mylynTaskResources)); } return chooser; } private boolean areFilesSelectable() { return options.filesSelectable; } private void createUserCommitCombo(Composite container) { Composite comp = SWTWidgetHelper.createComposite(container, 2); SWTWidgetHelper.createLabel(comp, Messages.getString("CommitDialog.userLabel.text")); userTextField = SWTWidgetHelper.createTextField(comp); user = getInitialCommitUserName(); userTextField.setText(user); } protected String getInitialCommitUserName() { return HgCommitMessageManager.getDefaultCommitName(root); } private void createCommitTextBox(Composite container) { if(!options.showCommitMessage){ return; } setMessage(Messages.getString("CommitDialog.commitTextLabel.text")); commitTextBox = new SourceViewer(container, null, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.WRAP); commitTextBox.setEditable(true); commitTextBox.getTextWidget().setLayoutData(SWTWidgetHelper.getFillGD(100)); // set up spell-check annotations decorationSupport = new SourceViewerDecorationSupport(commitTextBox, null, new DefaultMarkerAnnotationAccess(), EditorsUI.getSharedTextColors()); AnnotationPreference pref = EditorsUI.getAnnotationPreferenceLookup() .getAnnotationPreference(SpellingAnnotation.TYPE); decorationSupport.setAnnotationPreference(pref); decorationSupport.install(EditorsUI.getPreferenceStore()); commitTextBox.configure(new TextSourceViewerConfiguration(EditorsUI.getPreferenceStore())); AnnotationModel annotationModel = new AnnotationModel(); commitTextBox.setDocument(commitTextDocument, annotationModel); commitTextBox.getTextWidget().addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { decorationSupport.uninstall(); } }); commitTextBox.addTextListener(new ITextListener() { public void textChanged(TextEvent event) { validateControls(); } }); } private void createOldCommitCombo(Composite container) { if(!options.showCommitMessage){ return; } createOldCommitCombo(container, commitTextDocument, commitTextBox); } public static void createOldCommitCombo(Composite container, final IDocument commitTextDocument, final ISourceViewer commitTextBox) { final String[] oldCommits = MercurialEclipsePlugin.getCommitMessageManager() .getCommitMessages(); if (oldCommits.length > 0) { final Combo oldCommitComboBox = SWTWidgetHelper.createCombo(container); String[] oddCommitsDisplay = new String[oldCommits.length+1]; oddCommitsDisplay[0] = Messages.getString("CommitDialog.oldCommitMessages"); for (int i = 0; i < oldCommits.length; i++) { // Add text to the combo but replace \n with
to get a one-liner String commitText = oldCommits[i].replaceAll("\\n", "
"); //XXX This is a workaround of Bug 209157 of SWT Combo if (oddCommitsDisplay.length > 3 || commitText.length() <= 100) { oddCommitsDisplay[i+1] = commitText; } else { oddCommitsDisplay[i+1] = commitText.substring(0, 100) + " ..."; } } oldCommitComboBox.setItems(oddCommitsDisplay); oldCommitComboBox.setText(Messages.getString("CommitDialog.oldCommitMessages")); oldCommitComboBox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (oldCommitComboBox.getSelectionIndex() != 0) { commitTextDocument .set(oldCommits[oldCommitComboBox.getSelectionIndex() - 1]); commitTextBox.setSelectedRange(0, oldCommits[oldCommitComboBox .getSelectionIndex() - 1].length()); } } }); } } /** * Override the OK button pressed to capture the info we want first and then call super. */ @Override protected void okPressed() { IProgressMonitor pm = monitor; monitor.setVisible(true); monitor.attachToCancelComponent(getButton(IDialogConstants.CANCEL_ID)); pm.beginTask("Committing...", 20); // get checked resources and add them to the maps to be used by hg pm.subTask("Determining resources to add, remove and to commit."); resourcesToAdd = commitFilesList.getCheckedResources(FILE_UNTRACKED); resourcesToCommit = commitFilesList.getCheckedResources(); resourcesToRemove = commitFilesList.getCheckedResources(FILE_DELETED); pm.worked(3); // get commit message String commitMessage = getCommitMessage(); // get commit username user = userTextField.getText(); if (user == null || user.length() == 0) { user = getInitialCommitUserName(); } boolean closeBranchSelected = isCloseBranchSelected(); boolean amend = amendCheckbox != null && amendCheckbox.getSelection() && currentChangeset != null; try { // amend changeset if (amend) { if (closeBranchSelected) { setErrorMessage(Messages.getString("Cannot close branch while amending")); return; } // only one root allowed when amending Map> map = ResourceUtils.groupByRoot(resourcesToCommit); if (map.size() > 1) { setErrorMessage(Messages.getString("CommitDialog.amendingOnlyForOneRoot")); return; } // load additional changeset information (files, parents) updateChangeset(pm); // only proceed if files are present if (currentChangeset.getChangedFiles().isEmpty()) { setErrorMessage(Messages.getString("CommitDialog.noChangesetToAmend")); return; } if(currentChangeset.isMerge()) { setErrorMessage(Messages.getString("CommitDialog.noAmendForMerge")); return; } if (HgQAppliedClient.getAppliedPatches(root).size() > 0) { setErrorMessage("Cannot amend when there are applied MQ patches"); return; } pm.worked(1); if (!confirmHistoryRewrite()) { setErrorMessage(Messages.getString("CommitDialog.abortedAmending")); return; } } // add new resources pm.subTask("Adding selected untracked resources to repository."); HgAddClient.addResources(resourcesToAdd, pm); pm.worked(1); // remove deleted resources pm.subTask("Removing selected deleted resources from repository."); HgRemoveClient.removeResources(resourcesToRemove); pm.worked(1); // perform commit pm.subTask("Committing resources to repository."); if (amend) { commitResult = performAmend(commitMessage, currentChangeset); } else { commitResult = performCommit(commitMessage, closeBranchSelected, currentChangeset); } pm.worked(1); /* Store commit message in the database if not the default message */ if (!commitMessage.equals(options.defaultCommitMessage)) { pm.subTask("Storing the commit message for later use."); MercurialEclipsePlugin.getCommitMessageManager().saveCommitMessage(commitMessage); } pm.worked(1); // revertCheckBox can be null if this is a merge dialog if (isRevertSelected()) { revertResources(); } } catch (HgException e) { setErrorMessage(e.getConciseMessage()); MercurialEclipsePlugin.logError(e); return; } catch (CoreException e) { setErrorMessage(e.getLocalizedMessage()); MercurialEclipsePlugin.logError(e); return; } finally { monitor.done(); monitor.removeFromCancelComponent(getButton(IDialogConstants.CANCEL_ID)); monitor.setVisible(false); } super.okPressed(); if(closeBranchSelected){ // open "switch to" dialog as the user decided to close the branch and will // go to the switch dialog anyway try { new SwitchHandler().run(root); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } private boolean isRevertSelected() { return revertCheckBox != null && revertCheckBox.getSelection(); } private boolean isCloseBranchSelected() { return closeBranchCheckBox != null && closeBranchCheckBox.getSelection(); } private boolean confirmHistoryRewrite() { MessageDialog dialog = new MessageDialog( getShell(), Messages.getString("CommitDialog.reallyAmendAndRewriteHistory"), //$NON-NLS-1$ null, Messages.getString("CommitDialog.amendWarning1") //$NON-NLS-1$ + Messages.getString("CommitDialog.amendWarning2") //$NON-NLS-1$ + Messages.getString("CommitDialog.amendWarning3"), //$NON-NLS-1$ MessageDialog.CONFIRM, new String[]{ IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL}, 1 // default index - cancel ); dialog.setBlockOnOpen(true); // if false then may show in background return dialog.open() == 0; // 0 means yes } /** * @return the result of the commit operation (hg output), if any. If there was no commit or * commit output was null, return empty string */ public String getCommitResult() { return commitResult != null ? commitResult : ""; } private static String makePatchName(String id) { return "HGE-" + id + "-" + System.currentTimeMillis() + HgPatchClient.PATCH_EXTENSION; } /** * Amend adds the changes in the selected files to the parent changeset. QRefresh isn't used * generally because when it fails (eg inconsistent line endings) then programatically restoring * state is hard. Instead the parent is qimported (a), the selected files are qnew'd (b), if * still dirty remaining files are added to a 2nd qnew'd patch (c). Then a and b are folded and * c is applied and then stripped. This also works around the problem of qrefresh unexpectedly * adding changes to a file if changes in that file are already in the patch. * * TODO: allow amending commit user as well. */ protected String performAmend(String message, ChangeSet cs) throws HgException { final IProgressMonitor pm = monitor; final String origPatchName = makePatchName("amend-orig"); String result = ""; boolean exceptionExpected = true; boolean refreshWorspace = false; try { pm.subTask("Importing changeset into MQ."); result += HgQImportClient.qimport(root, true, currentChangeset, origPatchName); pm.worked(1); if (!resourcesToCommit.isEmpty() || HgStatusClient.isDirty(root)) { final String amendPatchName = makePatchName("amendment"); String notIncludedPatchName = null; refreshWorspace = true; pm.subTask("Creating new MQ patch containing changes to amend"); // May throw exceptions eg: inconsistent newline style or patch file exists result += HgQNewClient.createNewPatch(root, "Changes to amend with previous", resourcesToCommit, user, null, amendPatchName); pm.worked(1); if (HgStatusClient.isDirty(root)) { notIncludedPatchName = makePatchName("notSelected"); // Note: If an exception occurs here 2 patches will be qfinished // This error is semi-expected result += HgQNewClient.createNewPatch(root, "Changes to amend with previous", user, null, notIncludedPatchName); exceptionExpected = false; HgStatusClient.assertClean(root); } // These should not fail pm.subTask("Folding MQ patches"); exceptionExpected = false; HgQPopClient.pop(root, false, origPatchName); pm.worked(1); HgStatusClient.assertClean(root); HgQFoldClient.fold(root, false, message, amendPatchName); pm.worked(1); if (notIncludedPatchName != null) { pm.subTask("Restoring uncommitted changes"); HgQPushClient.push(root, false, notIncludedPatchName); HgStripClient.stripCurrent(root, true, false, false); HgQDeleteClient.delete(root, false, notIncludedPatchName); pm.worked(1); } } else { // refresh patch to update commit message pm.subTask("Refreshing MQ amend patch with newly added/removed/changed files."); result = HgQRefreshClient.refresh(root, true, resourcesToCommit, message, true); pm.worked(4); } } catch (HgException e) { if (!exceptionExpected) { MessageDialog.openError(getShell(), "Error amending!", "An unexpected error occurred performing amend!\n" + "To recover refer to the Mercurial Patch Queue View.\n" + "Intermediate steps are saved in /.hg/patches folder.\n" + "Please file a MercurialEclipse bug and include the Eclipse error log."); MercurialEclipsePlugin.logError("An unexpected error occurred during amend!", e); } throw e; } finally { try { pm.subTask("Removing amend patch from MQ and promoting it to repository."); HgQFinishClient.finishAllApplied(root); pm.worked(1); } catch (HgException e) { MessageDialog.openError(getShell(), "Error amending!", "An unexpected error occurred restoring state during amend!\n" + "To recover refer to the Mercurial Patch Queue View.\n" + "Intermediate steps are saved in /.hg/patches folder.\n" + "Please file a MercurialEclipse bug and include the Eclipse error log."); MercurialEclipsePlugin.logError("An unexpected error occurred restoring state during amend!", e); } RefreshRootJob job; if (refreshWorspace) { // The file contents should be the same but hg may have changed timestamps, etc // which will cause out of sync messages. job = new RefreshWorkspaceStatusJob(root, RefreshRootJob.LOCAL_AND_OUTGOING); } else { job = new RefreshRootJob( Messages.getString("CommitDialog.refreshingAfterAmend1") + root.getName() //$NON-NLS-1$ + Messages.getString("CommitDialog.refreshingAfterAmend2"), root, RefreshRootJob.LOCAL_AND_OUTGOING); //$NON-NLS-1$ } job.schedule(); } return result; } protected String performCommit(String messageToCommit, boolean closeBranch, ChangeSet cs) throws CoreException { if (resourcesToCommit.isEmpty() && (!options.filesSelectable || closeBranch)) { // enforce commit anyway return HgCommitClient.commitResources(root, closeBranch, user, messageToCommit, monitor); } return HgCommitClient.commitResources(resourcesToCommit, user, messageToCommit, monitor, closeBranch); } private void revertResources() { final List revertResources = commitFilesList.getUncheckedResources(FILE_ADDED, FILE_DELETED, FILE_MODIFIED, FILE_REMOVED); final List untrackedResources = commitFilesList .getUncheckedResources(FILE_UNTRACKED); new Job(Messages.getString("CommitDialog.revertJob.RevertingFiles")) { @Override protected IStatus run(IProgressMonitor m) { ActionRevert action = new ActionRevert(); try { action.doRevert(m, revertResources, untrackedResources, false, null); } catch (HgException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } return Status.OK_STATUS; } }.schedule(); } public List getResourcesToRemove() { return resourcesToRemove; } protected void setCommitMessage(String msg) { if (msg == null) { msg = options.defaultCommitMessage; } commitTextDocument.set(msg); if (commitTextBox != null) { commitTextBox.setSelectedRange(0, msg.length()); } } public String getUser() { return user; } private void openSash() throws HgException { IProgressMonitor pm = this.monitor; monitor.setVisible(true); pm.beginTask("Loading amend data.", 2); // only one root allowed when amending Map> map = ResourceUtils.groupByRoot(resourcesToCommit); if (map.size() > 1) { setMessage(Messages.getString("CommitDialog.amendingOnlyForOneRoot")); amendCheckbox.setEnabled(false); amendCheckbox.setSelection(false); } // determine current changeset updateChangeset(pm); pm.done(); monitor.setVisible(false); // set old commit message IDocument msg = commitTextDocument; if ("".equals(msg.get()) || msg.get().equals(DEFAULT_COMMIT_MESSAGE)) { msg.set(currentChangeset.getComment()); } // create tray controls ChangesetInfoTray t = new ChangesetInfoTray(currentChangeset); final Shell shell = getShell(); leftSeparator = new Label(shell, SWT.SEPARATOR | SWT.VERTICAL); leftSeparator.setLayoutData(new GridData(GridData.FILL_VERTICAL)); sash = new Sash(shell, SWT.VERTICAL); sash.setLayoutData(new GridData(GridData.FILL_VERTICAL)); rightSeparator = new Label(shell, SWT.SEPARATOR | SWT.VERTICAL); rightSeparator.setLayoutData(new GridData(GridData.FILL_VERTICAL)); trayControl = t.createContents(shell); // calculate width Rectangle clientArea = shell.getClientArea(); final GridData data = new GridData(GridData.FILL_VERTICAL); data.widthHint = trayControl.computeSize(clientArea.width*3/4, clientArea.height).x; trayControl.setLayoutData(data); int trayWidth = leftSeparator.computeSize(SWT.DEFAULT, clientArea.height).x + sash.computeSize(SWT.DEFAULT, clientArea.height).x + rightSeparator.computeSize(SWT.DEFAULT, clientArea.height).x + data.widthHint; Rectangle bounds = shell.getBounds(); shell.setBounds(bounds.x - ((Window.getDefaultOrientation() == SWT.RIGHT_TO_LEFT) ? trayWidth : 0), bounds.y, bounds.width + trayWidth, bounds.height); sash.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { if (event.detail != SWT.DRAG) { Rectangle rect = shell.getClientArea(); int newWidth = rect.width - event.x - (sash.getSize().x + rightSeparator.getSize().x); if (newWidth != data.widthHint) { data.widthHint = newWidth; shell.layout(); } } } }); this.tray = t; } private void updateChangeset(IProgressMonitor pm) throws HgException { if (!currentChangeset.getChangedFiles().isEmpty()) { // no update necessary return; } int startRev = currentChangeset.getChangesetIndex(); // update to get file status information Map> changesets = HgLogClient.getRootLog(root, 1, startRev, true); pm.worked(1); if (!changesets.isEmpty()) { currentChangeset = changesets.get(root.getIPath()).iterator().next(); pm.worked(1); } } private void closeSash() { if (tray == null) { throw new IllegalStateException("Tray was not open"); //$NON-NLS-1$ } int trayWidth = trayControl.getSize().x + leftSeparator.getSize().x + sash.getSize().x + rightSeparator.getSize().x; trayControl.dispose(); trayControl = null; tray = null; leftSeparator.dispose(); leftSeparator = null; rightSeparator.dispose(); rightSeparator = null; sash.dispose(); sash = null; Shell shell = getShell(); Rectangle bounds = shell.getBounds(); shell.setBounds(bounds.x + ((Window.getDefaultOrientation() == SWT.RIGHT_TO_LEFT) ? trayWidth : 0), bounds.y, bounds.width - trayWidth, bounds.height); } /** * @param options non null */ public void setOptions(Options options) { this.options = options; } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/CommitResource.java000066400000000000000000000060111173713500500336130ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * StefanC - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import java.io.File; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; public class CommitResource { private final String statusMessage; private final int status; private final IResource resource; private final File path; public CommitResource(int statusBitField, IResource resource, File path) { this.status = statusBitField; this.statusMessage = convertStatus(status); this.resource = resource; this.path = path; } private String convertStatus(int bits) { if ((bits & MercurialStatusCache.BIT_MODIFIED) != 0) { return CommitDialog.FILE_MODIFIED; } else if ((bits & MercurialStatusCache.BIT_ADDED) != 0) { return CommitDialog.FILE_ADDED; } else if ((bits & MercurialStatusCache.BIT_REMOVED) != 0) { return CommitDialog.FILE_REMOVED; } else if ((bits & MercurialStatusCache.BIT_UNKNOWN) != 0) { return CommitDialog.FILE_UNTRACKED; } else if ((bits & MercurialStatusCache.BIT_MISSING) != 0) { return CommitDialog.FILE_DELETED; } else if ((bits & MercurialStatusCache.BIT_CLEAN) != 0) { return CommitDialog.FILE_CLEAN; } else { return "status error: " + bits; //$NON-NLS-1$ } } public String getStatusMessage() { return statusMessage; } public IResource getResource() { return resource; } public File getPath() { return path; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("CommitResource [status="); builder.append(statusMessage); builder.append(", path="); builder.append(path); builder.append(", resource="); builder.append(resource); builder.append("]"); return builder.toString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((resource == null) ? 0 : resource.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof CommitResource)) { return false; } CommitResource other = (CommitResource) obj; if (resource == null) { if (other.resource != null) { return false; } } else if (!resource.equals(other.resource)) { return false; } return true; } public boolean isUnknown() { return (status & MercurialStatusCache.BIT_UNKNOWN) != 0; } public boolean isMissing() { return (status & MercurialStatusCache.BIT_MISSING) != 0; } }CommitResourceLabelProvider.java000066400000000000000000000037571173713500500362250ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * StefanC - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.model.WorkbenchLabelProvider; public final class CommitResourceLabelProvider extends LabelProvider { private final ILabelProvider workbenchLabelProvider; public CommitResourceLabelProvider() { super(); workbenchLabelProvider = WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider(); workbenchLabelProvider.addListener(new ILabelProviderListener() { public void labelProviderChanged(LabelProviderChangedEvent event) { fireLabelProviderChanged(event); } }); } @Override public boolean isLabelProperty(Object element, String property) { return true; } @Override public Image getImage(Object element) { if (!(element instanceof CommitResource)) { return null; } IResource resource = ((CommitResource) element).getResource(); return workbenchLabelProvider.getImage(resource); } @Override public String getText(Object element) { if (!(element instanceof CommitResource)) { return null; } return ((CommitResource) element).getPath().toString(); } @Override public void dispose() { workbenchLabelProvider.dispose(); super.dispose(); } }CommitResourceUtil.java000066400000000000000000000111511173713500500343730ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Jérôme Nègre - some fixes * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.team.core.Team; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public final class CommitResourceUtil { /** * Bit mask of status cache bits for cancidate statuses when committing */ private static final int COMMIT_CANDIDATE_STATUSES_BITS = MercurialStatusCache.BIT_MISSING | MercurialStatusCache.BIT_REMOVED | MercurialStatusCache.BIT_UNKNOWN | MercurialStatusCache.BIT_ADDED | MercurialStatusCache.BIT_MODIFIED; private CommitResourceUtil() { // static utility } /** * @return never null */ public static CommitResource[] getCommitResources(List inResources) { if(inResources.size() == 0){ return new CommitResource[0]; } Map> resourcesByRoot = ResourceUtils.groupByRoot(inResources); Set toCommit = new HashSet(); for (Map.Entry> mapEntry : resourcesByRoot.entrySet()) { toCommit.addAll(spliceStatusResult(mapEntry.getKey(), mapEntry.getValue())); } return toCommit.toArray(new CommitResource[toCommit.size()]); } /** * Construct the {@link CommitResource} instances. */ private static List spliceStatusResult(HgRoot root, List resources) { MercurialStatusCache cache = MercurialStatusCache.getInstance(); ArrayList list = new ArrayList(); for (IResource resource : resources) { if (resource instanceof IContainer) { for (IResource curResource : cache.getResources(COMMIT_CANDIDATE_STATUSES_BITS, (IContainer)resource)) { processStatusResult(root, cache, list, curResource); } } else { processStatusResult(root, cache, list, resource); } } return list; } private static void processStatusResult(HgRoot root, MercurialStatusCache cache, List list, IResource resource) { if (!(resource instanceof IFile)) { return; } IPath location = ResourceUtils.getPath(resource); if(location.isEmpty() || cache.isDirectory(location)) { return; } Integer status = cache.getStatus(resource); if (status != null || !Team.isIgnoredHint(resource)) { File path = new File(root.toRelative(location.toFile())); list.add(new CommitResource(status == null ? MercurialStatusCache.BIT_UNKNOWN : status .intValue(), resource, path)); } } /** * Filter a list of commit-resources to contain only tracked ones (which are already tracked by Mercurial). */ public static List filterForTracked(CommitResource[] commitResources) { List tracked = new ArrayList(); for (CommitResource commitResource : commitResources) { if (!commitResource.isUnknown()) { tracked.add(commitResource); } } return tracked; } /** * Filter a list of commit-resources to contain only those which are equal with a set of IResources * @param commitResources * @param resources * @return The commit resources */ public static List filterForResources(List commitResources,List resources) { List result = new ArrayList(); if (resources == null || resources.isEmpty()) { return result; } Set resourceSet = new HashSet(); resourceSet.addAll(resources); for (CommitResource commitResource : commitResources) { IResource res = commitResource.getResource(); if (res != null && resourceSet.contains(res)) { result.add(commitResource); } } return result; } } ContinueRebaseDialog.java000066400000000000000000000056101173713500500346260ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.RebaseOperation; import com.vectrace.MercurialEclipse.ui.CommitFilesChooser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * Dialog for showing which files will be committed for a rebase. *

* Future: For --collapse rebases allow the user to set commit message and commit user when the * rebase is started. Future: The user shouldn't be displayed. */ public class ContinueRebaseDialog extends CommitDialog { public ContinueRebaseDialog(Shell shell, HgRoot hgRoot) { super(shell, hgRoot, null); options.defaultCommitMessage = ""; options.showAmend = false; options.showCloseBranch = false; options.showRevert = false; options.showCommitMessage = false; } @Override protected Control createDialogArea(Composite parent) { Control control = super.createDialogArea(parent); getShell().setText(Messages.getString("RebaseDialog.window.title")); //$NON-NLS-1$ setTitle(Messages.getString("RebaseDialog.title")); // "; setMessage(Messages.getString("RebaseDialog.message")); return control; } @Override protected CommitFilesChooser createFilesList(Composite container) { SWTWidgetHelper.createLabel(container, Messages.getString("RebaseDialog.fileList")); return new CommitFilesChooser(root, container, false, false, false, false); } @Override protected String performCommit(String messageToCommit, boolean closeBranch, ChangeSet cs) throws CoreException { return continueRebase(messageToCommit); } private String continueRebase(String messageToCommit) throws CoreException { RebaseOperation op = RebaseOperation.createContinue(MercurialEclipsePlugin.getActiveWindow(), root, getUser()); try { op.run(new NullProgressMonitor()); } catch (InvocationTargetException e) { MercurialEclipsePlugin.rethrow(e); } catch (InterruptedException e) { MercurialEclipsePlugin.rethrow(e); } return op.getResult(); } } EditChangesetDialog.java000066400000000000000000000111571173713500500344320ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import java.util.ArrayList; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.CommitFilesChooser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * @author Andrei */ public class EditChangesetDialog extends CommitDialog { private final GroupedUncommittedChangeSet changeset; private Text changesetNameText; public EditChangesetDialog(Shell shell, HgRoot hgRoot, GroupedUncommittedChangeSet changeset, boolean isDefault) { super(shell, hgRoot, new ArrayList(changeset.getFiles())); setBlockOnOpen(true); this.changeset = changeset; Assert.isNotNull(hgRoot); options.defaultCommitMessage = changeset.getComment(); // not available options.showAmend = false; // don't create it as we don't want it in merge dialog options.showCloseBranch = false; options.showRevert = false; options.showDiff = true; options.filesSelectable = !isDefault; options.allowEmptyCommit = true; } @Override protected Control createDialogArea(Composite parent) { Composite control = (Composite) super.createDialogArea(parent); getShell().setText(Messages.getString("EditChangesetDialog.title", changeset.getName())); //$NON-NLS-1$ setTitle(Messages.getString("EditChangesetDialog.title", changeset.getName())); //$NON-NLS-1$"; setMessage(Messages.getString("EditChangesetDialog.message")); //$NON-NLS-1$"; createChangesetNameContainer(control); return control; } @Override protected String getInitialCommitMessage() { String initialCommitMessage = super.getInitialCommitMessage(); if(StringUtils.isEmpty(initialCommitMessage)) { if(!StringUtils.isEmpty(changeset.getComment())) { return changeset.getComment(); } if(!StringUtils.isEmpty(changeset.getName())) { return changeset.getName(); } } return initialCommitMessage; } private void createChangesetNameContainer(Composite container) { Composite comp = SWTWidgetHelper.createComposite(container, 2); comp.moveAbove(container.getChildren()[0]); SWTWidgetHelper.createLabel(comp, "Changeset name:"); changesetNameText = SWTWidgetHelper.createTextField(comp); changesetNameText.setText(changeset.getName()); changesetNameText.addFocusListener(new FocusListener() { private String oldCommitMessage; public void focusLost(FocusEvent e) { String text = changesetNameText.getText(); if(text.length() > 0 && getCommitMessage().length() == 0 || (oldCommitMessage != null && !text.equals(oldCommitMessage))) { setCommitMessage(text); } } public void focusGained(FocusEvent e) { oldCommitMessage = getCommitMessage(); if(!changesetNameText.getText().equals(oldCommitMessage)) { oldCommitMessage = null; } } }); } @Override protected CommitFilesChooser createFilesList(Composite container) { return super.createFilesList(container); // SWTWidgetHelper.createLabel(container, Messages.getString("CommitDialog.selectFiles")); //$NON-NLS-1$ // return new CommitFilesChooser(root, container, options.filesSelectable, true, true, false); } @Override protected void okPressed() { changeset.setComment(getCommitMessage()); changeset.setName(changesetNameText.getText()); setReturnCode(OK); close(); // TODO add file management // commitFilesList.getCheckedResources(); // commitFilesList.getUncheckedResources(FILE_ADDED, // FILE_DELETED, FILE_MODIFIED, FILE_REMOVED); } @Override protected String performCommit(String messageToCommit, boolean closeBranch, ChangeSet cs) throws CoreException { return ""; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/IgnoreDialog.java000066400000000000000000000107711173713500500332260ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * @author Jerome Negre * */ public class IgnoreDialog extends Dialog { public enum ResultType { FILE, FOLDER, EXTENSION, GLOB, REGEXP } private ResultType resultType; private IFile file; private IFolder folder; Text patternText; private String pattern; public IgnoreDialog(Shell parentShell) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); } public IgnoreDialog(Shell parentShell, IFile file) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); this.file = file; } public IgnoreDialog(Shell parentShell, IFolder folder) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); this.folder = folder; } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.getString("IgnoreDialog.shell.text")); //$NON-NLS-1$ } @Override protected IDialogSettings getDialogBoundsSettings() { IDialogSettings dialogSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); String sectionName = getClass().getSimpleName(); IDialogSettings section = dialogSettings.getSection(sectionName); if (section == null) { dialogSettings.addNewSection(sectionName); } return section; } @Override protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); GridLayout gridLayout = new GridLayout(1, true); composite.setLayout(gridLayout); Label label = new Label(composite, SWT.NONE); label.setText(Messages.getString("IgnoreDialog.selectLabel.text")); //$NON-NLS-1$ if(this.file != null) { addButton(composite, Messages.getString("IgnoreDialog.onlyFileBtn.label")+this.file.getName()+"')", false, ResultType.FILE); //$NON-NLS-1$ //$NON-NLS-2$ if(this.file.getFileExtension() != null) { addButton(composite, Messages.getString("IgnoreDialog.filesWithExtBtn.label")+this.file.getFileExtension()+"')", false, ResultType.EXTENSION); //$NON-NLS-1$ //$NON-NLS-2$ } } if(this.folder != null) { addButton(composite, Messages.getString("IgnoreDialog.folderBtn.label")+this.folder.getName()+"')", false, ResultType.FOLDER); //$NON-NLS-1$ //$NON-NLS-2$ } addButton(composite, Messages.getString("IgnoreDialog.customRegExpBtn.label"), true, ResultType.REGEXP); //$NON-NLS-1$ addButton(composite, Messages.getString("IgnoreDialog.customGlobBtn.label"), true, ResultType.GLOB); //$NON-NLS-1$ patternText = new Text(composite, SWT.BORDER | SWT.DROP_DOWN); patternText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); return composite; } private void addButton(Composite parent, String text, final boolean isPattern, final ResultType type) { Button button = new Button(parent, SWT.RADIO); button.setText(text); button.addSelectionListener(new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { patternText.setEnabled(isPattern); resultType = type; } }); } @Override protected void okPressed() { this.pattern = patternText.getText(); super.okPressed(); } public IFile getFile() { return file; } public IFolder getFolder() { return folder; } public String getPattern() { return pattern; } public ResultType getResultType() { return resultType; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/MergeDialog.java000066400000000000000000000043721173713500500330420ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import org.eclipse.core.runtime.CoreException; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.menu.CommitMergeHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.CommitFilesChooser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author Andrei */ public class MergeDialog extends CommitDialog { public MergeDialog(Shell shell, HgRoot hgRoot, String defaultCommitMessage) { super(shell, hgRoot, null); options.defaultCommitMessage = defaultCommitMessage; // not available when merging options.showAmend = false; // don't create it as we don't want it in merge dialog options.showCloseBranch = false; options.showRevert = false; } @Override protected Control createDialogArea(Composite parent) { Control control = super.createDialogArea(parent); getShell().setText(Messages.getString("MergeDialog.window.title")); //$NON-NLS-1$ setTitle(Messages.getString("MergeDialog.title")); //$NON-NLS-1$"; setMessage(Messages.getString("MergeDialog.message")); //$NON-NLS-1$"; return control; } @Override protected CommitFilesChooser createFilesList(Composite container) { SWTWidgetHelper.createLabel(container, Messages.getString("CommitDialog.selectFiles")); //$NON-NLS-1$ return new CommitFilesChooser(root, container, false, true, true, false); } @Override protected String performCommit(String messageToCommit, boolean closeBranch, ChangeSet cs) throws CoreException { return CommitMergeHandler.commitMerge(root, getUser(), messageToCommit); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/Messages.java000066400000000000000000000026001173713500500324220ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import java.text.MessageFormat; import java.util.Arrays; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.dialogs.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } public static String getString(String key, Object... args) { try { return MessageFormat.format(RESOURCE_BUNDLE.getString(key), args); } catch (MissingResourceException e) { return '!' + key + Arrays.toString(args) + '!'; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/NewHeadsDialog.java000066400000000000000000000203111173713500500334700ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov (Intland) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IconAndMessageDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.progress.IProgressService; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgRevertClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.commands.HgUpdateClient; import com.vectrace.MercurialEclipse.commands.extensions.HgRebaseClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.MergeHandler; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.views.MergeView; import com.vectrace.MercurialEclipse.wizards.RebaseWizard; public class NewHeadsDialog extends IconAndMessageDialog { private final static int MERGE_ID = IDialogConstants.CLIENT_ID + 1; private final static int REBASE_ID = IDialogConstants.CLIENT_ID + 2; private final static int SWITCH_ID = IDialogConstants.CLIENT_ID + 3; private final HgRoot hgRoot; private boolean moreThanTwoHeads; private boolean cleanUpdateRequested; public NewHeadsDialog(Shell parentShell, HgRoot hgRoot) throws HgException { super(parentShell); setShellStyle(SWT.TITLE | SWT.CLOSE); int extraHeads = MergeHandler.getHeadsInCurrentBranch(hgRoot).size(); if (extraHeads == 2) { message = Messages.getString("NewHeadsDialog.twoHeads"); } else if (extraHeads > 2) { message = Messages.getString("NewHeadsDialog.manyHeads"); moreThanTwoHeads = true; } else { throw new HgException("Should have at least two heads"); } this.hgRoot = hgRoot; } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.getString("NewHeadsDialog.title")); //$NON-NLS-1$ } @Override protected Control createDialogArea(Composite parent) { return createMessageArea(parent); } @Override protected void createButtonsForButtonBar(Composite parent) { if (moreThanTwoHeads) { // createButton(parent, SWITCH_ID, Messages.getString("NewHeadsDialog.manyHeads.Switch"), false); createButton(parent, REBASE_ID, Messages.getString("NewHeadsDialog.manyHeads.Rebase"), false); createButton(parent, MERGE_ID, Messages.getString("NewHeadsDialog.manyHeads.Merge"), false); } else { // createButton(parent, SWITCH_ID, Messages.getString("NewHeadsDialog.twoHeads.Switch"), false); createButton(parent, REBASE_ID, Messages.getString("NewHeadsDialog.twoHeads.Rebase"), false); createButton(parent, MERGE_ID, Messages.getString("NewHeadsDialog.twoHeads.Merge"), false); } createButton(parent, IDialogConstants.CANCEL_ID, Messages.getString("NewHeadsDialog.CancelUpdate"), false); } @Override protected void buttonPressed(int buttonId) { switch (buttonId) { case MERGE_ID: mergePressed(); break; case REBASE_ID: rebasePressed(); break; case SWITCH_ID: switchPressed(); break; } close(); // every button closes the dialog } private void switchPressed() { } private void rebasePressed() { if (!clearAndContinue()) { return; } if (moreThanTwoHeads) { RebaseWizard wizard = new RebaseWizard(hgRoot); WizardDialog wizardDialog = new WizardDialog(getShell(), wizard); wizardDialog.open(); } else { rebaseOnTip(); } } private void rebaseOnTip() { IProgressService iProgressService = PlatformUI.getWorkbench().getProgressService(); try { iProgressService.run(true, false, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { boolean useExternalMergeTool = MercurialEclipsePlugin.getDefault().getPreferenceStore() .getBoolean(MercurialPreferenceConstants.PREF_USE_EXTERNAL_MERGE); boolean rebaseConflict = false; try { monitor.beginTask("Rebasing on tip", 2); // rebase on Tip revision HgRebaseClient.rebase(hgRoot, -1, -1, -1, false, false, false, false, false, useExternalMergeTool, null); monitor.worked(1); monitor.setTaskName("Updating"); // if rebase succeeded try again updating to tip HgUpdateClient.update(hgRoot, null, cleanUpdateRequested); monitor.done(); } catch (final HgException e) { rebaseConflict = HgRebaseClient.isRebaseConflict(e); if (!rebaseConflict) { MercurialEclipsePlugin.logError(e); Display.getDefault().asyncExec(new Runnable() { public void run() { MessageDialog.openError(getShell(), "Rebase error", e.getMessage()); } }); } } finally { RefreshWorkspaceStatusJob job = new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.ALL); if (rebaseConflict) { // do not join to avoid any potential deadlocks. listener is enough job.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { showMergeView(); } }); } job.schedule(); } } }); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } } /** * Checks that working copy is clear and (if needed) asks user to revert dirty files * @return false if user cancelled operation or an error occured */ private boolean clearAndContinue() { try { if (HgStatusClient.isDirty(hgRoot)) { boolean clearAndContinue = cleanUpdateRequested || MessageDialog.openConfirm(getShell(), "Uncommited changes", Messages.getString("RevertDialog.uncommitedChanges")); if (clearAndContinue) { HgRevertClient.performRevertAll(new NullProgressMonitor(), hgRoot); return true; } return false; } return true; // no changes found } catch (HgException e) { MercurialEclipsePlugin.logError(e); return false; } } /** * show Merge view, as it offers to abort a merge and revise the automatically merged files */ private void showMergeView() { Runnable runnable = new Runnable() { public void run() { try { MergeView.showRebaseConflict(hgRoot, getShell()); } catch (PartInitException e1) { MercurialEclipsePlugin.logError(e1); } } }; Display.getDefault().asyncExec(runnable); } private void mergePressed() { if (!clearAndContinue()) { return; } try { MergeHandler.determineMergeHeadAndMerge(hgRoot, getParentShell(), new NullProgressMonitor(), false, true); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); MessageDialog.openError(getShell(), "Merging error", e.getMessage()); } } @Override protected Image getImage() { return getShell().getDisplay().getSystemImage(SWT.ICON_INFORMATION); } public void setClean(boolean clean) { this.cleanUpdateRequested = clean; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/RejectsDialog.java000066400000000000000000000203521173713500500333760ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.filebuffers.FileBuffers; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.TrayDialog; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.part.FileEditorInput; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class RejectsDialog extends TrayDialog { private static final Pattern REJECT_PATTERN = Pattern.compile("saving rejects to file (.*)\\s"); private static final Pattern CHANGESET_PATTERN = Pattern.compile("applying (.*)\\s"); private final List rejects; protected final HgRoot hgRoot; protected final String failedChangeSetId; private CheckboxTableViewer viewer; private Button openAllRejectsCheckBox; protected IFile selectedFile; private final String title; private final String detail; public RejectsDialog(Shell shell, HgRoot hgRoot, String message, String title, String detail) throws HgException { this(shell, hgRoot, message, title, detail, true); } public RejectsDialog(Shell shell, HgRoot hgRoot, String message, String title, String detail, boolean requireSource) throws HgException { super(shell); this.title = title; this.detail = detail; this.hgRoot = hgRoot; Matcher matcher = CHANGESET_PATTERN.matcher(message); boolean found = matcher.find() && matcher.groupCount() > 0; if (!found && requireSource) { throw new HgException("Couldn't find source"); } this.failedChangeSetId = found ? matcher.group(1) : ""; rejects = new ArrayList(); matcher = REJECT_PATTERN.matcher(message); int lastMatchOffset = 0; while (matcher.find(lastMatchOffset) && matcher.groupCount() > 0) { String filename = matcher.group(1); IPath path = new Path(hgRoot.getPath()).append(filename); IFile file = FileBuffers.getWorkspaceFileAtLocation(path); if (file != null) { rejects.add(file); } lastMatchOffset = matcher.end(); } setShellStyle(getShellStyle() | SWT.RESIZE); } @Override protected IDialogSettings getDialogBoundsSettings() { IDialogSettings dialogSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); String sectionName = getClass().getSimpleName(); IDialogSettings section = dialogSettings.getSection(sectionName); if (section == null) { dialogSettings.addNewSection(sectionName); } return section; } @Override protected Control createDialogArea(Composite parent) { getShell().setText(Messages.getString(title, failedChangeSetId)); Composite container = SWTWidgetHelper.createComposite(parent, 1); GridData gd = SWTWidgetHelper.getFillGD(400); gd.minimumWidth = 500; gd.widthHint = container.getBorderWidth(); container.setLayoutData(gd); super.createDialogArea(parent); Label label = new Label(container, SWT.WRAP); final GridData data = new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1); label.setLayoutData(data); label.setText(Messages.getString(detail)); Table table = createTable(container); viewer = new CheckboxTableViewer(table); viewer.setContentProvider(new ArrayContentProvider()); viewer.setLabelProvider(new RejectLabelProvider()); viewer.setInput(rejects); viewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { showRejectedDiff(selectedFile); } }); addSelectionListener(); openAllRejectsCheckBox = SWTWidgetHelper.createCheckBox(container, Messages .getString("RejectsDialog.openAllRejects")); return container; } private void addSelectionListener() { viewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) selection; IFile res = (IFile) sel.getFirstElement(); selectedFile = res; } } }); } private void showRejectedDiff(IFile file) { if (file != null) { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getActivePage(); IEditorDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry().findEditor( org.eclipse.ui.editors.text.EditorsUI.DEFAULT_TEXT_EDITOR_ID); try { page.openEditor(new FileEditorInput(file), desc.getId()); } catch (PartInitException e) { } } } private Table createTable(Composite composite) { int flags = SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER; flags |= SWT.READ_ONLY | SWT.HIDE_SELECTION; Table table = new Table(composite, flags); table.setHeaderVisible(false); table.setLinesVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); table.setLayoutData(data); return table; } @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); } @Override protected void okPressed() { boolean editRejects = openAllRejectsCheckBox.getSelection(); close(); if (editRejects) { for (IFile file : rejects) { showRejectedDiff(file); } } } private final class RejectLabelProvider extends LabelProvider { private final ILabelProvider workbenchLabelProvider; public RejectLabelProvider() { super(); workbenchLabelProvider = WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider(); workbenchLabelProvider.addListener(new ILabelProviderListener() { public void labelProviderChanged(LabelProviderChangedEvent event) { fireLabelProviderChanged(event); } }); } @Override public boolean isLabelProperty(Object element, String property) { return true; } @Override public Image getImage(Object element) { if (!(element instanceof IResource)) { return null; } return workbenchLabelProvider.getImage(element); } @Override public String getText(Object element) { if (!(element instanceof IResource)) { return null; } return hgRoot.toRelative(ResourceUtils.getFileHandle(((IResource) element))); } @Override public void dispose() { workbenchLabelProvider.dispose(); super.dispose(); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/RevertDialog.java000066400000000000000000000136131173713500500332500ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * StefanC - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import static com.vectrace.MercurialEclipse.ui.SWTWidgetHelper.getFillGD; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.CommitFilesChooser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; public class RevertDialog extends TitleAreaDialog { private final List resources; private CommitFilesChooser selectFilesList; private List selection; private List untrackedSelection; private ChangesetTable csTable; private ChangeSet changeset; public static final String FILE_MODIFIED = Messages.getString("CommitDialog.modified"); //$NON-NLS-1$ public static final String FILE_ADDED = Messages.getString("CommitDialog.added"); //$NON-NLS-1$ public static final String FILE_REMOVED = Messages.getString("CommitDialog.removed"); //$NON-NLS-1$ public static final String FILE_UNTRACKED = Messages.getString("CommitDialog.untracked"); //$NON-NLS-1$ public static final String FILE_DELETED = Messages.getString("CommitDialog.deletedInWorkspace"); //$NON-NLS-1$ public static final String FILE_CLEAN = Messages.getString("CommitDialog.clean"); //$NON-NLS-1$ /** * @param parentShell * @param resources non null */ public RevertDialog(Shell parentShell, List resources) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); this.resources = resources; } @Override protected IDialogSettings getDialogBoundsSettings() { IDialogSettings dialogSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); String sectionName = getClass().getSimpleName(); IDialogSettings section = dialogSettings.getSection(sectionName); if (section == null) { dialogSettings.addNewSection(sectionName); } return section; } /** * Create contents of the dialog * * @param parent */ @Override protected Control createDialogArea(Composite parent) { Composite container = SWTWidgetHelper.createComposite(parent, 1); GridData gd = getFillGD(400); container.setLayoutData(gd); super.createDialogArea(parent); createFilesList(container); createRevertToChangesetWidgets(container); getShell().setText(Messages.getString("RevertDialog.window.title")); //$NON-NLS-1$ setTitle(Messages.getString("RevertDialog.title")); //$NON-NLS-1$ setMessage(Messages.getString("RevertDialog.message")); //$NON-NLS-1$ return container; } private void createRevertToChangesetWidgets(Composite container) { Group g = SWTWidgetHelper.createGroup(container, Messages.getString("RevertDialog.revision")); //$NON-NLS-1$ final Button b = SWTWidgetHelper.createCheckBox(g, Messages.getString("RevertDialog.revertToADifferentChangeset")); //$NON-NLS-1$ b.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { csTable.setEnabled(b.getSelection()); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); GridData gridData = new GridData(GridData.FILL_BOTH); g.setLayoutData(gridData); gridData = new GridData(GridData.FILL_BOTH); csTable = new ChangesetTable(g, resources.get(0)); boolean enableChangesetTable = false; if(resources.size() == 1){ enableChangesetTable = MercurialStatusCache.getInstance().isClean(resources.get(0)); } csTable.setEnabled(enableChangesetTable); csTable.setLayoutData(gridData); b.setSelection(enableChangesetTable); } private void createFilesList(Composite container) { selectFilesList = new CommitFilesChooser(container, true, resources, true, true, true); } @Override protected void okPressed() { if(resources.size() != 1) { selection = selectFilesList.getCheckedResources(FILE_ADDED, FILE_DELETED, FILE_MODIFIED, FILE_REMOVED); } else { selection = selectFilesList.getCheckedResources(FILE_ADDED, FILE_DELETED, FILE_MODIFIED, FILE_REMOVED, FILE_CLEAN); } untrackedSelection = selectFilesList.getCheckedResources(FILE_UNTRACKED); changeset = csTable.getSelection(); if(!untrackedSelection.isEmpty()){ boolean confirm = MessageDialog.openConfirm(getShell(), Messages.getString("RevertDialog.pleaseConfirmDelete"), //$NON-NLS-1$ Messages.getString("RevertDialog.youHaveSelectedToRevertUntracked") + //$NON-NLS-1$ Messages.getString("RevertDialog.thisFilesWillNowBeDeleted")); //$NON-NLS-1$ if(!confirm){ return; } } super.okPressed(); } public List getSelectionForHgRevert() { return selection; } public List getUntrackedSelection() { return untrackedSelection; } public ChangesetTable getCsTable() { return csTable; } public ChangeSet getChangeset() { return changeset; } } RevisionChooserDialog.java000066400000000000000000000103151173713500500350370ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/******************************************************************************* * Copyright (c) 2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Stefan C - Code cleanup * Bastian Doetsch - small changes * Adam Berkes (Intland) - bug fixes * Andrei Loskutov - bug fixes * Philip Graf - Field assistance for revision field and bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import org.eclipse.core.resources.IResource; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.storage.DataLoader; import com.vectrace.MercurialEclipse.storage.ResourceDataLoader; import com.vectrace.MercurialEclipse.storage.RootDataLoader; /** * @author Jerome Negre */ public class RevisionChooserDialog extends Dialog { private final DataLoader dataLoader; private final String title; private boolean defaultShowingHeads; private boolean disallowSelectingParents; private boolean showForceButton; private boolean isForceChecked; private String forceButtonText; private RevisionChooserPanel panel; public RevisionChooserDialog(Shell parentShell, String title, IResource resource) { this(parentShell, title, new ResourceDataLoader(resource)); } public RevisionChooserDialog(Shell parentShell, String title, HgRoot hgRoot) { this(parentShell, title, new RootDataLoader(hgRoot)); } private RevisionChooserDialog(Shell parentShell, String title, DataLoader loader) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); this.title = title; dataLoader = loader; } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(title); } @Override protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); RevisionChooserPanel.Settings opt = new RevisionChooserPanel.Settings(); opt.defaultShowingHeads = defaultShowingHeads; opt.disallowSelectingParents = disallowSelectingParents; opt.forceButtonText = forceButtonText; opt.isForceChecked = isForceChecked; opt.showForceButton = showForceButton; panel = new RevisionChooserPanel(composite, dataLoader, opt); panel.addSelectionListener(this); return composite; } @Override protected IDialogSettings getDialogBoundsSettings() { IDialogSettings dialogSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); String sectionName = getClass().getSimpleName(); IDialogSettings section = dialogSettings.getSection(sectionName); if (section == null) { dialogSettings.addNewSection(sectionName); } return section; } public void setForceChecked(boolean on){ isForceChecked = true; } public boolean isForceChecked(){ return isForceChecked; } public void showForceButton(boolean show){ showForceButton = show; } public void setForceButtonText(String forceButtonText) { this.forceButtonText = forceButtonText; } @Override protected void okPressed() { boolean ok = panel.calculateRevision(); if(!ok){ return; } super.okPressed(); } protected void revisionSelected() { super.okPressed(); } public String getRevision() { return panel.getRevision(); } public ChangeSet getChangeSet() { return panel.getChangeSet(); } public void setDefaultShowingHeads(boolean defaultShowingHeads) { this.defaultShowingHeads = defaultShowingHeads; } public void setDisallowSelectingParents(boolean b) { this.disallowSelectingParents = b; } } RevisionChooserPanel.java000066400000000000000000000422511173713500500347030ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/******************************************************************************* * Copyright (c) 2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Stefan C - Code cleanup * Bastian Doetsch - small changes * Adam Berkes (Intland) - bug fixes * Andrei Loskutov - bug fixes * Philip Graf - Field assistance for revision field and bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import static com.vectrace.MercurialEclipse.MercurialEclipsePlugin.logError; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.fieldassist.ContentProposalAdapter; import org.eclipse.jface.fieldassist.IContentProposal; import org.eclipse.jface.fieldassist.IContentProposalListener; import org.eclipse.jface.fieldassist.TextContentAdapter; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Bookmark; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Tag; import com.vectrace.MercurialEclipse.storage.DataLoader; import com.vectrace.MercurialEclipse.storage.EmptyDataLoader; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.ResourceProperties; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.ui.BookmarkTable; import com.vectrace.MercurialEclipse.ui.BranchTable; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.TagTable; /** * @author Jerome Negre */ public class RevisionChooserPanel extends Composite { public static class Settings { public boolean defaultShowingHeads; public boolean disallowSelectingParents; public boolean showForceButton; public boolean isForceChecked; public boolean highlightDefaultBranch; public String forceButtonText; public String revision; public ChangeSet changeSet; } private DataLoader dataLoader; private final Text text; private int[] parents; private final Settings data; private Tag tag; private Branch branch; private Bookmark bookmark; private Button forceButton; private RevisionChooserDialog dialog; private ContentAssistCommandAdapter contentAssist; public RevisionChooserPanel(Composite parent, DataLoader loader, Settings settings) { super(parent, SWT.NONE); this.data = settings; setDataLoader(loader); GridLayout gridLayout = new GridLayout(1, true); setLayoutData(new GridData(GridData.FILL_BOTH)); setLayout(gridLayout); Label label = new Label(this, SWT.NONE); label.setText(Messages.getString("RevisionChooserDialog.rev.label")); //$NON-NLS-1$ text = new Text(this, SWT.BORDER); text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); if(data.highlightDefaultBranch){ text.setText(Branch.DEFAULT); } text.addFocusListener(new FocusListener() { String textStr; public void focusLost(FocusEvent e) { String newText = text.getText(); if(newText.equals(textStr)){ return; } // cleanup not up-to-date data data.changeSet = null; bookmark = null; tag = null; branch = null; } public void focusGained(FocusEvent e) { textStr = text.getText(); } }); setupRevisionFieldAssistance(); TabFolder tabFolder = new TabFolder(this, SWT.NONE); GridData gdata = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL); gdata.heightHint = 200; tabFolder.setLayoutData(gdata); // This is a sublist of heads: unnecessary duplication to show. // The branch tab shows also *inactive* branches, which do *not* have heads. // it make sense to show it to see the project state at given branch createBranchTabItem(tabFolder); createHeadTabItem(tabFolder); createTagTabItem(tabFolder); createRevisionTabItem(tabFolder); try { if (MercurialUtilities.isCommandAvailable("bookmarks", //$NON-NLS-1$ ResourceProperties.EXT_BOOKMARKS_AVAILABLE, "hgext.bookmarks=")) { //$NON-NLS-1$ createBookmarkTabItem(tabFolder); } } catch (HgException e) { logError(e); } createOptions(this); } public void setDataLoader(DataLoader loader) { dataLoader = loader; int[] p = {}; try { p = loader.getParents(); } catch (HgException e) { logError(e); } parents = p; } /** * Adds field assistance to the revision text field. */ private void setupRevisionFieldAssistance() { contentAssist = new ContentAssistCommandAdapter(text, new TextContentAdapter(), new RevisionContentProposalProvider(dataLoader), null, null, true); contentAssist.setAutoActivationDelay(300); contentAssist.setPopupSize(new Point(320, 240)); contentAssist.setPropagateKeys(true); contentAssist.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE); contentAssist.addContentProposalListener(new IContentProposalListener() { public void proposalAccepted(IContentProposal proposal) { tag = null; branch = null; bookmark = null; String changeSetId = proposal.getContent().split(" ", 2)[0]; //$NON-NLS-1$ try { data.changeSet = LocalChangesetCache.getInstance().getOrFetchChangeSetById( dataLoader.getHgRoot(), changeSetId); } catch (HgException e) { data.changeSet = null; String message = Messages.getString( "RevisionChooserDialog.error.loadChangeset1", changeSetId); //$NON-NLS-1$ logError(message, e); } } }); } private void createOptions(Composite composite) { if(data.showForceButton){ forceButton = new Button(composite, SWT.CHECK); String message = getForceText(); if(message == null) { message = Messages.getString("RevisionChooserDialog.button.forcedOperation.label"); //$NON-NLS-1$ } forceButton.setText(message); forceButton.setSelection(data.isForceChecked); forceButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { data.isForceChecked = forceButton.getSelection(); } }); } } public boolean isForceChecked(){ return data.isForceChecked; } private String getForceText() { return data.forceButtonText; } @SuppressWarnings("boxing") public boolean calculateRevision() { String[] split = text.getText().split(":"); //$NON-NLS-1$ data.revision = split[0].trim(); if (data.changeSet == null) { HgRoot hgRoot = dataLoader.getHgRoot(); LocalChangesetCache localCache = LocalChangesetCache.getInstance(); if (tag != null){ try { data.changeSet = localCache.getOrFetchChangeSetById(hgRoot, tag.getRevision() + ":" + tag.getGlobalId()); //$NON-NLS-1$ } catch (HgException ex) { logError( Messages.getString("RevisionChooserDialog.error.loadChangeset2", tag.getRevision(), tag.getGlobalId()), ex); } } else if(branch != null) { try { data.changeSet = localCache.getOrFetchChangeSetById(hgRoot, branch.getRevision() + ":" + branch.getGlobalId()); //$NON-NLS-1$ } catch (HgException ex) { logError(Messages.getString("RevisionChooserDialog.error.loadChangeset2", branch.getRevision(), branch.getGlobalId()), ex); } } else if (bookmark != null) { try { data.changeSet = localCache.getOrFetchChangeSetById(hgRoot, bookmark.getRevision() + ":" + bookmark.getShortNodeId()); //$NON-NLS-1$ } catch (HgException ex) { logError(Messages.getString("RevisionChooserDialog.error.loadChangeset2", bookmark.getRevision(), bookmark.getShortNodeId()), ex); } } } if (data.changeSet != null) { int changesetIndex = data.changeSet.getChangesetIndex(); if(changesetIndex >= 0){ data.revision = Integer.toString(changesetIndex); } else { data.revision = ""; } } if (data.revision.length() == 0) { data.revision = null; } if (data.disallowSelectingParents) { for (int p : parents) { if (String.valueOf(p).equals(data.revision)) { MessageBox mb = new MessageBox(getShell(), SWT.ICON_WARNING); mb.setText("Merge"); //$NON-NLS-1$ mb.setMessage(Messages.getString("RevisionChooserDialog.cannotMergeWithParent")); //$NON-NLS-1$ mb.open(); return false; } } } return true; } public void applyRevision() { if(calculateRevision()){ if(dialog != null){ dialog.revisionSelected(); } } } public String getRevision() { return data.revision; } protected TabItem createRevisionTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("RevisionChooserDialog.revTab.name")); //$NON-NLS-1$ final ChangesetTable table = new ChangesetTable(folder, false); table.setLayoutData(new GridData(GridData.FILL_BOTH)); table.highlightParents(parents); table.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { tag = null; branch = null; bookmark = null; ChangeSet selection = table.getSelection(); text.setText(selection.getChangesetIndex() + ":" + selection.getChangeset()); //$NON-NLS-1$ data.changeSet = selection; } @Override public void widgetDefaultSelected(SelectionEvent e) { applyRevision(); } }); table.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { table.removeListener(SWT.Show, this); new SafeUiJob(Messages.getString("RevisionChooserDialog.tagJob.description")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor) { if(dataLoader.getResource() != null) { table.setStrategy(new ChangesetTable.ResourceStrategy(dataLoader.getResource())); } else { table.setStrategy(new ChangesetTable.RootStrategy(dataLoader.getHgRoot())); } table.setEnabled(true); return Status.OK_STATUS; } }.schedule(); } }); item.setControl(table); return item; } protected TabItem createTagTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("RevisionChooserDialog.tagTab.name")); //$NON-NLS-1$ final TagTable table = new TagTable(folder, dataLoader.getHgRoot()); table.highlightParents(parents); table.setLayoutData(new GridData(GridData.FILL_BOTH)); table.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { tag = table.getSelection(); text.setText(tag.getName()); branch = null; bookmark = null; data.changeSet = null; } @Override public void widgetDefaultSelected(SelectionEvent e) { applyRevision(); } }); table.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { table.removeListener(SWT.Show, this); new SafeUiJob(Messages.getString("RevisionChooserDialog.tagJob.description")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor) { try { Tag[] tags = dataLoader.getTags(); table.setHgRoot(dataLoader.getHgRoot()); table.setTags(tags); return Status.OK_STATUS; } catch (HgException e) { logError(e); return Status.CANCEL_STATUS; } } }.schedule(); } }); item.setControl(table); return item; } protected TabItem createBranchTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("RevisionChooserDialog.branchTab.name")); //$NON-NLS-1$ final BranchTable table = new BranchTable(folder); table.highlightParents(parents); if(data.highlightDefaultBranch) { table.highlightBranch(Branch.DEFAULT); } table.setLayoutData(new GridData(GridData.FILL_BOTH)); table.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { branch = table.getSelection(); text.setText(branch.getName()); tag = null; bookmark = null; data.changeSet = null; } @Override public void widgetDefaultSelected(SelectionEvent e) { applyRevision(); } }); boolean needListener = dataLoader == null || dataLoader instanceof EmptyDataLoader; final SafeUiJob fetchData = new SafeUiJob(Messages.getString("RevisionChooserDialog.branchJob.description")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor) { try { Branch[] branches = dataLoader.getBranches(); if (data.highlightDefaultBranch && branches.length == 0 && Branch.DEFAULT.equals(text.getText())) { text.setText(""); } table.setBranches(branches); table.redraw(); table.update(); return Status.OK_STATUS; } catch (HgException e) { logError(e); return Status.CANCEL_STATUS; } } }; if(needListener){ table.addListener(SWT.Paint, new Listener() { public void handleEvent(Event event) { table.removeListener(SWT.Paint, this); fetchData.schedule(); } }); } else { fetchData.schedule(); } item.setControl(table); return item; } protected TabItem createBookmarkTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("RevisionChooserDialog.bookmarkTab.name")); //$NON-NLS-1$ final BookmarkTable table = new BookmarkTable(folder); table.setLayoutData(new GridData(GridData.FILL_BOTH)); table.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { table.removeListener(SWT.Show, this); new SafeUiJob(Messages.getString("RevisionChooserDialog.bookmarksJob.name")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor) { table.updateTable(dataLoader.getHgRoot()); table.setEnabled(true); return Status.OK_STATUS; } }.schedule(); } }); table.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { bookmark = table.getSelection(); text.setText(bookmark.getName()); tag = null; branch = null; data.changeSet = null; } @Override public void widgetDefaultSelected(SelectionEvent e) { applyRevision(); } }); item.setControl(table); return item; } protected TabItem createHeadTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("RevisionChooserDialog.headTab.name")); //$NON-NLS-1$ final ChangesetTable table = new ChangesetTable(folder, false); table.setLayoutData(new GridData(GridData.FILL_BOTH)); table.addListener(SWT.Show, new Listener() { public void handleEvent(Event event) { table.removeListener(SWT.Show, this); new SafeUiJob(Messages.getString("RevisionChooserDialog.fetchJob.description")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor) { try { table.highlightParents(parents); table.setStrategy(new ChangesetTable.PrefetchedStrategy(dataLoader.getHeads())); table.setEnabled(true); return Status.OK_STATUS; } catch (HgException e) { logError(e); return Status.CANCEL_STATUS; } } }.schedule(); } }); table.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { tag = null; branch = null; bookmark = null; ChangeSet selection = table.getSelection(); data.changeSet = selection; if(selection.getChangesetIndex() >= 0) { text.setText(selection.getChangesetIndex() + ":" + selection.getChangeset()); //$NON-NLS-1$ } else { text.setText(""); //$NON-NLS-1$ } } @Override public void widgetDefaultSelected(SelectionEvent e) { applyRevision(); } }); item.setControl(table); if (data.defaultShowingHeads) { folder.setSelection(item); } return item; } public ChangeSet getChangeSet() { return data.changeSet; } public void addSelectionListener(RevisionChooserDialog dialog1) { this.dialog = dialog1; } public void update(DataLoader loader){ setDataLoader(loader); contentAssist.setContentProposalProvider(new RevisionContentProposalProvider(loader)); } } RevisionContentProposalProvider.java000066400000000000000000000242531173713500500371700ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/******************************************************************************* * Copyright (c) 2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Philip Graf - implementation * Andrei Loskutov - bug fixes, refactored to standalone class *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import static com.vectrace.MercurialEclipse.MercurialEclipsePlugin.logError; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.regex.Pattern; import org.eclipse.core.resources.IResource; import org.eclipse.jface.fieldassist.IContentProposal; import org.eclipse.jface.fieldassist.IContentProposalProvider; import com.vectrace.MercurialEclipse.commands.extensions.HgBookmarkClient; import com.vectrace.MercurialEclipse.model.Bookmark; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Tag; import com.vectrace.MercurialEclipse.storage.DataLoader; import com.vectrace.MercurialEclipse.storage.EmptyDataLoader; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.utils.ChangeSetUtils; /** * Proposal provider for the revision text field. */ public class RevisionContentProposalProvider implements IContentProposalProvider { private final Future> changeSets; private final Future> bookmarks; public RevisionContentProposalProvider(final DataLoader dataLoader) { ExecutorService executor = Executors.newFixedThreadPool(2); if(dataLoader instanceof EmptyDataLoader){ changeSets = executor.submit(new Callable>() { public SortedSet call() throws Exception { return Collections.unmodifiableSortedSet(new TreeSet()); } }); bookmarks = executor.submit(new Callable>() { public List call() throws Exception { return Collections.unmodifiableList(new ArrayList()); } }); } else { changeSets = executor.submit(new Callable>() { public SortedSet call() throws Exception { IResource resource = dataLoader.getResource(); HgRoot hgRoot = dataLoader.getHgRoot(); SortedSet result; LocalChangesetCache cache = LocalChangesetCache.getInstance(); if(resource != null) { result = cache.getOrFetchChangeSets(resource); } else { result = cache.getOrFetchChangeSets(hgRoot); } if(result.isEmpty() || result.first().getChangesetIndex() > 0) { if(resource != null) { cache.fetchRevisions(resource, false, 0, 0, false); result = cache.getOrFetchChangeSets(resource); } else { cache.fetchRevisions(hgRoot, false, 0, 0, false); result = cache.getOrFetchChangeSets(hgRoot); } if(result == null) { // fetching the change sets failed result = Collections.unmodifiableSortedSet(new TreeSet()); } } return result; } }); bookmarks = executor.submit(new Callable>() { public List call() throws Exception { return HgBookmarkClient.getBookmarks(dataLoader.getHgRoot()); } }); } executor.shutdown(); } public IContentProposal[] getProposals(String contents, int position) { List result = new LinkedList(); String filter = contents.substring(0, position).toLowerCase(); try { for (ChangeSet changeSet : changeSets.get()) { if (changeSet.getName().toLowerCase().startsWith(filter) || changeSet.getChangeset().startsWith(filter)) { result.add(0, new ChangeSetContentProposal(changeSet, ContentType.REVISION)); } else { String value = getTagsStartingWith(filter, changeSet); if (value.length() > 0) { result.add(0, new ChangeSetContentProposal(changeSet, ContentType.TAG, value)); } else if (changeSet.getBranch().toLowerCase().startsWith(filter)) { result.add(0, new ChangeSetContentProposal(changeSet, ContentType.BRANCH, changeSet.getBranch())); } } } } catch (InterruptedException e) { logError(Messages.getString("RevisionChooserDialog.error.loadChangesets"), e); //$NON-NLS-1$ } catch (ExecutionException e) { logError(Messages.getString("RevisionChooserDialog.error.loadChangesets"), e); //$NON-NLS-1$ } try { for (Bookmark bookmark : bookmarks.get()) { if (bookmark.getName().toLowerCase().startsWith(filter)) { result.add(new BookmarkContentProposal(bookmark)); } } } catch (InterruptedException e) { logError(Messages.getString("RevisionChooserDialog.error.loadBookmarks"), e); //$NON-NLS-1$ } catch (ExecutionException e) { logError(Messages.getString("RevisionChooserDialog.error.loadBookmarks"), e); //$NON-NLS-1$ } return result.toArray(new IContentProposal[result.size()]); } private String getTagsStartingWith(String filter, ChangeSet changeSet) { StringBuilder builder = new StringBuilder(); for(Tag tag: changeSet.getTags()) { if(tag.getName().toLowerCase().startsWith(filter)) { builder.append(tag.getName()).append(", "); //$NON-NLS-1$ } } if(builder.length() > 2) { // truncate the trailing ", " builder.setLength(builder.length() - 2); } return builder.toString(); } public static enum ContentType {REVISION, TAG, BRANCH, AUTHOR, DATE, SUMMARY} public static class ChangeSetContentProposal implements IContentProposal { private static final Pattern LABEL_SPLITTER = Pattern.compile("\\.\\s|[\\n\\r]"); //$NON-NLS-1$ protected final ChangeSet changeSet; private final RevisionContentProposalProvider.ContentType type; protected final String value; private String label; private String description; /** * @param changeSet non null * @param type */ public ChangeSetContentProposal(ChangeSet changeSet, RevisionContentProposalProvider.ContentType type) { this.changeSet = changeSet; this.type = type; value = null; } public ChangeSetContentProposal(ChangeSet changeSet, RevisionContentProposalProvider.ContentType type, String value) { this.changeSet = changeSet; this.type = type; this.value = value; } public String getContent() { return changeSet.getName(); } public int getCursorPosition() { return getContent().length(); } public String getDescription() { if(description == null) { description = createDescription(); } return description; } private String createDescription() { StringBuilder builder = new StringBuilder(); // summary builder.append(changeSet.getSummary()).append("\n\n"); //$NON-NLS-1$ // branch (optional) String branch = changeSet.getBranch(); if(branch != null && branch.length() > 0) { builder.append(Messages.getString("RevisionChooserDialog.fieldassist.description.changeset.branch")); //$NON-NLS-1$ builder.append(": ").append(branch).append('\n'); //$NON-NLS-1$ } // tag (optional) String tags = ChangeSetUtils.getPrintableTagsString(changeSet); if(tags.length() > 0) { builder.append(Messages.getString("RevisionChooserDialog.fieldassist.description.changeset.tags")); //$NON-NLS-1$ builder.append(": ").append(tags).append('\n'); //$NON-NLS-1$ } // author builder.append(Messages.getString("RevisionChooserDialog.fieldassist.description.changeset.author")); //$NON-NLS-1$ builder.append(": ").append(changeSet.getAuthor()).append("\n"); //$NON-NLS-1$ // date builder.append(Messages.getString("RevisionChooserDialog.fieldassist.description.changeset.date")); //$NON-NLS-1$ builder.append(": ").append(changeSet.getDateString()).append('\n'); //$NON-NLS-1$ // revision builder.append(Messages.getString("RevisionChooserDialog.fieldassist.description.changeset.revision")); //$NON-NLS-1$ builder.append(": ").append(changeSet.getName()); //$NON-NLS-1$ return builder.toString(); } public String getLabel() { if(label == null) { label = createLabel(); } return label; } private String createLabel() { StringBuilder builder = new StringBuilder(String.valueOf(changeSet.getChangesetIndex())); builder.append(": "); //$NON-NLS-1$ String text; switch(type) { case TAG: case BRANCH: case AUTHOR: case DATE: text = "[" + value + "] " + changeSet.getSummary(); //$NON-NLS-1$ //$NON-NLS-2$ break; case SUMMARY: case REVISION: default: text = changeSet.getSummary(); break; } // shorten label text if necessary int maxLineLength = getMaxLineLength(); if(text.length() > maxLineLength) { // extract first sentence or line text = LABEL_SPLITTER.split(text, 2)[0].trim(); // shorten it if still too long if(text.length() > maxLineLength) { text = text.substring(0, maxLineLength - 7).trim() + "..."; //$NON-NLS-1$ } builder.append(text); } else { builder.append(text); } return builder.toString(); } protected int getMaxLineLength() { return 50; } } public static final class BookmarkContentProposal implements IContentProposal { private final Bookmark bookmark; private BookmarkContentProposal(Bookmark bookmark) { this.bookmark = bookmark; } public String getContent() { return bookmark.getRevision() + ":" + bookmark.getShortNodeId(); //$NON-NLS-1$ } public int getCursorPosition() { return getContent().length(); } public String getDescription() { return bookmark.getRevision() + ":" + bookmark.getShortNodeId() + "\n\n" + bookmark.getName(); //$NON-NLS-1$ //$NON-NLS-2$ } public String getLabel() { return bookmark.getRevision() + ": " + bookmark.getName(); //$NON-NLS-1$ } } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/TagDialog.java000066400000000000000000000245361173713500500325220ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgTagClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Tag; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.ui.TagTable; /** * @author Jerome Negre */ public class TagDialog extends Dialog { private final HgRoot hgRoot; // main TabItem private Text nameText; private Button forceButton; private Button localButton; // output private String name; private String targetRevision; private boolean forced; private boolean local; private Text userTextField; private String user; public TagDialog(Shell parentShell, HgRoot hgRoot) { super(parentShell); setShellStyle(getShellStyle() | SWT.RESIZE); this.hgRoot = hgRoot; } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(Messages.getString("TagDialog.shell.text")); //$NON-NLS-1$ } @Override protected IDialogSettings getDialogBoundsSettings() { IDialogSettings dialogSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); String sectionName = getClass().getSimpleName(); IDialogSettings section = dialogSettings.getSection(sectionName); if (section == null) { dialogSettings.addNewSection(sectionName); } return section; } @Override protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); GridLayout gridLayout = new GridLayout(2, false); composite.setLayout(gridLayout); TabFolder tabFolder = new TabFolder(composite, SWT.NONE); tabFolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL)); createMainTabItem(tabFolder); createTargetTabItem(tabFolder); createRemoveTabItem(tabFolder); return composite; } private GridData createGridData(int colspan) { GridData data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = colspan; data.minimumWidth = SWT.DEFAULT; return data; } private GridData createGridData(int colspan, int width) { GridData data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalSpan = colspan; data.minimumWidth = width; return data; } private void createUserCommitText(Composite container) { Composite comp = SWTWidgetHelper.createComposite(container, 2); SWTWidgetHelper.createLabel(comp, Messages.getString("CommitDialog.userLabel.text")); //$NON-NLS-1$ userTextField = SWTWidgetHelper.createTextField(comp); user = HgCommitMessageManager.getDefaultCommitName(hgRoot); userTextField.setText(user); } protected TabItem createMainTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("TagDialog.mainTab.name")); //$NON-NLS-1$ Composite composite = new Composite(folder, SWT.NONE); composite.setLayout(new GridLayout(1, true)); // tag name Label label = new Label(composite, SWT.NONE); label.setText(Messages.getString("TagDialog.enterTagName")); //$NON-NLS-1$ label.setLayoutData(createGridData(1)); nameText = new Text(composite, SWT.BORDER); nameText.setLayoutData(createGridData(1)); createUserCommitText(composite); forceButton = new Button(composite, SWT.CHECK); forceButton.setText(Messages.getString("TagDialog.moveTag")); //$NON-NLS-1$ forceButton.setLayoutData(createGridData(1)); localButton = new Button(composite, SWT.CHECK); localButton.setText(Messages.getString("TagDialog.createLocal")); //$NON-NLS-1$ localButton.setLayoutData(createGridData(1)); // List of existing tags label = new Label(composite, SWT.NONE); label.setText(Messages.getString("TagDialog.existingTags")); //$NON-NLS-1$ label.setLayoutData(createGridData(1)); final TagTable table = new TagTable(composite, hgRoot); table.hideTip(); GridData data = new GridData(GridData.FILL_BOTH); data.heightHint = 150; table.setLayoutData(data); table.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Tag tag = table.getSelection(); nameText.setText(tag.getName()); localButton.setSelection(tag.isLocal()); } }); try { table.setTags(HgTagClient.getTags(hgRoot)); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } item.setControl(composite); return item; } protected TabItem createOptionsTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("TagDialog.options")); //$NON-NLS-1$ Composite composite = new Composite(folder, SWT.NONE); composite.setLayout(new GridLayout(1, true)); // TODO commit date // user name final Button customUserButton = new Button(composite, SWT.CHECK); customUserButton.setText(Messages.getString("TagDialog.customUserName")); //$NON-NLS-1$ final Text userText = new Text(composite, SWT.BORDER); userText.setLayoutData(createGridData(1, 250)); userText.setEnabled(false); customUserButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { userText.setEnabled(customUserButton.getSelection()); } }); // commit message item.setControl(composite); return item; } protected TabItem createRemoveTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("TagDialog.removeTag")); //$NON-NLS-1$ Composite composite = SWTWidgetHelper.createComposite(folder, 1); final TagTable tt = new TagTable(composite, hgRoot); tt.hideTip(); GridData data = new GridData(GridData.FILL_BOTH); data.heightHint = 150; tt.setLayoutData(data); try { tt.setTags(HgTagClient.getTags(hgRoot)); } catch (HgException e2) { MercurialEclipsePlugin.showError(e2); MercurialEclipsePlugin.logError(e2); } Button removeButton = SWTWidgetHelper.createPushButton(composite, Messages.getString("TagDialog.removeSelectedTag"), 1); //$NON-NLS-1$ MouseListener listener = new MouseListener() { public void mouseUp(MouseEvent e) { try { String result = HgTagClient.removeTag(hgRoot, tt.getSelection(), userTextField.getText()); HgClients.getConsole().printMessage(result, null); tt.setTags(HgTagClient.getTags(hgRoot)); new RefreshRootJob(com.vectrace.MercurialEclipse.menu.Messages.getString( "TagHandler.refreshing"), hgRoot, RefreshRootJob.ALL).schedule(); //$NON-NLS-1$ } catch (HgException e1) { MercurialEclipsePlugin.showError(e1); MercurialEclipsePlugin.logError(e1); } } public void mouseDown(MouseEvent e) { } public void mouseDoubleClick(MouseEvent e) { } }; removeButton.addMouseListener(listener); item.setControl(composite); return item; } protected TabItem createTargetTabItem(TabFolder folder) { TabItem item = new TabItem(folder, SWT.NONE); item.setText(Messages.getString("TagDialog.targetTab.name")); //$NON-NLS-1$ Composite composite = new Composite(folder, SWT.NONE); composite.setLayout(new GridLayout(1, true)); Button parentButton = new Button(composite, SWT.RADIO); parentButton.setText(Messages.getString("TagDialog.tagParentChangeset")); //$NON-NLS-1$ parentButton.setSelection(true); Button otherButton = new Button(composite, SWT.RADIO); otherButton.setText(Messages.getString("TagDialog.tagAnotherChangeset")); //$NON-NLS-1$ final ChangesetTable table = new ChangesetTable(composite, hgRoot); table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); table.setEnabled(false); table.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { targetRevision = Integer.toString(table.getSelection() .getChangesetIndex()); } }); parentButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { table.setEnabled(false); targetRevision = null; } }); otherButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { table.setEnabled(true); ChangeSet changeset = table.getSelection(); if (changeset != null) { targetRevision = Integer.toString(changeset .getChangesetIndex()); } } }); item.setControl(composite); return item; } @Override protected void okPressed() { name = nameText.getText(); forced = forceButton.getSelection(); local = localButton.getSelection(); user = userTextField.getText(); super.okPressed(); } public String getName() { return name; } public String getTargetRevision() { return targetRevision; } public boolean isForced() { return forced; } public boolean isLocal() { return local; } public String getUser() { return user; } } TransplantRejectsDialog.java000066400000000000000000000060021173713500500353620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov (Intland) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.dialogs; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgRevertClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.wizards.TransplantWizard; /** * Dialog shows list of rejected patches. Allows user to revert changes and reopen Transplant wizard */ public class TransplantRejectsDialog extends RejectsDialog { public TransplantRejectsDialog(Shell parentShell, HgRoot hgRoot, String message) throws HgException { super(parentShell, hgRoot, message, "TransplantRejectsDialog.title", "TransplantRejectsDialog.transplantFailed"); setBlockOnOpen(false); } @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.CANCEL_ID, Messages .getString("TransplantRejectsDialog.tryAnotherTransplant"), false); createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); } @Override protected void cancelPressed() { final Display display = getShell().getDisplay(); new Job("Reverting transplant") { @Override protected IStatus run(IProgressMonitor monitor) { monitor.beginTask("Reverting transplant", 1); try { HgRevertClient.performRevertAll(new NullProgressMonitor(), hgRoot); new RefreshRootJob(hgRoot, RefreshRootJob.LOCAL_AND_OUTGOING).schedule(); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } display.syncExec(new Runnable() { public void run() { TransplantWizard transplantWizard = new TransplantWizard(hgRoot); WizardDialog transplantWizardDialog = new WizardDialog(getParentShell(), transplantWizard); transplantWizardDialog.setBlockOnOpen(false); transplantWizardDialog.open(); } }); monitor.done(); return Status.OK_STATUS; } }.schedule(); close(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/dialogs/messages.properties000066400000000000000000000176061173713500500337510ustar00rootroot00000000000000BookmarkDialog.bookmarkName=Bookmark name BookmarkDialog.createGroup.label=Create new bookmark BookmarkDialog.createTab.name=Create bookmark BookmarkDialog.modifyTab.name=Modify bookmark BookmarkDialog.newName=New name of bookmark BookmarkDialog.option.delete=Delete selected bookmark BookmarkDialog.option.rename=Rename selected bookmark BookmarkDialog.renameGroup.label=Modify action BookmarkDialog.selectBookmark=Select bookmark BookmarkDialog.selectRevision=Select revision (or don't select to set bookmark to tip) BookmarkDialog.shell.text=Manage bookmarks... EditChangesetDialog.title=Edit Changeset ''{0}'' EditChangesetDialog.message=Enter a commit message and select the files which should be committed later together MergeDialog.title=Commit changes to local Mercurial repository MergeDialog.window.title=Mercurial Merge MergeDialog.message=Enter a commit message and select the files to commit after merge. NewHeadsDialog.title=Multiple heads in branch NewHeadsDialog.twoHeads=You have two heads in current branch. You can merge them or rebase your current change sets onto tip revision. NewHeadsDialog.manyHeads=You have more than two heads in current branch. Automatic update is not possible in this case, you can rebase your current changes on another head or merge heads manually. NewHeadsDialog.manyHeads.Rebase=Rebase wizard NewHeadsDialog.manyHeads.Merge=Merge wizard NewHeadsDialog.manyHeads.Switch=Switch to... NewHeadsDialog.twoHeads.Rebase=Rebase on tip NewHeadsDialog.twoHeads.Merge=Merge two heads NewHeadsDialog.twoHeads.Switch=Switch to tip NewHeadsDialog.CancelUpdate=Neither RebaseDialog.title=Confirm rebase to local Mercurial repository RebaseDialog.window.title=Mercurial Rebase In Progress RebaseDialog.message=Continue conflicted rebase. RebaseDialog.fileList=The following files will be committed with the rebase RevertDialog.uncommitedChanges=Your working directory contains uncommited changes.\nDo you really want to continue and discard them? CommitDialog.reallyAmendAndRewriteHistory=Really amend changeset and rewrite history? CommitDialog.refreshing=Refreshing local changesets after commit... CommitDialog.abortedAmending=Aborted amending the current changeset. CommitDialog.refreshingAfterAmend1=Refreshing CommitDialog.refreshingAfterAmend2=\ after amending current changeset. CommitDialog.added=Added CommitDialog.amendCurrentChangeset1=Amend current changeset ( CommitDialog.amendingOnlyForOneRoot=Amending works only if all resources are in the same repository. CommitDialog.amendWarning1=Amending changesets changes the history of the repository.\n CommitDialog.amendWarning2=If you have already pushed the last changeset press Cancel.\n\n CommitDialog.amendWarning3=Do you really want to amend the current changeset? CommitDialog.closingBranch=Closing branch: {0} CommitDialog.commitTextLabel.text=Please enter the commit message. CommitDialog.oldCommitMessages=Select old commit message CommitDialog.defaultCommitMessage=(no commit message) CommitDialog.deletedInWorkspace=Missing but still tracked CommitDialog.clean=Clean CommitDialog.closeBranch=Close named branch CommitDialog.modified=Modified CommitDialog.removed=Removed CommitDialog.revertCheckBoxLabel.revertUncheckedResources=Revert all unselected files CommitDialog.revertJob.RevertingFiles=Reverting files CommitDialog.selectFiles=Select Files: CommitDialog.title=Commit changes to local Mercurial repository CommitDialog.window.title=Mercurial Commit CommitDialog.commitMessageRequired=Enter a commit message. CommitDialog.noResourcesSelected=Select the files to commit. CommitDialog.readyToCommit=Press Ok to commit selected files. CommitDialog.noChangesetToAmend=There is no changeset to amend. CommitDialog.noAmendForMerge=Amend is not possible for merge changeset. CommitDialog.untracked=Untracked CommitDialog.userLabel.text=User to record as committer: CommitResourceUtil.error.unableToGetStatus=: unable to get status IgnoreDialog.customGlobBtn.label=Custom glob IgnoreDialog.customRegExpBtn.label=Custom regexp IgnoreDialog.filesWithExtBtn.label=All files with the same extension ('*. IgnoreDialog.folderBtn.label=Only this folder (' IgnoreDialog.onlyFileBtn.label=Only this file (' IgnoreDialog.selectLabel.text=Select what to ignore: IgnoreDialog.shell.text=Add to hgignore... RevertDialog.file=File RevertDialog.thisFilesWillNowBeDeleted=\nThis files will be now deleted.\n\nContinue? RevertDialog.title=Revert changes in local repository RevertDialog.window.title=Mercurial Revert RevertDialog.message=Please select the resources to be reverted. RevertDialog.pleaseConfirmDelete=Please confirm delete RevertDialog.revertToADifferentChangeset=Revert to a different changeset RevertDialog.revision=Choose the changeset to revert to RevertDialog.youHaveSelectedToRevertUntracked=You have selected to revert untracked files. RevisionChooserDialog.bookmarkTab.name=Bookmarks RevisionChooserDialog.branchJob.description=Fetching branches from repository RevisionChooserDialog.branchTab.name=Branches RevisionChooserDialog.fetchJob.description=Fetching heads from repository RevisionChooserDialog.headTab.name=Heads RevisionChooserDialog.rev.label=Please enter a valid revision (local, global, tag or branch): RevisionChooserDialog.revTab.name=Revisions RevisionChooserDialog.tagJob.description=Fetching tags from repository RevisionChooserDialog.bookmarksJob.name=Fetching bookmarks from repository RevisionChooserDialog.tagTab.name=Tags RevisionChooserDialog.fieldassist.description.changeset.branch=Branch RevisionChooserDialog.fieldassist.description.changeset.tags=Tags RevisionChooserDialog.fieldassist.description.changeset.author=Author RevisionChooserDialog.fieldassist.description.changeset.date=Date RevisionChooserDialog.fieldassist.description.changeset.revision=Revision RevisionChooserDialog.cannotMergeWithParent=You cannot merge a changeset with itself.\nPlease choose another revision.\nYou probably wanted to select the other Head. RevisionChooserDialog.button.forcedOperation.label=Forced operation RevisionChooserDialog.error.loadChangesets=Unable to load changesets RevisionChooserDialog.error.loadBookmarks=Unable to load bookmarks RevisionChooserDialog.error.loadChangeset1=Unable to get or fetch revision: <{0}> RevisionChooserDialog.error.loadChangeset2=Unable to get or fetch revision: <{0,number,0}:{1}> TagDialog.createLocal=Create local tag TagDialog.customUserName=Use custom user name TagDialog.enterTagName=Please enter a tag name: TagDialog.existingTags=Existing tags: TagDialog.mainTab.name=Main TagDialog.moveTag=Move tag if it already exists TagDialog.options=Options TagDialog.removeSelectedTag=Remove selected Tag TagDialog.removeTag=Remove Tag TagDialog.shell.text=Tag as Version... TagDialog.tagAnotherChangeset=Tag another changeset TagDialog.tagParentChangeset=Tag parent changeset TagDialog.targetTab.name=Target RejectsDialog.openAllRejects=Open all rejected patches in editors TransplantRejectsDialog.tryAnotherTransplant=Revert and reopen Transplant Wizard TransplantRejectsDialog.transplantFailed=Transplant tried to patch files or code lines that are not present in your current working copy. You can revert transplant and try again with another change set.\nOr if you know what you are doing, you can apply the patch manually. Press OK, fix the merge and start transplant with continue option.\n\nRejected patches: TransplantRejectsDialog.title=Failed to transplant revision {0} ImportPatchRejectsDialog.conflict=A conflict occurred applying patch! ImportPatchRejectsDialog.title=Failed to apply patch {0} UnshelveRejectsDialog.title=A conflict occurred unshelving! UnshelveRejectsDialog.conflict=A conflict occurred unshelving!\n\nSee .rej files to resolve the conflicts. The patch remains shelved. QPushRejectsDialog.conflict=A conflict occurred pushing patch!\n\nResolve the conflicts and then refresh the patch. QRejectsDialog.title=Failed to apply patch {0} QFoldRejectsDialog.conflict=A conflict occurred folding patch!\n\nResolve the conflicts, refresh the patch, then invoke qdelete if desired. eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/exception/000077500000000000000000000000001173713500500303665ustar00rootroot00000000000000HgCoreException.java000066400000000000000000000017501173713500500342030ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/exception/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.exception; /** * @author bastian * */ public class HgCoreException extends RuntimeException { public HgCoreException() { super(); } public HgCoreException(String message, Throwable cause) { super(message, cause); } public HgCoreException(String message) { super(message); } public HgCoreException(Throwable cause) { super(cause); } /** * */ private static final long serialVersionUID = -582465463467902805L; } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/exception/HgException.java000066400000000000000000000071121173713500500334470ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Balm Consulting Inc (Peter Hunnisett ) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.exception; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.team.core.TeamException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; public class HgException extends TeamException { private static final long serialVersionUID = 1L; // Get rid of warning public static final int OPERATION_FAILED = -100; public static final int OPERATION_CANCELLED = -200; public static final String OPERATION_FAILED_STRING = Messages.getString("HgException.operationFailed"); //$NON-NLS-1$ /** * @see #getConciseMessage() */ private static final Pattern CONCISE_MESSAGE_PATTERN = Pattern.compile("^(?:remote:\\s*)?(?:error|abort):\\s*(.+)", Pattern.MULTILINE); private static final Pattern LINE_PATTERN = Pattern.compile(".+"); /** * May be null. Raw hg output. */ private String output; public HgException(IStatus status) { super(status); } public HgException(String message) { super(new Status(IStatus.ERROR, MercurialEclipsePlugin.ID, OPERATION_FAILED, message, new Exception(message))); } public HgException(CoreException e) { super(e); } public HgException(String message, Throwable e) { super(new Status(IStatus.ERROR, MercurialEclipsePlugin.ID, OPERATION_FAILED, message, e)); } public HgException(int code, String message, Throwable e) { super(new Status(IStatus.ERROR, MercurialEclipsePlugin.ID, code, message, e)); } /** * Create an exception indicating an error that occurred invoking hg. */ public HgException(int code, String message, String jobName, Throwable e) { this(code, message + ". Command line: " + jobName, e); this.output = message; } @Override public String getMessage() { IStatus status = getStatus(); StringBuilder sb = new StringBuilder(status.getMessage()); switch (status.getCode()) { case OPERATION_CANCELLED: break; case OPERATION_FAILED: break; default: sb.append(", error code: ").append(status.getCode()); break; } return sb.toString(); } @Override public String getLocalizedMessage() { return getMessage(); } @Override public String toString() { // never null return getMessage(); } private String getOutput() { return this.output != null ? this.output : getStatus().getMessage(); } /** * Parses the message looking for "abort:" and if present returns the remainder of the line * * @return A more concise error message if possible. Otherwise the entire error message */ public String getConciseMessage() { String message = getOutput(); Matcher matcher = CONCISE_MESSAGE_PATTERN.matcher(message); if (matcher.find()) { return matcher.group(1); } return message; } /** * @return Whether the message is multiple lines */ public boolean isMultiLine() { Matcher m = LINE_PATTERN.matcher(getOutput()); m.find(); return m.find(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/exception/Messages.java000066400000000000000000000021331173713500500327770ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.exception; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.exception.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } messages.properties000066400000000000000000000000671173713500500342370ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/exceptionHgException.operationFailed=Mercurial Operation failed eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/000077500000000000000000000000001173713500500300715ustar00rootroot00000000000000BisectAbstractAction.java000066400000000000000000000105401173713500500347100ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.MessageDialog; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.commands.HgBisectClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; /** * @author bastian */ public abstract class BisectAbstractAction extends Action { private final MercurialHistoryPage mercurialHistoryPage; public BisectAbstractAction(String text, MercurialHistoryPage mercurialHistoryPage) { super(text); this.mercurialHistoryPage = mercurialHistoryPage; } public boolean isBisectStarted() { return mercurialHistoryPage.getMercurialHistory().isBisectStarted(); } public void setBisectStarted(boolean started) { mercurialHistoryPage.getMercurialHistory().setBisectStarted(started); } private MercurialRevision getRevision() { MercurialRevision[] selectedRevisions = mercurialHistoryPage.getSelectedRevisions(); if (selectedRevisions != null && selectedRevisions.length == 1) { return selectedRevisions[0]; } ChangeSet cs = mercurialHistoryPage.getCurrentWorkdirChangeset(); return (MercurialRevision) mercurialHistoryPage.getMercurialHistory().getFileRevision( cs.getChangeset()); } abstract String callBisect(final HgRoot root, final ChangeSet cs) throws HgException; @Override public void run() { final HgRoot root; try { root = MercurialTeamProvider.getHgRoot(mercurialHistoryPage.resource); if(root == null || checkDirty(root)){ return; } } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); return; } final MercurialRevision rev = getRevision(); final ChangeSet cs = rev.getChangeSet(); new Job(Messages.BisectAbstractAction_bisecting) { @Override protected IStatus run(IProgressMonitor monitor) { try { final String result = callBisect(root, cs); if (result.startsWith(Messages.BisectAbstractAction_successString)) { HgBisectClient.reset(root); } new RefreshWorkspaceStatusJob(root, RefreshRootJob.LOCAL).schedule(); new SafeUiJob(Messages.BisectAbstractAction_showBisectionResult) { @Override protected IStatus runSafe(IProgressMonitor m) { if (result.length() > 0) { MercurialEclipsePlugin.logInfo(result, null); MessageDialog.openInformation(getDisplay().getActiveShell(), Messages.BisectAbstractAction_BisectionResult, result); } updateHistory(rev, root); return super.runSafe(m); } }.schedule(); } catch (HgException e) { MercurialEclipsePlugin.showError(e); return e.getStatus(); } return Status.OK_STATUS; } }.schedule(); } protected boolean checkDirty(final HgRoot root) throws HgException { if (HgStatusClient.isDirty(root)) { MessageDialog.openWarning(mercurialHistoryPage.getControl().getShell(), "Uncommitted Changes", //$NON-NLS-1$ "Your hg root has uncommited changes." + "\nPlease commit or revert to start Bisection."); //$NON-NLS-1$ return true; } return false; } protected void updateHistory(MercurialRevision rev, HgRoot root) { mercurialHistoryPage.clearSelection(); mercurialHistoryPage.refresh(); } }BisectMarkBadAction.java000066400000000000000000000030421173713500500344450ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2010 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - Implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import com.vectrace.MercurialEclipse.commands.HgBisectClient; import com.vectrace.MercurialEclipse.commands.HgBisectClient.Status; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian */ final class BisectMarkBadAction extends BisectAbstractAction { BisectMarkBadAction(MercurialHistoryPage mercurialHistoryPage) { super(Messages.BisectMarkBadAction_name, mercurialHistoryPage); this.setDescription(Messages.BisectMarkBadAction_description1 + Messages.BisectMarkBadAction_description2); } @Override protected void updateHistory(MercurialRevision rev, HgRoot root) { rev.setBisectStatus(Status.BAD); super.updateHistory(rev, root); } @Override String callBisect(final HgRoot root, final ChangeSet changeSet) throws HgException { setBisectStarted(true); return HgBisectClient.markBad(root, changeSet); } }BisectMarkGoodAction.java000066400000000000000000000031771173713500500346600ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2010 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - Implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import com.vectrace.MercurialEclipse.commands.HgBisectClient; import com.vectrace.MercurialEclipse.commands.HgBisectClient.Status; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian */ final class BisectMarkGoodAction extends BisectAbstractAction { BisectMarkGoodAction(MercurialHistoryPage mercurialHistoryPage) { super(Messages.BisectMarkGoodAction_markSelectionAsGood, mercurialHistoryPage); this.setDescription(Messages.BisectMarkGoodAction_markSelectionDescription + Messages.BisectMarkGoodAction_markSelectionDescription2); } @Override protected void updateHistory(MercurialRevision rev, HgRoot root) { rev.setBisectStatus(Status.GOOD); super.updateHistory(rev, root); } @Override public boolean isEnabled() { return isBisectStarted(); } @Override String callBisect(HgRoot root, ChangeSet cs) throws HgException { setBisectStarted(true); return HgBisectClient.markGood(root, cs); } }BisectResetAction.java000066400000000000000000000027021173713500500342300ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2010 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - Implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import com.vectrace.MercurialEclipse.commands.HgBisectClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian */ final class BisectResetAction extends BisectAbstractAction { BisectResetAction(MercurialHistoryPage mercurialHistoryPage) { super(Messages.BisectResetAction_name, mercurialHistoryPage); this.setDescription(Messages.BisectResetAction_description + Messages.BisectResetAction_description2); } @Override public boolean isEnabled() { return isBisectStarted(); } @Override String callBisect(HgRoot root, ChangeSet cs) throws HgException { setBisectStarted(false); return HgBisectClient.reset(root); } @Override protected boolean checkDirty(HgRoot root) throws HgException { return false; } }ChangePathsTableProvider.java000066400000000000000000000175011173713500500355310ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2004, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.history; import java.util.List; import java.util.WeakHashMap; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class ChangePathsTableProvider extends TableViewer { private static final FileStatus[] EMPTY_CHANGE_PATHS = new FileStatus[0]; private final ChangedPathsPage page; private final ChangePathsTableContentProvider contentProvider; public ChangePathsTableProvider(Composite parent, ChangedPathsPage page) { super(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); this.page = page; contentProvider = new ChangePathsTableContentProvider(page); setContentProvider(contentProvider); setLabelProvider(new ChangePathLabelProvider(page, this)); GridData data = new GridData(GridData.FILL_BOTH); final Table table = (Table) getControl(); table.setHeaderVisible(false); table.setLinesVisible(true); table.setLayoutData(data); } public int getElementsCount(){ MercurialRevision revision = page.getCurrentRevision(); if(revision == null || !revision.isFile()){ return 0; } return contentProvider.getElements(revision).length; } private static class ChangePathLabelProvider extends DecoratingLabelProvider implements ITableLabelProvider { private final ChangedPathsPage page; private final ChangePathsTableProvider tableProvider; public ChangePathLabelProvider(ChangedPathsPage page, ChangePathsTableProvider tableProvider) { super(new SimpleLabelImageProvider(), PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()); this.page = page; this.tableProvider = tableProvider; } public Image getColumnImage(Object element, int columnIndex) { if (!(element instanceof FileStatus)) { return null; } return getImage(element); } public String getColumnText(Object element, int columnIndex) { if (!(element instanceof FileStatus)) { return null; } return getText(element); } @Override public Font getFont(Object element) { if (!(element instanceof FileStatus)) { return null; } MercurialRevision revision = page.getCurrentRevision(); if(revision == null || !revision.isFile()){ return null; } IPath basePath = ResourceUtils.getPath(revision.getResource()); IPath currentPath = ((FileStatus) element).getAbsolutePath(); if(basePath.equals(currentPath) && tableProvider.getElementsCount() > 1) { // highlight current file in the changeset, if there are more files return JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT); } return JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT); } } private static class ChangePathsTableContentProvider implements IStructuredContentProvider { private final WeakHashMap revToFiles; private final ChangedPathsPage page; private Viewer viewer; private boolean disposed; public ChangePathsTableContentProvider(ChangedPathsPage page) { this.page = page; revToFiles = new WeakHashMap(); } public Object[] getElements(Object inputElement) { if (!this.page.isShowChangePaths()) { return EMPTY_CHANGE_PATHS; } MercurialRevision rev = (MercurialRevision) inputElement; FileStatus[] fileStatus; synchronized(revToFiles){ fileStatus = revToFiles.get(rev); } if(fileStatus != null){ return fileStatus; } fetchPaths(rev); // but sometimes hg returns a null version map... return EMPTY_CHANGE_PATHS; } private void fetchPaths(final MercurialRevision rev) { final MercurialHistory history = page.getMercurialHistory(); final ChangeSet [] cs = new ChangeSet[1]; Job.getJobManager().cancel(ChangePathsTableContentProvider.class); Job pathJob = new Job(NLS.bind( Messages.ChangePathsTableProvider_retrievingAffectedPaths, rev.getChangeSet())) { @Override protected IStatus run(IProgressMonitor monitor) { synchronized(revToFiles){ if(revToFiles.get(rev) != null || monitor.isCanceled()){ return Status.CANCEL_STATUS; } } try { cs[0] = HgLogClient.getLogWithBranchInfo(rev, history, monitor); } catch (HgException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } return monitor.isCanceled()? Status.CANCEL_STATUS : Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return ChangePathsTableContentProvider.class == family; } }; pathJob.setRule(new ExclusiveHistoryRule()); pathJob.addJobChangeListener(new JobChangeAdapter(){ @Override public void done(IJobChangeEvent event) { if(!event.getResult().isOK()){ return; } FileStatus[] changedFiles = EMPTY_CHANGE_PATHS; ChangeSet fullCs = cs[0]; if(fullCs != null) { ChangeSet revCs = rev.getChangeSet(); // TODO this is a workaround: we copy some info from freshly retrieved cs // because this data is NOT currently available in the history view changesets (different template) // but it is nice to show it in the properties view revCs.setTags(fullCs.getTags()); revCs.setTagsStr(fullCs.getTagsStr()); List list = fullCs.getChangedFiles(); revCs.setChangedFiles(list); changedFiles = list.toArray(new FileStatus[list.size()]); if(changedFiles.length == 0){ changedFiles = EMPTY_CHANGE_PATHS; } } synchronized(revToFiles){ if(!revToFiles.containsKey(rev)) { revToFiles.put(rev, changedFiles); } } if(disposed){ return; } Runnable refresh = new Runnable() { public void run() { if(!disposed && viewer != null) { viewer.refresh(); } } }; Display.getDefault().asyncExec(refresh); } }); if(!disposed) { page.getHistoryPage().scheduleInPage(pathJob); } } public void dispose() { disposed = true; synchronized(revToFiles){ revToFiles.clear(); } } public void inputChanged(Viewer viewer1, Object oldInput, Object newInput) { this.viewer = viewer1; } } } ChangeSetComparator.java000066400000000000000000000021741173713500500345520ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import java.util.Comparator; import com.vectrace.MercurialEclipse.model.ChangeSet; public class ChangeSetComparator implements Comparator { public int compare(ChangeSet o1, ChangeSet o2) { int result = o2.getChangesetIndex() - o1.getChangesetIndex(); // we need to cover the situation when repo-indices are the same if (result == 0 && o1.getDateString() != null && o2.getDateString() != null) { int dateCompare = o2.getRealDate().compareTo(o1.getRealDate()); if (dateCompare != 0) { result = dateCompare; } } return result; } }ChangedPathsPage.java000066400000000000000000000571761173713500500340230ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - reference * Andrei Loskutov - bug fixes * Bjoern Stachmann - diff viewer *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.TextViewer; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.team.ui.history.IHistoryPageSite; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.actions.BaseSelectionListenerAction; import org.eclipse.ui.part.IPageSite; import org.eclipse.ui.progress.UIJob; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.HgRootRule; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.utils.StringUtils; import com.vectrace.MercurialEclipse.wizards.Messages; public class ChangedPathsPage { private static final String IMG_COMMENTS = "comments.gif"; //$NON-NLS-1$ private static final String IMG_DIFFS = "diffs.gif"; //$NON-NLS-1$ private static final String IMG_AFFECTED_PATHS_FLAT_MODE = "flatLayout.gif"; //$NON-NLS-1$ private SashForm mainSashForm; private SashForm innerSashForm; private boolean showComments; private boolean showAffectedPaths; private boolean showDiffs; private boolean wrapCommentsText; private ChangePathsTableProvider changePathsViewer; private TextViewer commentTextViewer; private TextViewer diffTextViewer; private final IPreferenceStore store = MercurialEclipsePlugin.getDefault() .getPreferenceStore(); private ToggleAffectedPathsOptionAction[] toggleAffectedPathsLayoutActions; private final MercurialHistoryPage page; private final Color colorBlue; private final Color colorGreen; private final Color colorBlack; private final Color colorRed; public ChangedPathsPage(MercurialHistoryPage page, Composite parent) { this.page = page; Display display = parent.getDisplay(); colorBlue = display.getSystemColor(SWT.COLOR_BLUE); colorGreen = display.getSystemColor(SWT.COLOR_DARK_GREEN); colorBlack = display.getSystemColor(SWT.COLOR_BLACK); colorRed = display.getSystemColor(SWT.COLOR_DARK_RED); init(parent); } private void init(Composite parent) { this.showComments = store.getBoolean(PREF_SHOW_COMMENTS); this.wrapCommentsText = store.getBoolean(PREF_WRAP_COMMENTS); this.showAffectedPaths = store.getBoolean(PREF_SHOW_PATHS); this.showDiffs = store.getBoolean(PREF_SHOW_DIFFS); this.mainSashForm = new SashForm(parent, SWT.VERTICAL); this.mainSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); this.toggleAffectedPathsLayoutActions = new ToggleAffectedPathsOptionAction[] { new ToggleAffectedPathsOptionAction(this, "HistoryView.affectedPathsHorizontalLayout", //$NON-NLS-1$ PREF_AFFECTED_PATHS_LAYOUT, LAYOUT_HORIZONTAL), new ToggleAffectedPathsOptionAction(this, "HistoryView.affectedPathsVerticalLayout", //$NON-NLS-1$ PREF_AFFECTED_PATHS_LAYOUT, LAYOUT_VERTICAL), }; } public void createControl() { createRevisionDetailViewers(); addSelectionListeners(); contributeActions(); } private void addSelectionListeners() { page.getTableViewer().addSelectionChangedListener( new ISelectionChangedListener() { private Object currentLogEntry; private int currentNumberOfSelectedElements; public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); Object logEntry = ((IStructuredSelection) selection).getFirstElement(); int nrOfSelectedElements = ((IStructuredSelection) selection).size(); if (logEntry != currentLogEntry || nrOfSelectedElements != currentNumberOfSelectedElements) { this.currentLogEntry = logEntry; this.currentNumberOfSelectedElements = nrOfSelectedElements; updatePanels(selection); } } }); changePathsViewer.addSelectionChangedListener(new ISelectionChangedListener() { private Object selectedChangePath; public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); FileStatus changePath = (FileStatus) selection.getFirstElement(); if (changePath != selectedChangePath) { selectedChangePath = changePath; selectInDiffViewerAndScroll(changePath); } } }); } private void selectInDiffViewerAndScroll(FileStatus selectedChangePath) { if(selectedChangePath == null) { return; } String pathAsString = selectedChangePath.getRootRelativePath().toString(); // Note: this is a plain text search for the path in the diff text // This could be refined with a regular expression matching the // whole diff line. int offset = diffTextViewer.getDocument().get().indexOf(pathAsString); if(offset != -1) { selectInDiffViewerAndScrollToPosition(offset, pathAsString.length()); } } private void selectInDiffViewerAndScrollToPosition(int offset, int length) { try { diffTextViewer.setSelectedRange(offset, length); int line = diffTextViewer.getDocument().getLineOfOffset(offset); diffTextViewer.setTopIndex(line); } catch (BadLocationException e) { MercurialEclipsePlugin.logError(e); } } /** * Creates the detail viewers (commentViewer, changePathsViewer and diffViewer) shown * below the table of revisions. Will rebuild these viewers after a layout change. */ private void createRevisionDetailViewers() { disposeExistingViewers(); int layout = store.getInt(PREF_AFFECTED_PATHS_LAYOUT); int swtOrientation = layout == LAYOUT_HORIZONTAL ? SWT.HORIZONTAL: SWT.VERTICAL; innerSashForm = new SashForm(mainSashForm, swtOrientation); createText(innerSashForm); changePathsViewer = new ChangePathsTableProvider(innerSashForm, this); createDiffViewer(innerSashForm); setViewerVisibility(); refreshLayout(); } private void disposeExistingViewers() { if (innerSashForm != null && !innerSashForm.isDisposed()) { // disposes ALL child widgets too innerSashForm.dispose(); } } private void createDiffViewer(SashForm parent) { SourceViewer sourceViewer = new SourceViewer(parent, null, null, true, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.READ_ONLY); sourceViewer.getTextWidget().setIndent(2); diffTextViewer = sourceViewer; diffTextViewer.setDocument(new Document()); } private void updatePanels(ISelection selection) { if (!(selection instanceof IStructuredSelection)) { clearTextChangePathsAndDiffTextViewers(); return; } Object[] selectedElememts = ((IStructuredSelection) selection).toArray(); if (selectedElememts.length == 1) { MercurialRevision revision = (MercurialRevision) selectedElememts[0]; updatePanelsAfterSelectionOf(revision); } else if (selectedElememts.length == 2) { MercurialRevision youngerRevision = (MercurialRevision) selectedElememts[0]; MercurialRevision olderRevision = (MercurialRevision) selectedElememts[1]; updatePanelsAfterSelectionOf(olderRevision, youngerRevision); } else { clearTextChangePathsAndDiffTextViewers(); } } private void clearTextChangePathsAndDiffTextViewers() { commentTextViewer.setDocument(new Document("")); //$NON-NLS-1$ changePathsViewer.setInput(null); diffTextViewer.setDocument(new Document("")); //$NON-NLS-1$ } private void updatePanelsAfterSelectionOf(MercurialRevision revision) { commentTextViewer.setDocument(new Document(revision.getChangeSet().getComment())); changePathsViewer.setInput(revision); updateDiffPanelFor(revision, null); } private void updatePanelsAfterSelectionOf(MercurialRevision firstRevision, MercurialRevision secondRevision) { // TODO update to combined comment commentTextViewer.setDocument(new Document()); // TODO update to combined file list changePathsViewer.setInput(null); updateDiffPanelFor(firstRevision, secondRevision); } private void updateDiffPanelFor(final MercurialRevision entry, final MercurialRevision secondEntry) { if(!showDiffs) { diffTextViewer.setDocument(new Document()); return; } Job.getJobManager().cancel(FetchDiffJob.class); diffTextViewer.setDocument(new Document()); final HgRoot hgRoot = entry.getChangeSet().getHgRoot(); FetchDiffJob job = new FetchDiffJob(entry, secondEntry, hgRoot); // give the changePathsViewer a chance to fetch the data first getHistoryPage().scheduleInPage(job, 100); } private void applyLineColoringToDiffViewer(IProgressMonitor monitor) { IDocument document = diffTextViewer.getDocument(); int nrOfLines = document.getNumberOfLines(); Display display = diffTextViewer.getControl().getDisplay(); for (int lineNo = 0; lineNo < nrOfLines && !monitor.isCanceled();) { // color lines 100 at a time to allow user cancellation in between try { diffTextViewer.getControl().setRedraw(false); for (int i = 0; i < 100 && lineNo < nrOfLines; i++, lineNo++) { try { IRegion lineInformation = document.getLineInformation(i); int offset = lineInformation.getOffset(); int length = lineInformation.getLength(); Color lineColor = getDiffLineColor(document.get( offset, length)); diffTextViewer.setTextColor(lineColor, offset, length, true); } catch (BadLocationException e) { MercurialEclipsePlugin.logError(e); } } } finally { diffTextViewer.getControl().setRedraw(true); } // don't dispatch event with redraw disabled & re-check control status afterwards ! while(display.readAndDispatch()){ // give user the chance to break the job } if (diffTextViewer.getControl() == null || diffTextViewer.getControl().isDisposed()) { return; } } } private Color getDiffLineColor(String line) { if(StringUtils.isEmpty(line)){ return colorBlack; } if(line.startsWith("diff ")) { return colorBlue; } else if(line.startsWith("+++ ")) { return colorBlue; } else if(line.startsWith("--- ")) { return colorBlue; } else if(line.startsWith("@@ ")) { return colorBlue; } else if(line.startsWith("new file mode")) { return colorBlue; } else if(line.startsWith("\\ ")) { return colorBlue; } else if(line.startsWith("+")) { return colorGreen; } else if(line.startsWith("-")) { return colorRed; } else { return colorBlack; } } /** * @return may return null */ MercurialRevision getCurrentRevision() { return (MercurialRevision) changePathsViewer.getInput(); } /** * Create the TextViewer for the logEntry comments */ private void createText(Composite parent) { SourceViewer result = new SourceViewer(parent, null, null, true, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.READ_ONLY); result.getTextWidget().setIndent(2); this.commentTextViewer = result; // Create actions for the text editor (copy and select all) final TextViewerAction copyAction = new TextViewerAction( this.commentTextViewer, ITextOperationTarget.COPY); copyAction.setText(Messages.getString("HistoryView.copy")); this.commentTextViewer .addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { copyAction.update(); } }); final TextViewerAction selectAllAction = new TextViewerAction( this.commentTextViewer, ITextOperationTarget.SELECT_ALL); selectAllAction.setText(Messages.getString("HistoryView.selectAll")); IHistoryPageSite parentSite = getHistoryPageSite(); IPageSite pageSite = parentSite.getWorkbenchPageSite(); IActionBars actionBars = pageSite.getActionBars(); actionBars.setGlobalActionHandler(ITextEditorActionConstants.COPY, copyAction); actionBars.setGlobalActionHandler( ITextEditorActionConstants.SELECT_ALL, selectAllAction); actionBars.updateActionBars(); // Contribute actions to popup menu for the comments area MenuManager menuMgr = new MenuManager(); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager menuMgr1) { menuMgr1.add(copyAction); menuMgr1.add(selectAllAction); } }); StyledText text = this.commentTextViewer.getTextWidget(); Menu menu = menuMgr.createContextMenu(text); text.setMenu(menu); } private void contributeActions() { Action toggleShowComments = new Action(Messages .getString("HistoryView.showComments"), //$NON-NLS-1$ MercurialEclipsePlugin.getImageDescriptor(IMG_COMMENTS)) { @Override public void run() { showComments = isChecked(); setViewerVisibility(); store.setValue(PREF_SHOW_COMMENTS, showComments); } }; toggleShowComments.setChecked(showComments); Action toggleShowDiffs = new Action(Messages // TODO create new text & image .getString("HistoryView.showDiffs"), //$NON-NLS-1$ MercurialEclipsePlugin.getImageDescriptor(IMG_DIFFS)) { @Override public void run() { showDiffs = isChecked(); setViewerVisibility(); store.setValue(PREF_SHOW_DIFFS, showDiffs); } }; toggleShowDiffs.setChecked(showDiffs); // Toggle wrap comments action Action toggleWrapCommentsAction = new Action(Messages .getString("HistoryView.wrapComments")) { @Override public void run() { wrapCommentsText = isChecked(); setViewerVisibility(); store.setValue(PREF_WRAP_COMMENTS, wrapCommentsText); } }; toggleWrapCommentsAction.setChecked(wrapCommentsText); // Toggle path visible action Action toggleShowAffectedPathsAction = new Action(Messages .getString("HistoryView.showAffectedPaths"), //$NON-NLS-1$ MercurialEclipsePlugin .getImageDescriptor(IMG_AFFECTED_PATHS_FLAT_MODE)) { @Override public void run() { showAffectedPaths = isChecked(); setViewerVisibility(); store.setValue(PREF_SHOW_PATHS, showAffectedPaths); } }; toggleShowAffectedPathsAction.setChecked(showAffectedPaths); IHistoryPageSite parentSite = getHistoryPageSite(); IPageSite pageSite = parentSite.getWorkbenchPageSite(); IActionBars actionBars = pageSite.getActionBars(); // Contribute toggle text visible to the toolbar drop-down IMenuManager actionBarsMenu = actionBars.getMenuManager(); actionBarsMenu.add(toggleWrapCommentsAction); actionBarsMenu.add(new Separator()); actionBarsMenu.add(toggleShowComments); actionBarsMenu.add(toggleShowAffectedPathsAction); actionBarsMenu.add(toggleShowDiffs); actionBarsMenu.add(new Separator()); for (int i = 0; i < toggleAffectedPathsLayoutActions.length; i++) { actionBarsMenu.add(toggleAffectedPathsLayoutActions[i]); } // Create the local tool bar IToolBarManager tbm = actionBars.getToolBarManager(); tbm.add(toggleShowComments); tbm.add(toggleShowAffectedPathsAction); tbm.add(toggleShowDiffs); tbm.update(false); actionBars.updateActionBars(); final BaseSelectionListenerAction openAction = page.getOpenAction(); final BaseSelectionListenerAction openEditorAction = page.getOpenEditorAction(); final BaseSelectionListenerAction compareWithCurrent = page.getCompareWithCurrentAction(); final BaseSelectionListenerAction compareWithPrevious = page.getCompareWithPreviousAction(); final BaseSelectionListenerAction compareWithOther = page.getCompareWithOtherAction(); final BaseSelectionListenerAction actionRevert = page.getRevertAction(); final BaseSelectionListenerAction focusOnSelected = page.getFocusOnSelectedFileAction(); changePathsViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { FileStatus fileStatus = (FileStatus) ((IStructuredSelection) event.getSelection()).getFirstElement(); MercurialRevision derived = getDerivedRevision(fileStatus, getCurrentRevision()); if(derived == null){ return; } StructuredSelection selection = new StructuredSelection(new Object[]{derived, fileStatus}); compareWithPrevious.selectionChanged(selection); compareWithPrevious.run(); } }); // Contribute actions to popup menu final MenuManager menuMgr = new MenuManager(); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager menuMgr1) { IStructuredSelection selection = (IStructuredSelection) changePathsViewer.getSelection(); if(selection.isEmpty()){ return; } FileStatus fileStatus = (FileStatus) selection.getFirstElement(); MercurialRevision base = getCurrentRevision(); MercurialRevision derived = getDerivedRevision(fileStatus, base); if(derived == null){ // XXX currently files outside workspace are not supported... return; } selection = new StructuredSelection(derived); openAction.selectionChanged(selection); focusOnSelected.selectionChanged(selection); openEditorAction.selectionChanged(selection); compareWithCurrent.selectionChanged(selection); compareWithOther.selectionChanged(selection); selection = new StructuredSelection(new Object[]{derived, fileStatus}); compareWithPrevious.selectionChanged(selection); menuMgr1.add(openAction); menuMgr1.add(openEditorAction); menuMgr1.add(focusOnSelected); menuMgr1.add(new Separator(IWorkbenchActionConstants.GROUP_FILE)); menuMgr1.add(compareWithCurrent); menuMgr1.add(compareWithPrevious); menuMgr1.add(compareWithOther); menuMgr1.add(new Separator()); selection = new StructuredSelection(new Object[]{derived}); actionRevert.selectionChanged(selection); menuMgr1.add(actionRevert); menuMgr1.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } }); menuMgr.setRemoveAllWhenShown(true); changePathsViewer.getTable().setMenu(menuMgr.createContextMenu(changePathsViewer.getTable())); } private void setViewerVisibility() { boolean lowerPartVisible = showAffectedPaths || showComments || showDiffs; mainSashForm.setMaximizedControl(lowerPartVisible ? null : getChangesetsTableControl()); if(!lowerPartVisible) { return; } int[] weights = { showComments ? 1 : 0, // showAffectedPaths ? 1 : 0, // showDiffs ? 1 : 0 // }; innerSashForm.setWeights(weights); commentTextViewer.getTextWidget().setWordWrap(wrapCommentsText); updatePanels(page.getTableViewer().getSelection()); } private Composite getChangesetsTableControl() { return page.getTableViewer().getControl().getParent(); } public void refreshLayout() { innerSashForm.layout(); int[] weights = mainSashForm.getWeights(); if (weights != null && weights.length == 2) { mainSashForm.setWeights(weights); } mainSashForm.layout(); } /** * @author Andrei */ private final class FetchDiffJob extends Job { private final MercurialRevision entry; private final MercurialRevision secondEntry; private final HgRoot hgRoot; private FetchDiffJob(MercurialRevision entry, MercurialRevision secondEntry, HgRoot hgRoot) { super("Fetching the diff data"); this.entry = entry; this.secondEntry = secondEntry; this.hgRoot = hgRoot; setRule(new HgRootRule(hgRoot)); } @Override protected IStatus run(IProgressMonitor monitor) { try { String diff = HgPatchClient.getDiff(hgRoot, entry, secondEntry); if (!monitor.isCanceled() && diffTextViewer.getControl() != null && !diffTextViewer.getControl().isDisposed()) { getHistoryPage().scheduleInPage(new UpdateDiffViewerJob(diff)); } } catch (HgException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return FetchDiffJob.class == family; } } class UpdateDiffViewerJob extends UIJob { private final String diff; public UpdateDiffViewerJob(String diff) { super(diffTextViewer.getControl().getDisplay(), "Updating diff pane"); this.diff = diff; } @Override public IStatus runInUIThread(IProgressMonitor monitor) { if (diffTextViewer.getControl() == null || diffTextViewer.getControl().isDisposed()) { return Status.CANCEL_STATUS; } diffTextViewer.setDocument(new Document(diff)); applyLineColoringToDiffViewer(monitor); return monitor.isCanceled()? Status.CANCEL_STATUS : Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return FetchDiffJob.class == family; } } public static class ToggleAffectedPathsOptionAction extends Action { private final ChangedPathsPage page; private final String preferenceName; private final int value; public ToggleAffectedPathsOptionAction(ChangedPathsPage page, String label, String preferenceName, int value) { super(Messages.getString(label), AS_RADIO_BUTTON); this.page = page; this.preferenceName = preferenceName; this.value = value; IPreferenceStore store = MercurialEclipsePlugin.getDefault() .getPreferenceStore(); setChecked(value == store.getInt(preferenceName)); } @Override public void run() { if (isChecked()) { MercurialEclipsePlugin.getDefault().getPreferenceStore() .setValue(preferenceName, value); page.createRevisionDetailViewers(); } } } public MercurialHistoryPage getHistoryPage() { return page; } public IHistoryPageSite getHistoryPageSite() { return page.getHistoryPageSite(); } public Composite getControl() { return mainSashForm; } public boolean isShowChangePaths() { return showAffectedPaths; } public MercurialHistory getMercurialHistory() { return page.getMercurialHistory(); } /** * @return might return null, if the file is outside Eclipse workspace */ private MercurialRevision getDerivedRevision(FileStatus fileStatus, MercurialRevision base) { IFile file = ResourceUtils.getFileHandle(fileStatus.getAbsolutePath()); if(file == null){ return null; } MercurialRevision derived = new MercurialRevision(base.getChangeSet(), base .getGChangeSet(), file, null, null); return derived; } } CompareRevisionAction.java000066400000000000000000000120171173713500500351210ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.actions.BaseSelectionListenerAction; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.utils.CompareUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; class CompareRevisionAction extends BaseSelectionListenerAction { private Object[] selection; private final MercurialHistoryPage page; private boolean enableCompareWithPrev; CompareRevisionAction(String text, MercurialHistoryPage page) { super(text); this.page = page; setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/compare_with_local.gif")); //$NON-NLS-1$ } void setCompareWithPrevousEnabled(boolean enable){ this.enableCompareWithPrev = enable; } @Override public void run() { final MercurialRevisionStorage [] right = new MercurialRevisionStorage [1]; final MercurialRevisionStorage [] left = new MercurialRevisionStorage [1]; final Job job = new Job(Messages.CompareRevisionAction_retrievingDiffData) { @Override public IStatus run(IProgressMonitor monitor) { try { if(selection.length > 0 && !monitor.isCanceled()){ left[0] = getStorage((MercurialRevision) selection[0], monitor); if(selection.length > 1 && !monitor.isCanceled()){ if(enableCompareWithPrev && selection[1] instanceof FileStatus){ FileStatus clickedFileStatus = (FileStatus) selection[1]; ChangeSet cs = left[0].getChangeSet(); IPath fileAbsPath = cs.getHgRoot().toAbsolute(clickedFileStatus.getRootRelativePath()); IFile file = ResourceUtils.getFileHandle(fileAbsPath); if(file != null) { right[0] = MercurialUtilities.getParentRevision(cs, file); } } else if(selection[1] instanceof MercurialRevision) { right[0] = getStorage((MercurialRevision) selection[1], monitor); } } else if(enableCompareWithPrev){ ChangeSet cs = left[0].getChangeSet(); IFile file = left[0].getResource(); right[0] = MercurialUtilities.getParentRevision(cs, file); } } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } if(monitor.isCanceled()){ return Status.CANCEL_STATUS; } return Status.OK_STATUS; } }; job.addJobChangeListener(new JobChangeAdapter(){ @Override public void done(IJobChangeEvent event) { if(left[0] == null || !event.getResult().isOK()){ return; } CompareUtils.openEditor(left[0], right[0], false); } }); job.schedule(); } @Override protected boolean updateSelection(IStructuredSelection sSelection) { if(sSelection.size() != 1 && sSelection.size() != 2){ return false; } if(sSelection.size() == 1){ Object element = sSelection.getFirstElement(); if(element instanceof MercurialRevision){ MercurialRevision rev = (MercurialRevision) element; if(rev.getResource() instanceof IFile){ selection = sSelection.toArray(); return true; } } return false; } else if(enableCompareWithPrev && sSelection.size() == 2){ selection = sSelection.toArray(); return sSelection.toArray()[1] instanceof FileStatus; } selection = sSelection.toArray(); return true; } /** * this can take a lot of time, and UI must take care that it will not be frozen until * the info is fetched... * @param monitor */ private MercurialRevisionStorage getStorage(MercurialRevision rev, IProgressMonitor monitor) throws CoreException { if(rev.getParent() == null){ // see issue #10302: this is a dirty trick to make sure to get content even // if the file was renamed/copied. HgLogClient.getLogWithBranchInfo(rev, page.getMercurialHistory(), monitor); } return (MercurialRevisionStorage) rev.getStorage(monitor); } }ExclusiveHistoryRule.java000066400000000000000000000021441173713500500350370ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.jobs.ISchedulingRule; import com.vectrace.MercurialEclipse.team.cache.HgRootRule; /** * A rule which disallows parallel execution of jobs using it */ public final class ExclusiveHistoryRule implements ISchedulingRule { public boolean isConflicting(ISchedulingRule rule) { return contains(rule); } public boolean contains(ISchedulingRule rule) { return rule instanceof ExclusiveHistoryRule || rule instanceof IResource || rule instanceof HgRootRule; } }FileStatusDecorator.java000066400000000000000000000037161173713500500346120ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelProvider; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.FileStatus.Action; import com.vectrace.MercurialEclipse.team.DecoratorImages; public class FileStatusDecorator extends LabelProvider implements ILightweightLabelDecorator { public static final String ID = "com.vectrace.MercurialEclipse.history.FileStatusDecorator"; //$NON-NLS-1$ @Override public void addListener(ILabelProviderListener listener) { // noop } public void decorate(Object element, IDecoration decoration) { if (!(element instanceof FileStatus)) { return; } final Action action = ((FileStatus) element).getAction(); ImageDescriptor overlay = null; if(action == null){ overlay = DecoratorImages.NOT_TRACKED; } else { switch(action){ case ADDED: overlay = DecoratorImages.ADDED; break; case MODIFIED: overlay = DecoratorImages.MODIFIED; break; case REMOVED: overlay = DecoratorImages.REMOVED; break; case COPIED: overlay = DecoratorImages.COPIED; break; case MOVED: overlay = DecoratorImages.MOVED; break; } } decoration.addOverlay(overlay); } } GraphLogTableViewer.java000066400000000000000000000156631173713500500345250ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.LineAttributes; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableItem; import com.vectrace.MercurialEclipse.commands.HgBisectClient.Status; import com.vectrace.MercurialEclipse.model.GChangeSet; import com.vectrace.MercurialEclipse.model.GChangeSet.Edge; import com.vectrace.MercurialEclipse.model.GChangeSet.EdgeList; import com.vectrace.MercurialEclipse.model.Signature; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialUtilities; public class GraphLogTableViewer extends TableViewer { private final List colours = new ArrayList(); private final MercurialHistoryPage mhp; private final Color mergeBack; private final Color mergeFore; public GraphLogTableViewer(Composite parent, int style, MercurialHistoryPage mercurialHistoryPage) { super(parent, style); this.mhp = mercurialHistoryPage; getTable().addListener(SWT.PaintItem, new Listener() { public void handleEvent(final Event event) { paint(event); } }); Display display = parent.getDisplay(); colours.add(display.getSystemColor(SWT.COLOR_GREEN)); colours.add(display.getSystemColor(SWT.COLOR_BLUE)); colours.add(display.getSystemColor(SWT.COLOR_RED)); colours.add(display.getSystemColor(SWT.COLOR_MAGENTA)); colours.add(display.getSystemColor(SWT.COLOR_GRAY)); colours.add(display.getSystemColor(SWT.COLOR_DARK_YELLOW)); colours.add(display.getSystemColor(SWT.COLOR_DARK_MAGENTA)); colours.add(display.getSystemColor(SWT.COLOR_DARK_CYAN)); colours.add(display.getSystemColor(SWT.COLOR_DARK_GRAY)); colours.add(display.getSystemColor(SWT.COLOR_DARK_GREEN)); colours.add(display.getSystemColor(SWT.COLOR_DARK_RED)); // TODO add pref store listener mergeBack = MercurialUtilities .getColorPreference(MercurialPreferenceConstants.PREF_HISTORY_MERGE_CHANGESET_BACKGROUND); mergeFore = MercurialUtilities .getColorPreference(MercurialPreferenceConstants.PREF_HISTORY_MERGE_CHANGESET_FOREGROUND); } protected void paint(Event event) { TableItem tableItem = (TableItem) event.item; if (event.index != 0) { return; } MercurialRevision rev = (MercurialRevision) tableItem.getData(); GChangeSet gcs = rev.getGChangeSet(); if (gcs != null) { paint(event, gcs.getBefore(), 0); paint(event, gcs.getMiddle(), 1); paint(event, gcs.getAfter(), 2); } final Table table = tableItem.getParent(); int from = rev.getRevision() - 1; int lastReqVersion = mhp.getMercurialHistory().getLastRequestedVersion(); if (from != lastReqVersion && from >= 0 && mhp.getMercurialHistory().getLastVersion() > 0) { if (tableItem.equals(table.getItems()[table.getItemCount() - 1])) { MercurialHistoryPage.RefreshMercurialHistory refreshJob = mhp.new RefreshMercurialHistory( from); refreshJob.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event1) { Display.getDefault().asyncExec(new Runnable() { public void run() { if (table.isDisposed()) { return; } table.redraw(); table.update(); } }); } }); mhp.scheduleInPage(refreshJob); } } // validate signed changesets Signature sig = rev.getSignature(); if (sig != null) { if (sig.validate()) { tableItem.setBackground(colours.get(0)); } else { tableItem.setBackground(colours.get(2)); } } if (mhp.getCurrentWorkdirChangeset() != null) { if (rev.getRevision() == mhp.getCurrentWorkdirChangeset().getChangesetIndex()) { tableItem.setFont(JFaceResources.getFontRegistry().getBold( JFaceResources.DEFAULT_FONT)); } } // bisect colorization Status bisectStatus = rev.getBisectStatus(); if (bisectStatus != null) { if (bisectStatus == Status.BAD) { tableItem.setBackground(colours.get(10)); } else { tableItem.setBackground(colours.get(9)); } } else { // use italic dark grey font for merge changesets if (rev.getChangeSet().isMerge()) { decorateMergeChangesets(tableItem); } } } private void decorateMergeChangesets(TableItem tableItem) { // Don't ask me why, but it seems that setting the font here causes strange // UI thread freeze periods on Windows. I guess that this causes another paint // requests... // tableItem.setFont(mergeFont); tableItem.setBackground(mergeBack); tableItem.setForeground(mergeFore); } private void paint(Event event, EdgeList edges, int i) { GC g = event.gc; g.setLineAttributes(new LineAttributes(2)); g.setLineStyle(SWT.LINE_SOLID); int div3 = event.height / 3; int y = event.y + div3 * i; int middle = event.y + (event.height / 2); for (Edge e : edges.getEdges()) { drawLine(event, g, div3, e.isFinish() ? middle : y, e, e.getTop(), e.getBottom()); if (e.isDot()) { fillOval(event, e); } } int[] jump = edges.getJump(); if (jump != null) { g.setLineStyle(SWT.LINE_DOT); g.setForeground(g.getDevice().getSystemColor(SWT.COLOR_BLACK)); g.drawLine(getX(event, jump[0]), middle, getX(event, jump[1]), middle); } } private void drawLine(Event event, GC g, int div3, int y, Edge e, int top, int bottom) { g.setForeground(getColor(event, e)); g.drawLine(getX(event, top), y, getX(event, bottom), y + div3); } private void fillOval(Event event, Edge e) { int size = 6; event.gc.setBackground(event.display.getSystemColor(SWT.COLOR_BLACK)); int halfSize = size / 2; int i = e.getTop(); if (e.isPlus()) { event.gc.drawOval(getX(event, i) - halfSize, event.y + (event.height / 2) - halfSize, size, size); } else { event.gc.fillOval(getX(event, i) - halfSize, event.y + (event.height / 2) - halfSize, size, size); } } private Color getColor(Event event, Edge edge) { return colours.get(edge.getLane() % colours.size()); } private int getX(Event event, int col) { return event.x + (8 * col) + 5; } }HistoryContentProposalProvider.java000066400000000000000000000074041173713500500371110ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import java.util.LinkedList; import java.util.List; import org.eclipse.jface.fieldassist.IContentProposal; import org.eclipse.jface.fieldassist.IContentProposalProvider; import com.vectrace.MercurialEclipse.dialogs.RevisionContentProposalProvider.ChangeSetContentProposal; import com.vectrace.MercurialEclipse.dialogs.RevisionContentProposalProvider.ContentType; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.utils.ChangeSetUtils; /** * @author andrei */ public class HistoryContentProposalProvider implements IContentProposalProvider { private final MercurialHistoryPage page; /** * @param page non null */ public HistoryContentProposalProvider(MercurialHistoryPage page) { this.page = page; } public IContentProposal[] getProposals(String contents, int position) { contents = contents.trim(); if(position > contents.length()) { position = contents.length(); } List result = new LinkedList(); List revisions = page.getMercurialHistory().getRevisions(); String filter = contents.substring(0, position).toLowerCase(); for (MercurialRevision revision : revisions) { ChangeSet changeSet = revision.getChangeSet(); if (changeSet.getName().startsWith(filter) || changeSet.getChangeset().startsWith(filter)) { result.add(new RevisionContentProposal(revision, ContentType.REVISION, null)); continue; } String author = revision.getAuthor(); if(author != null && author.toLowerCase().contains(filter)) { result.add(new RevisionContentProposal(revision, ContentType.AUTHOR, author)); continue; } String comment = revision.getComment(); if(comment != null && comment.toLowerCase().contains(filter)) { result.add(new RevisionContentProposal(revision, ContentType.SUMMARY, null)); continue; } String tags = ChangeSetUtils.getPrintableTagsString(revision.getChangeSet()); if(tags.toLowerCase().contains(filter)) { result.add(new RevisionContentProposal(revision, ContentType.TAG, tags)); continue; } String branch = revision.getChangeSet().getBranch(); if(branch != null && branch.toLowerCase().contains(filter)) { result.add(new RevisionContentProposal(revision, ContentType.BRANCH, branch)); continue; } String date = revision.getChangeSet().getDateString(); if(date != null && date.startsWith(filter)) { result.add(new RevisionContentProposal(revision, ContentType.DATE, date)); continue; } } return result.toArray(new IContentProposal[result.size()]); } public static class RevisionContentProposal extends ChangeSetContentProposal { private final MercurialRevision revision; /** * @param revision non null * @param type non null */ public RevisionContentProposal(MercurialRevision revision, ContentType type, String value) { super(revision.getChangeSet(), type, value); this.revision = revision; } /** * @return the revision, never null */ public MercurialRevision getRevision() { return revision; } @Override public String getContent() { return value == null? changeSet.getName() : value; } @Override protected int getMaxLineLength() { return 500; } } } MercurialHistory.java000066400000000000000000000351501173713500500341660ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.core.history.provider.FileHistory; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgBisectClient; import com.vectrace.MercurialEclipse.commands.HgBisectClient.Status; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.commands.HgTagClient; import com.vectrace.MercurialEclipse.commands.extensions.HgGLogClient; import com.vectrace.MercurialEclipse.commands.extensions.HgSigsClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.GChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Signature; import com.vectrace.MercurialEclipse.model.Tag; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author zingo */ public class MercurialHistory extends FileHistory { private static final class RevisionComparator implements Comparator, Serializable { private static final long serialVersionUID = 5305190339206751711L; public int compare(MercurialRevision o1, MercurialRevision o2) { int result = o2.getRevision() - o1.getRevision(); // we need to cover the situation when repo-indices are the same if (result == 0 && o1.getChangeSet().getDateString() != null && o2.getChangeSet().getDateString() != null) { result = o2.getChangeSet().getRealDate().compareTo( o1.getChangeSet().getRealDate()); } return result; } } private static final ChangeSetComparator CS_COMPARATOR = new ChangeSetComparator(); private static final RevisionComparator REV_COMPARATOR = new RevisionComparator(); private final IResource resource; private final HgRoot hgRoot; private final List revisions; private Tag[] tags; private final Map gChangeSets; private GChangeSet lastGCS; private int lastReqRevision; private boolean showTags; private boolean bisectStarted; /** * @param resource must be non null */ public MercurialHistory(IResource resource) { super(); Assert.isNotNull(resource); HgRoot root = MercurialTeamProvider.getHgRoot(resource); if(root != null && root.getIPath().equals(ResourceUtils.getPath(resource))){ this.resource = null; } else { this.resource = resource; } hgRoot = root; revisions = new ArrayList(); gChangeSets = new HashMap(); } /** * @param hgRoot must be non null */ public MercurialHistory(HgRoot hgRoot) { super(); Assert.isNotNull(hgRoot); this.resource = null; this.hgRoot = hgRoot; revisions = new ArrayList(); gChangeSets = new HashMap(); } /** * @return true if this is a history of the hg root, otherwise it's about any sibling of it */ boolean isRootHistory() { return resource == null; } public void setBisectStarted(boolean started){ this.bisectStarted = started; } public boolean isBisectStarted() { return bisectStarted; } /** * @param prev * @return a next revision int the history: revision wich is the successor of the given one (has * higher rev number) */ public MercurialRevision getNext(MercurialRevision prev){ // revisions are sorted descending: first has the highest rev number for (int i = 0; i < revisions.size(); i++) { if (revisions.get(i) == prev) { if(i > 0){ return revisions.get(i - 1); } } } return null; } /** * @param next * @return a previous revision int the history: revision wich is the ancestor of the given one * (has lower rev number) */ public MercurialRevision getPrev(MercurialRevision next){ // revisions are sorted descending: first has the highest rev number for (int i = 0; i < revisions.size(); i++) { if (revisions.get(i) == next) { if (i + 1 < revisions.size()) { return revisions.get(i + 1); } } } return null; } /** * @return last revision index requested for the current history, or zero if no * revisions was requested. */ public int getLastRequestedVersion() { return lastReqRevision; } public int getLastVersion() { if(revisions.isEmpty()) { return 0; } return revisions.get(revisions.size() - 1).getRevision(); } public IFileRevision[] getContributors(IFileRevision revision) { return null; } public IFileRevision getFileRevision(String id) { if (revisions.isEmpty()) { return null; } for (MercurialRevision rev : revisions) { if (rev.getContentIdentifier().equals(id)) { return rev; } } return null; } public IFileRevision[] getFileRevisions() { if (!revisions.isEmpty()) { return revisions.toArray(new MercurialRevision[revisions.size()]); } return new IFileRevision[0]; } public List getRevisions() { if (!revisions.isEmpty()) { return new ArrayList(revisions); } return Collections.emptyList(); } public IFileRevision[] getTargets(IFileRevision revision) { return new IFileRevision[0]; } public void refresh(IProgressMonitor monitor, int from) throws CoreException { if (from < 0) { return; } if (from == Integer.MAX_VALUE) { // We're getting revisions up to the latest one available. // So clear out the cached list, as it may contain revisions // that no longer exist (e.g. after a strip/rollback). revisions.clear(); gChangeSets.clear(); tags = null; lastReqRevision = 0; } // check if we have reached the bottom (initially = Integer.MAX_VALUE) if (from == lastReqRevision) { return; } IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); int logBatchSize = store.getInt(LOG_BATCH_SIZE); Map> map; IPath location; if(!isRootHistory()) { map = HgLogClient.getProjectLog(resource, logBatchSize, from, false); location = ResourceUtils.getPath(resource); } else { map = HgLogClient.getRootLog(hgRoot, logBatchSize, from, false); location = hgRoot.getIPath(); } // no result -> bottom reached if (map.isEmpty()) { lastReqRevision = from; return; } // still changesets there -> process Set localChangeSets = map.get(location); if (localChangeSets == null) { lastReqRevision = from; return; } // We need these to be in order for the GChangeSets to display properly SortedSet changeSets = new TreeSet(CS_COMPARATOR); changeSets.addAll(localChangeSets); if (revisions.size() < changeSets.size() || !(location.equals(ResourceUtils.getPath(revisions.get(0).getResource())))) { revisions.clear(); gChangeSets.clear(); } // Update graph data also in batch updateGraphData(changeSets, logBatchSize, from, store.getBoolean(ENABLE_FULL_GLOG)); if(!revisions.isEmpty()){ // in case of a particular data fetch before, we may still have some // temporary tags assigned to the last visible revision => cleanup it now MercurialRevision lastOne = revisions.get(revisions.size() - 1); lastOne.cleanupExtraTags(); } IResource revisionResource; if(isRootHistory()){ revisionResource = hgRoot.getResource(); } else { revisionResource = resource; } Map sigMap = getSignatures(); Map bisectMap = HgBisectClient.getBisectStatus(hgRoot); setBisectStarted(!bisectMap.isEmpty()); for (ChangeSet cs : changeSets) { Signature sig = !sigMap.isEmpty() ? sigMap.get(cs.getChangeset()) : null; Status bisectStatus = !bisectMap.isEmpty() ? bisectMap.get(cs.getChangeset()) : null; GChangeSet set = gChangeSets.get(Integer.valueOf(cs.getChangesetIndex())); revisions.add(new MercurialRevision(cs, set, revisionResource, sig, bisectStatus)); } Collections.sort(revisions, REV_COMPARATOR); lastReqRevision = from; if(showTags){ if(!isRootHistory()) { if(tags == null){ fetchTags(); } assignTagsToRevisions(); } } } private Map getSignatures() throws CoreException { // get signatures Map sigMap = new HashMap(); boolean sigcheck = "true".equals(HgClients.getPreference( PREF_SIGCHECK_IN_HISTORY, "false")); //$NON-NLS-1$ if (sigcheck) { if (!"false".equals(MercurialUtilities.getGpgExecutable())) { //$NON-NLS-1$ List sigs = HgSigsClient.getSigs(hgRoot); for (Signature signature : sigs) { sigMap.put(signature.getNodeId(), signature); } } } return sigMap; } private void fetchTags() throws HgException { // we need extra tag changesets for files/folders only. boolean withChangesets = !isRootHistory(); Tag[] tags2 = HgTagClient.getTags(hgRoot, withChangesets); SortedSet sorted = new TreeSet(); for (Tag tag : tags2) { if(!tag.isTip()){ sorted.add(tag); } } // tags are sorted naturally descending by cs revision tags = sorted.toArray(new Tag[sorted.size()]); } private void assignTagsToRevisions() { if(tags == null || tags.length == 0){ return; } int start = 0; // sorted ascending by revision for (Tag tag : tags) { int matchingRevision = getFirstMatchingRevision(tag, start); if(matchingRevision >= 0){ start = matchingRevision; revisions.get(matchingRevision).addTag(tag); } } } /** * @param tag * tag to search for * @param start * start index in the revisions array * @return first matching revision index in the revisions array, or -1 if no one * revision matches given tag */ private int getFirstMatchingRevision(Tag tag, int start) { String tagBranch = tag.getChangeSet().getBranch(); int tagRev = tag.getRevision(); // revisions are sorted descending by cs revision int lastRev = getLastRevision(tagBranch); for (int i = start; i <= lastRev; i++) { i = getNextRevision(i, tagBranch); int revision = revisions.get(i).getRevision(); // perfect match if(revision == tagRev){ return i; } // if tag rev is greater as greatest (first) revision, return the version, // because the last file version was created before the tag => so it // was the current one at the time the tag was created if(i == 0 && tagRev > revision){ return i; } // if tag rev is smaller as smallest (last) revision, return if(i == lastRev && tagRev < revision){ // fix for bug 10830 return -1; } // if tag rev is greater as current rev, return the version if(tagRev > revision){ return i; } } return -1; } /** * @param branch * may be null * @return internal index of the latest revision known for this branch, or -1 if there * are no matches */ private int getLastRevision(String branch) { for (int i = revisions.size() - 1; i >= 0; i--) { MercurialRevision rev = revisions.get(i); if(Branch.same(rev.getChangeSet().getBranch(), branch)){ return i; } } return -1; } /** * @param from * the first revision to start looking for * @param branch * may be null * @return internal index of the next revision (starting from given one) known for this * branch, or -1 if there are no matches */ private int getNextRevision(int from, String branch) { for (int i = from; i < revisions.size(); i++) { MercurialRevision rev = revisions.get(i); if(Branch.same(rev.getChangeSet().getBranch(), branch)){ return i; } } return -1; } private void updateGraphData(SortedSet changeSets, int logBatchSize, int from, boolean enableFullLog) { if(enableFullLog && !gChangeSets.isEmpty()){ return; } else if (!isRootHistory() && resource.getType() == IResource.FOLDER) { return; } logBatchSize = enableFullLog? 0 : logBatchSize; // put glog changesets in map for later referencing List gLogChangeSets; try { // the code below will produce sometimes bad graphs because the glog is re-set // each time we request the new portion of data. // the only reason why we use logBatchSize here and accept "bad" graphs is the performance if(!isRootHistory()) { gLogChangeSets = new HgGLogClient(resource, logBatchSize, from).getChangeSets(); } else { gLogChangeSets = new HgGLogClient(hgRoot, logBatchSize, from).getChangeSets(); } } catch (HgException e) { MercurialEclipsePlugin.logError(e); return; } if(!enableFullLog && !gLogChangeSets.isEmpty()){ GChangeSet firstNew = gLogChangeSets.get(0); GChangeSet lastOld = lastGCS; if(lastOld != null) { // a VERY primitive, wrong way to connect graphs. works only if there // is one active branch at given changeset time firstNew.clean(lastOld); } } for (GChangeSet gs : gLogChangeSets) { if (gs != null) { gChangeSets.put(Integer.valueOf(gs.getRev()), gs); } } if(!enableFullLog && !gLogChangeSets.isEmpty()) { lastGCS = gLogChangeSets.get(gLogChangeSets.size() - 1); } } /** * @param showTags true to show tagged changesets, even if they are not related to the * current file */ public void setEnableExtraTags(boolean showTags) { this.showTags = showTags; } } MercurialHistoryPage.java000066400000000000000000001315321173713500500347640ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * StefanC - some updates, code cleanup * Stefan Groschupf - logError * Subclipse project committers - reference * Charles O'Farrell - comparison diff * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - modifications *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import java.util.Iterator; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.fieldassist.ContentProposalAdapter; import org.eclipse.jface.fieldassist.IContentProposal; import org.eclipse.jface.fieldassist.IContentProposalListener; import org.eclipse.jface.fieldassist.IContentProposalListener2; import org.eclipse.jface.fieldassist.TextContentAdapter; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.revisions.Revision; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import org.eclipse.team.core.history.IFileHistory; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.ui.history.HistoryPage; import org.eclipse.team.ui.history.IHistoryView; import org.eclipse.team.ui.history.RevisionAnnotationController; import org.eclipse.ui.IActionBars; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IStorageEditorInput; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.actions.BaseSelectionListenerAction; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; import org.osgi.framework.Version; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.ExportAsBundleAction; import com.vectrace.MercurialEclipse.actions.MergeWithCurrentChangesetAction; import com.vectrace.MercurialEclipse.actions.OpenMercurialRevisionAction; import com.vectrace.MercurialEclipse.annotations.ShowAnnotationOperation; import com.vectrace.MercurialEclipse.dialogs.RevisionChooserDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.HistoryContentProposalProvider.RevisionContentProposal; import com.vectrace.MercurialEclipse.menu.StripHandler; import com.vectrace.MercurialEclipse.menu.UpdateJob; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.ActionRevert; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.wizards.BackoutWizard; import com.vectrace.MercurialEclipse.wizards.Messages; public class MercurialHistoryPage extends HistoryPage { private static final boolean ECLISPE_BEFORE_38 = Platform.getBundle("org.eclipse.ui.ide") .getVersion().compareTo(new Version(3, 8, 0)) < 0; public static final String REMOTE_MODE = null; private GraphLogTableViewer viewer; IResource resource; private HgRoot hgRoot; private ChangeLogContentProvider changeLogViewContentProvider; private MercurialHistory mercurialHistory; private RefreshMercurialHistory refreshFileHistoryJob; private ChangedPathsPage changedPaths; private ChangeSet currentWorkdirChangeset; private OpenMercurialRevisionAction openAction; private BaseSelectionListenerAction openEditorAction; private BaseSelectionListenerAction focusOnSelectedFileAction; private boolean showTags; private CompareRevisionAction compareWithCurrAction; private CompareRevisionAction compareWithPrevAction; private CompareRevisionAction compareWithOtherAction; private CompareRevisionAction compareTwo; private BaseSelectionListenerAction revertAction; private Action actionShowParentHistory; private final IAction bisectMarkGoodAction = new BisectMarkGoodAction(this); private final IAction bisectMarkBadAction = new BisectMarkBadAction(this); private final IAction bisectResetAction = new BisectResetAction(this); private final IAction exportAsBundleAction = new ExportAsBundleAction(this); private final IAction mergeWithCurrentChangesetAction = new MergeWithCurrentChangesetAction(this); private Action stripAction; private Action backoutAction; protected boolean showGoTo; private Text gotoText; private Composite rootControl; private Composite gotoPanel; private HistoryContentProposalProvider proposalProvider; private Job fetchAllJob; private RevisionAnnotationController rulerSelectionListener; /** * Action which is related to the selected file */ private abstract class BaseFileHistoryAction extends BaseSelectionListenerAction { protected IFile file; private BaseFileHistoryAction(String text) { super(text); } @Override protected boolean updateSelection(IStructuredSelection selection) { Object element = selection.getFirstElement(); if(element instanceof MercurialHistory){ MercurialHistory history = (MercurialHistory) element; IFileRevision[] revisions = history.getFileRevisions(); if(revisions.length != 1 || !(revisions[0] instanceof MercurialRevision)){ file = null; return false; } MercurialRevision rev = (MercurialRevision) revisions[0]; if(rev.getResource() instanceof IFile){ file = (IFile) rev.getResource(); return file.exists(); } } else if (element instanceof MercurialRevision){ MercurialRevision rev = (MercurialRevision) element; if(rev.getResource() instanceof IFile){ file = (IFile) rev.getResource(); return file.exists(); } } if(resource instanceof IFile){ file = (IFile) resource; return file.exists(); } file = null; return false; } } private final class FetchEntireHistoryJob extends Job { private FetchEntireHistoryJob(String name) { super(name); } @Override protected IStatus run(IProgressMonitor monitor) { int from = mercurialHistory.getLastVersion() - 1; boolean gotEverything = historyFetched(from); while(!gotEverything && !monitor.isCanceled()) { try { mercurialHistory.refresh(monitor, from); } catch (CoreException ex) { MercurialEclipsePlugin.logError(ex); } from = mercurialHistory.getLastVersion() - 1; gotEverything = historyFetched(from); updateUI(gotEverything); } return Status.OK_STATUS; } private boolean historyFetched(int from) { return from == mercurialHistory.getLastRequestedVersion() || from < 0; } private void updateUI(final boolean gotEverything) { final Control ctrl = viewer.getControl(); if (ctrl != null && !ctrl.isDisposed()) { ctrl.getDisplay().syncExec(new Runnable() { public void run() { if (!ctrl.isDisposed()) { viewer.setInput(mercurialHistory); viewer.refresh(); // refresh the proposal list with new data. // code below works only if the gotoText is not empty Listener[] listeners2 = gotoText.getListeners(SWT.KeyDown); for (Listener listener : listeners2) { Event event = new Event(); event.type = SWT.KeyDown; event.keyCode = SWT.ARROW_RIGHT; event.widget = gotoText; listener.handleEvent(event); } // remove the workaround after we've sent the event if(gotEverything && gotoText.getText().equals(" ")) { gotoText.setText(""); } } } }); } } } class RefreshMercurialHistory extends Job { private final int from; public RefreshMercurialHistory(int from) { super("Retrieving Mercurial revisions..."); //$NON-NLS-1$ this.from = from; setRule(new ExclusiveHistoryRule()); } @Override public IStatus run(IProgressMonitor monitor) { if (mercurialHistory == null) { return Status.OK_STATUS; } mercurialHistory.setEnableExtraTags(showTags); try { mercurialHistory.refresh(monitor, from); if(resource != null) { currentWorkdirChangeset = LocalChangesetCache.getInstance().getChangesetByRootId(resource); } else { currentWorkdirChangeset = LocalChangesetCache.getInstance().getChangesetForRoot(hgRoot); } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } final Runnable runnable = new Runnable() { public void run() { clearSelection(); viewer.setInput(mercurialHistory); viewer.refresh(); } }; // Internal code copied here from Utils.asyncExec if (viewer == null) { return Status.OK_STATUS; } final Control ctrl = viewer.getControl(); if (ctrl != null && !ctrl.isDisposed()) { ctrl.getDisplay().asyncExec(new Runnable() { public void run() { if (!ctrl.isDisposed()) { BusyIndicator.showWhile(ctrl.getDisplay(), runnable); } } }); } return Status.OK_STATUS; } } static class ChangeLogContentProvider implements IStructuredContentProvider { private IFileRevision[] entries; public ChangeLogContentProvider() { super(); } public void inputChanged(Viewer v, Object oldInput, Object newInput) { entries = null; } public void dispose() { entries = null; } public Object[] getElements(Object parent) { if (entries != null) { return entries; } final IFileHistory fileHistory = (IFileHistory) parent; entries = fileHistory.getFileRevisions(); return entries; } } static class ChangeSetLabelProvider extends LabelProvider implements ITableLabelProvider { public String getColumnText(Object obj, int index) { String ret; if (!(obj instanceof MercurialRevision)) { return "Type Error"; //$NON-NLS-1$ } MercurialRevision revision = (MercurialRevision) obj; ChangeSet changeSet = revision.getChangeSet(); switch (index) { case 1: ret = changeSet.toString(); break; case 2: ret = revision.getTagsString(); break; case 3: ret = changeSet.getBranch(); break; case 4: ret = changeSet.getAuthor(); break; case 5: ret = changeSet.getDateString(); break; case 6: ret = changeSet.getSummary(); break; default: ret = null; break; } return ret; } public Image getColumnImage(Object obj, int index) { return null; } } public MercurialHistoryPage() { super(); } public MercurialHistory getMercurialHistory() { return mercurialHistory; } @Override public boolean setInput(Object object) { if (!isValidInput(object)) { return false; } if(object instanceof HgRoot){ actionShowParentHistory.setEnabled(false); HgRoot old = hgRoot; this.hgRoot = (HgRoot) object; super.setInput(object); if(hgRoot == null || (hgRoot != null && !hgRoot.equals(old))){ if(hgRoot != null) { mercurialHistory = new MercurialHistory(hgRoot); } else { mercurialHistory = null; } linkWithEditor(); refresh(); } return true; } IResource old = resource; this.resource = MercurialEclipsePlugin.getAdapter(object, IResource.class); super.setInput(object); if(resource == null || (resource != null && !resource.equals(old))){ if(resource != null) { mercurialHistory = new MercurialHistory(resource); actionShowParentHistory.setEnabled(!mercurialHistory.isRootHistory()); } else { mercurialHistory = null; } linkWithEditor(); refresh(); } return true; } @Override public boolean inputSet() { return true; } @Override public void createControl(Composite parent) { IActionBars actionBars = getHistoryPageSite().getWorkbenchPageSite().getActionBars(); IMenuManager actionBarsMenu = actionBars.getMenuManager(); final IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); showTags = store.getBoolean(PREF_SHOW_ALL_TAGS); Action toggleShowTags = new Action(Messages.getString("HistoryView.showTags"), //$NON-NLS-1$ MercurialEclipsePlugin.getImageDescriptor("actions/tag.gif")) { //$NON-NLS-1$ @Override public void run() { showTags = isChecked(); store.setValue(PREF_SHOW_ALL_TAGS, showTags); if(mercurialHistory != null) { refresh(); } } }; toggleShowTags.setChecked(showTags); actionBarsMenu.add(toggleShowTags); showGoTo = store.getBoolean(PREF_SHOW_GOTO_TEXT); Action toggleGotoText = new Action("Show 'Go To' Panel", //$NON-NLS-1$ MercurialEclipsePlugin.getImageDescriptor("actions/goto.gif")) { //$NON-NLS-1$ @Override public void run() { showGoTo = isChecked(); store.setValue(PREF_SHOW_GOTO_TEXT, showGoTo); if(mercurialHistory != null) { GridData gd = (GridData) gotoPanel.getLayoutData(); gd.exclude = !showGoTo; gotoPanel.setVisible(showGoTo); rootControl.layout(false); changedPaths.refreshLayout(); } } }; toggleGotoText.setChecked(showGoTo); actionBarsMenu.add(toggleGotoText); actionShowParentHistory = new Action("Show Parent History", //$NON-NLS-1$ PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_UP)) { @Override public void run() { if(mercurialHistory == null || hgRoot != null || resource == null) { setEnabled(false); return; } if(resource instanceof IProject){ HgRoot root = MercurialTeamProvider.getHgRoot(resource); if(root != null){ getHistoryView().showHistoryFor(root, true); } else { setEnabled(false); } } else { IContainer parentRes = resource.getParent(); if (parentRes instanceof IFolder || parentRes instanceof IProject) { getHistoryView().showHistoryFor(parentRes, true); } else { setEnabled(false); } } } }; IToolBarManager tbm = actionBars.getToolBarManager(); tbm.add(new Separator()); tbm.add(toggleShowTags); tbm.add(actionShowParentHistory); tbm.add(new Separator()); tbm.add(toggleGotoText); rootControl = createComposite(parent); createGotoText(rootControl); changedPaths = new ChangedPathsPage(this, rootControl); createTableHistory(changedPaths.getControl()); changedPaths.createControl(); setSelectionProvider(viewer); getSite().getActionBars().setGlobalActionHandler(ActionFactory.COPY.getId(), new Action() { @Override public void run() { copyToClipboard(); } }); } private static Composite createComposite(Composite parent) { Composite root = new Composite(parent, SWT.NONE); GridLayout gridLayout = new GridLayout(1, false); gridLayout.marginLeft = 0; gridLayout.marginBottom = 0; gridLayout.marginHeight = 0; gridLayout.marginTop = 0; gridLayout.marginWidth = 0; gridLayout.horizontalSpacing = 1; gridLayout.verticalSpacing = 1; root.setLayout(gridLayout); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); gridData.widthHint = SWT.DEFAULT; gridData.heightHint = SWT.DEFAULT; root.setLayoutData(gridData); return root; } private void createGotoText(Composite parent) { String tooltipForGoTo = "Type version, tag, branch, author or date \n" + "+ to jump directly to the right version.\n" + "Use to get list of proposals.\n" + "Use to stop retrieving history for big repositories."; gotoPanel = new Composite(parent, SWT.NONE); gotoPanel.setToolTipText(tooltipForGoTo); GridLayout gridLayout = new GridLayout(2, false); gridLayout.marginLeft = 0; gridLayout.marginBottom = 0; gridLayout.marginHeight = 0; gridLayout.marginTop = 0; gridLayout.marginWidth = 0; gridLayout.horizontalSpacing = 1; gridLayout.verticalSpacing = 1; gotoPanel.setLayout(gridLayout); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false); gd.exclude = !showGoTo; gotoPanel.setLayoutData(gd); gotoPanel.setVisible(showGoTo); gotoText = new Text(gotoPanel, SWT.SINGLE | SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL); gotoText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); gotoText.setToolTipText(tooltipForGoTo); gotoText.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { fetchEntireHistory(true); } @Override public void focusLost(FocusEvent e) { fetchEntireHistory(false); } }); gotoText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if(e.keyCode == SWT.ESC) { fetchEntireHistory(false); return; } if(e.keyCode != SWT.CR) { return; } // try to retrieve right revision and if it's there, select it String text = gotoText.getText(); guessAndSelectVersion(text); } }); // hack is needed to make the text widget content length > 0, which allows us // to trigger the history retrieving as soon as content assist opens gotoText.setText(" "); Button gotoButton = new Button(gotoPanel, 0); gotoButton.setImage(MercurialEclipsePlugin.getImage("actions/goto.gif")); gotoButton.setToolTipText(tooltipForGoTo); gotoButton.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { fetchEntireHistory(true); guessAndSelectVersion(gotoText.getText()); } }); setupRevisionFieldAssistance(); } private void createTableHistory(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayout layout0 = new GridLayout(); layout0.marginHeight = 0; layout0.marginWidth = 0; composite.setLayout(layout0); GridData data = new GridData(GridData.FILL_BOTH); data.grabExcessVerticalSpace = true; composite.setLayoutData(data); viewer = new GraphLogTableViewer(composite, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.VIRTUAL, this); Table changeLogTable = viewer.getTable(); changeLogTable.setLinesVisible(true); changeLogTable.setHeaderVisible(true); GridData gridData = new GridData(GridData.FILL_BOTH); changeLogTable.setLayoutData(gridData); TableLayout layout = new TableLayout(); changeLogTable.setLayout(layout); TableColumn column = new TableColumn(changeLogTable, SWT.CENTER); column.setText(Messages.getString("MercurialHistoryPage.columnHeader.graph")); //$NON-NLS-1$ layout.addColumnData(new ColumnWeightData(7, true)); column = new TableColumn(changeLogTable, SWT.LEFT); column.setText(Messages.getString("MercurialHistoryPage.columnHeader.changeset")); //$NON-NLS-1$ layout.addColumnData(new ColumnWeightData(15, true)); column = new TableColumn(changeLogTable, SWT.LEFT); column.setText(Messages.getString("MercurialHistoryPage.columnHeader.tag")); //$NON-NLS-1$ layout.addColumnData(new ColumnWeightData(10, true)); column = new TableColumn(changeLogTable, SWT.LEFT); column.setText(Messages.getString("MercurialHistoryPage.columnHeader.branch")); //$NON-NLS-1$ layout.addColumnData(new ColumnWeightData(10, true)); column = new TableColumn(changeLogTable, SWT.LEFT); column.setText(Messages.getString("MercurialHistoryPage.columnHeader.user")); //$NON-NLS-1$ layout.addColumnData(new ColumnWeightData(12, true)); column = new TableColumn(changeLogTable, SWT.LEFT); column.setText(Messages.getString("MercurialHistoryPage.columnHeader.date")); //$NON-NLS-1$ layout.addColumnData(new ColumnWeightData(12, true)); column = new TableColumn(changeLogTable, SWT.LEFT); column.setText(Messages.getString("MercurialHistoryPage.columnHeader.summary")); //$NON-NLS-1$ layout.addColumnData(new ColumnWeightData(25, true)); viewer.setLabelProvider(new ChangeSetLabelProvider()); changeLogViewContentProvider = new ChangeLogContentProvider(); viewer.setContentProvider(changeLogViewContentProvider); viewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { getCompareWithPreviousAction(); updateActionEnablement(); if(compareWithPrevAction.isEnabled()) { compareWithPrevAction.run(); } } }); viewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { if(!gotoText.isVisible()) { return; } IStructuredSelection selection = getSelection(); if(selection.isEmpty()) { return; } gotoText.setText(((MercurialRevision) selection.getFirstElement()).getChangeSet() .toString()); gotoText.selectAll(); } }); viewer.getControl().addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { setSelectionProvider(viewer); } }); contributeActions(); } /** * Adds field assistance to the revision text field. */ private void setupRevisionFieldAssistance() { proposalProvider = new HistoryContentProposalProvider(this); ContentAssistCommandAdapter contentAssist = new ContentAssistCommandAdapter(gotoText, new TextContentAdapter(), proposalProvider, null, null, true); // uncomment to open popup immediately on typing first character into the text field // contentAssist.setAutoActivationCharacters(null); contentAssist.setAutoActivationDelay(300); contentAssist.setPropagateKeys(true); contentAssist.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE); contentAssist.addContentProposalListener(new IContentProposalListener2() { public void proposalPopupOpened(ContentProposalAdapter adapter) { fetchEntireHistory(true); } public void proposalPopupClosed(ContentProposalAdapter adapter) { fetchEntireHistory(false); } }); contentAssist.addContentProposalListener(new IContentProposalListener() { public void proposalAccepted(IContentProposal proposal) { if(proposal instanceof RevisionContentProposal) { selectProposal(proposal); } else { // try to find something guessAndSelectVersion(proposal.getContent()); } } }); } private void copyToClipboard() { Iterator iterator = getSelection().iterator(); StringBuilder text = new StringBuilder(); Table table = viewer.getTable(); for(int columnIndex = 1; columnIndex < table.getColumnCount(); columnIndex++) { text.append(table.getColumn(columnIndex).getText()).append('\t'); } String crlf = System.getProperty("line.separator"); //$NON-NLS-1$ text.append(crlf); while(iterator.hasNext()) { Object next = iterator.next(); ITableLabelProvider labelProvider = (ITableLabelProvider) viewer.getLabelProvider(); for(int columnIndex = 1; columnIndex < table.getColumnCount(); columnIndex++) { text.append(labelProvider.getColumnText(next, columnIndex)).append('\t'); } text.append(crlf); } Clipboard clipboard = null; try { clipboard = new Clipboard(getSite().getShell().getDisplay()); clipboard.setContents(new String[]{text.toString()}, new Transfer[]{ TextTransfer.getInstance() }); } finally { if(clipboard != null){ clipboard.dispose(); } } } private IStructuredSelection getSelection() { return (IStructuredSelection) viewer.getSelection(); } void clearSelection() { viewer.setSelection(StructuredSelection.EMPTY); } public MercurialRevision[] getSelectedRevisions() { Object[] obj = getSelection().toArray(); if (obj != null && obj.length > 0) { MercurialRevision[] revs = new MercurialRevision[obj.length]; int i = 0; for (Object o : obj) { MercurialRevision mr = (MercurialRevision) o; revs[i++] = mr; } return revs; } return null; } private void contributeActions() { final Action updateAction = new Action(Messages.getString("MercurialHistoryPage.updateAction.name")) { //$NON-NLS-1$ private MercurialRevision rev; @Override public void run() { if(rev == null){ return; } try { HgRoot root = resource != null ? MercurialTeamProvider.getHgRoot(resource) : hgRoot; Assert.isNotNull(root); UpdateJob job = new UpdateJob(rev.getContentIdentifier(), true, root, false); if (!job.confirmDataLoss(getControl().getShell())) { return; } JobChangeAdapter adap = new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { refresh(); } }; job.addJobChangeListener(adap); job.schedule(); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } @Override public boolean isEnabled() { MercurialRevision[] revs = getSelectedRevisions(); if (revs != null && revs.length == 1) { rev = revs[0]; return true; } rev = null; return false; } }; updateAction.setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/update.gif")); //$NON-NLS-1$ stripAction = new Action() { { setText("Strip..."); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/revert.gif")); } @Override public void run() { final Shell shell = MercurialEclipsePlugin.getActiveShell(); shell.getDisplay().asyncExec(new Runnable() { public void run() { ChangeSet changeSet = null; MercurialRevision[] revisions = getSelectedRevisions(); if (revisions == null || revisions.length != 1) { return; } changeSet = revisions[0].getChangeSet(); StripHandler.openWizard(changeSet.getHgRoot(), shell, changeSet); } }); } @Override public boolean isEnabled() { MercurialRevision[] revs = getSelectedRevisions(); if (revs != null && revs.length == 1) { return true; } return false; } }; backoutAction = new Action() { { setText("Backout..."); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/revert.gif")); } @Override public void run() { final Shell shell = MercurialEclipsePlugin.getActiveShell(); shell.getDisplay().asyncExec(new Runnable() { public void run() { ChangeSet changeSet = null; MercurialRevision[] revisions = getSelectedRevisions(); if (revisions == null || revisions.length != 1) { return; } changeSet = revisions[0].getChangeSet(); BackoutWizard backoutWizard = new BackoutWizard(changeSet.getHgRoot(), changeSet); WizardDialog dialog = new WizardDialog(shell, backoutWizard); dialog.setBlockOnOpen(true); int result = dialog.open(); if (result == Window.OK) { new RefreshWorkspaceStatusJob(changeSet.getHgRoot(), RefreshRootJob.ALL).schedule(); } } }); } @Override public boolean isEnabled() { MercurialRevision[] revs = getSelectedRevisions(); if (revs != null && revs.length == 1) { return true; } return false; } }; // Contribute actions to popup menu final MenuManager menuMgr = new MenuManager(); final MenuManager bisectMenu = new MenuManager("Bisect"); final MenuManager undoMenu = new MenuManager("Undo", MercurialEclipsePlugin.getImageDescriptor("undo_edit.gif"), null); undoMenu.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { undoMenu.add(backoutAction); undoMenu.add(stripAction); } }); bisectMenu.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager menuMgr1) { bisectMenu.add(bisectMarkBadAction); bisectMenu.add(bisectMarkGoodAction); bisectMenu.add(bisectResetAction); } }); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager menuMgr1) { // enablement updateAction.setEnabled(updateAction.isEnabled()); bisectMarkBadAction.setEnabled(bisectMarkBadAction.isEnabled()); bisectMarkGoodAction.setEnabled(bisectMarkGoodAction.isEnabled()); bisectResetAction.setEnabled(bisectResetAction.isEnabled()); exportAsBundleAction.setEnabled(true); mergeWithCurrentChangesetAction.setEnabled(true); stripAction.setEnabled(stripAction.isEnabled()); backoutAction.setEnabled(backoutAction.isEnabled()); undoMenu.setVisible(stripAction.isEnabled() || backoutAction.isEnabled()); // layout if(resource instanceof IFile){ IStructuredSelection sel = updateActionEnablement(); menuMgr1.add(openAction); menuMgr1.add(openEditorAction); menuMgr1.add(new Separator(IWorkbenchActionConstants.GROUP_FILE)); if(sel.size() == 2){ menuMgr1.add(compareTwo); } else { menuMgr1.add(compareWithPrevAction); menuMgr1.add(compareWithCurrAction); menuMgr1.add(compareWithOtherAction); menuMgr1.add(new Separator()); menuMgr1.add(revertAction); } } menuMgr1.add(mergeWithCurrentChangesetAction); menuMgr1.add(undoMenu); menuMgr1.add(new Separator()); menuMgr1.add(updateAction); menuMgr1.add(bisectMenu); menuMgr1.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); menuMgr1.add(exportAsBundleAction); } }); bisectMenu.setRemoveAllWhenShown(true); undoMenu.setRemoveAllWhenShown(true); menuMgr.setRemoveAllWhenShown(true); viewer.getTable().setMenu(menuMgr.createContextMenu(viewer.getTable())); getSite().registerContextMenu(MercurialEclipsePlugin.ID + ".hgHistoryPage", menuMgr, viewer); } private void createActions() { getOpenAction(); getOpenEditorAction(); getCompareWithCurrentAction(); getCompareWithOtherAction(); getRevertAction(); compareTwo = new CompareRevisionAction(Messages.getString("CompareWithEachOtherAction.label"), this){ //$NON-NLS-1$ @Override protected boolean updateSelection(IStructuredSelection selection) { if(selection.size() != 2){ return false; } return super.updateSelection(selection); } }; } OpenMercurialRevisionAction getOpenAction() { if(openAction != null){ return openAction; } openAction = new OpenMercurialRevisionAction(Messages.getString("MercurialHistoryPage.openSelectedVersion")); //$NON-NLS-1$ openAction.setPage(this); return openAction; } BaseSelectionListenerAction getOpenEditorAction() { if(openEditorAction != null){ return openEditorAction; } openEditorAction = new BaseFileHistoryAction(Messages.getString("MercurialHistoryPage.openCurrentVersion")) { @Override public void run() { if(file == null){ return; } ResourceUtils.openEditor(getSite().getPage(), file); } }; return openEditorAction; } BaseSelectionListenerAction getFocusOnSelectedFileAction() { if(focusOnSelectedFileAction != null){ return focusOnSelectedFileAction; } focusOnSelectedFileAction = new BaseFileHistoryAction(Messages.getString("MercurialHistoryPage.showSelectedFileHistory")) { //$NON-NLS-1$ @Override public void run() { if(file == null){ return; } getHistoryView().showHistoryFor(file, true); } @Override protected boolean updateSelection(IStructuredSelection selection) { boolean result = super.updateSelection(selection); if(result) { // disable "focus on" for the already focused file if(file != null && file.equals(resource)) { file = null; return false; } } return result; } }; focusOnSelectedFileAction.setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/goto.gif")); return focusOnSelectedFileAction; } CompareRevisionAction getCompareWithCurrentAction() { if(compareWithCurrAction == null) { compareWithCurrAction = new CompareRevisionAction(Messages.getString("CompareAction.label"), this); //$NON-NLS-1$ } return compareWithCurrAction; } CompareRevisionAction getCompareWithPreviousAction() { if(compareWithPrevAction == null) { compareWithPrevAction = new CompareRevisionAction(Messages.getString("CompareWithPreviousAction.label"), this); //$NON-NLS-1$ compareWithPrevAction.setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("compare_view.gif")); //$NON-NLS-1$ compareWithPrevAction.setCompareWithPrevousEnabled(true); } return compareWithPrevAction; } CompareRevisionAction getCompareWithOtherAction() { if(compareWithOtherAction == null) { compareWithOtherAction = new CompareRevisionAction(Messages.getString("CompareWithOtherAction.label"), this) { //$NON-NLS-1$ private IFile file; private MercurialRevision selectedRev; @Override public void run() { if(file == null || selectedRev == null) { return; } String title = "Compare " + file.getName() + " [" + selectedRev.getRevision() + "] with ..."; RevisionChooserDialog dialog = new RevisionChooserDialog(getControl().getShell(), title, file); int result = dialog.open(); if (result == IDialogConstants.OK_ID) { ChangeSet cs = dialog.getChangeSet(); MercurialRevision rev = new MercurialRevision(cs, null, file, null, null); super.updateSelection(new StructuredSelection(new Object[] {selectedRev, rev})); super.run(); } } @Override protected boolean updateSelection(IStructuredSelection selection) { Object element = selection.getFirstElement(); if(element instanceof MercurialHistory){ MercurialHistory history = (MercurialHistory) element; IFileRevision[] revisions = history.getFileRevisions(); if(revisions.length != 1 || !(revisions[0] instanceof MercurialRevision)){ file = null; selectedRev = null; return false; } MercurialRevision rev = (MercurialRevision) revisions[0]; if(rev.getResource() instanceof IFile){ file = (IFile) rev.getResource(); selectedRev = rev; return file.exists(); } } else if (element instanceof MercurialRevision){ MercurialRevision rev = (MercurialRevision) element; if(rev.getResource() instanceof IFile){ file = (IFile) rev.getResource(); selectedRev = rev; return file.exists(); } } file = null; selectedRev = null; return false; } }; compareWithOtherAction.setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("compare_view.gif")); //$NON-NLS-1$ } return compareWithOtherAction; } @Override public Control getControl() { return rootControl; } @Override public void setFocus() { viewer.getControl().setFocus(); } public String getDescription() { return resource != null? ResourceUtils.getPath(resource).toOSString() : hgRoot.getAbsolutePath(); } public String getName() { return getDescription(); } public boolean isValidInput(Object object) { return object == null || object instanceof IResource || object instanceof HgRoot || MercurialEclipsePlugin.getAdapter(object, IResource.class) != null; } public ChangeSet getCurrentWorkdirChangeset() { return currentWorkdirChangeset; } public void refresh() { if (refreshFileHistoryJob == null) { refreshFileHistoryJob = new RefreshMercurialHistory(Integer.MAX_VALUE); } if (refreshFileHistoryJob.getState() != Job.NONE) { refreshFileHistoryJob.cancel(); fetchEntireHistory(false); } scheduleInPage(refreshFileHistoryJob); } public void scheduleInPage(Job job, long delayInMillis) { IWorkbenchSiteProgressService progressService = getProgressService(); if (progressService != null) { progressService.schedule(job, delayInMillis); } else { job.schedule(delayInMillis); } } public void scheduleInPage(Job job) { scheduleInPage(job, 0); } private IWorkbenchSiteProgressService getProgressService() { IWorkbenchSiteProgressService progressService = (IWorkbenchSiteProgressService) getHistoryPageSite() .getWorkbenchPageSite().getService(IWorkbenchSiteProgressService.class); return progressService; } /** * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ public Object getAdapter(Class adapter) { return null; } public TableViewer getTableViewer() { return viewer; } private IStructuredSelection updateActionEnablement() { createActions(); IStructuredSelection selection = getSelection(); openAction.selectionChanged(selection); openEditorAction.selectionChanged(selection); compareWithCurrAction.selectionChanged(selection); compareWithOtherAction.selectionChanged(selection); compareWithPrevAction.selectionChanged(selection); compareTwo.selectionChanged(selection); revertAction.selectionChanged(selection); return selection; } public BaseSelectionListenerAction getRevertAction() { if (revertAction == null) { final String replaceString = Messages.getString("MercurialHistoryPage.replaceCurrentWithSelected"); final String restoreString = Messages.getString("MercurialHistoryPage.restoreDeletedFile"); final String undoMoveString = Messages.getString("MercurialHistoryPage.undoMove"); revertAction = new BaseSelectionListenerAction(replaceString) { @Override public void run() { IStructuredSelection selection = getStructuredSelection(); if (selection.isEmpty()) { return; } ActionRevert revert = new ActionRevert(); MercurialRevision revision = (MercurialRevision) selection.getFirstElement(); IResource selectedElement = revision.getResource(); MercurialStatusCache cache = MercurialStatusCache.getInstance(); if (!cache.isUnknown(selectedElement) && !cache.isClean(selectedElement) && !MessageDialog.openQuestion(getControl().getShell(), Messages.getString("MercurialHistoryPage.UncommittedChanges"), //$NON-NLS-1$ Messages.getString("MercurialHistoryPage.file") + selectedElement.getName() //$NON-NLS-1$ + Messages.getString("MercurialHistoryPage.hasUncommittedChanges"))) { //$NON-NLS-1$ return; } selection = new StructuredSelection(selectedElement); revert.setChangesetToRevert(revision.getChangeSet()); revert.selectionChanged(this, selection); revert.run(this); } @Override protected boolean updateSelection(IStructuredSelection sSelection) { if(sSelection.size() != 1){ return false; } if(sSelection.size() == 1){ Object element = sSelection.getFirstElement(); if(element instanceof MercurialRevision){ MercurialRevision rev = (MercurialRevision) element; if(rev.getResource() instanceof IFile){ if(rev.getChangeSet().isRemoved(rev.getResource())) { setText(restoreString); } else if (rev.getChangeSet().isMoved(rev.getResource())) { setText(undoMoveString); } else { setText(replaceString); } return true; } } } return false; } }; revertAction.setImageDescriptor(MercurialEclipsePlugin .getImageDescriptor("actions/revert.gif")); //$NON-NLS-1$ } return revertAction; } /** * @param currentWorkdirChangeset the currentWorkdirChangeset to set */ public void setCurrentWorkdirChangeset(ChangeSet currentWorkdirChangeset) { this.currentWorkdirChangeset = currentWorkdirChangeset; } protected synchronized void fetchEntireHistory(boolean on) { if(!on) { if(fetchAllJob != null) { fetchAllJob.cancel(); } } else { if(fetchAllJob == null) { fetchAllJob = new FetchEntireHistoryJob("Retrieving entire history"); fetchAllJob.setRule(new ExclusiveHistoryRule()); } scheduleInPage(fetchAllJob); } } /** * @param proposal non null */ private void selectProposal(IContentProposal proposal) { RevisionContentProposal revProposal = (RevisionContentProposal) proposal; MercurialRevision revision = revProposal.getRevision(); viewer.getControl().setFocus(); viewer.setSelection(new StructuredSelection(revision)); viewer.reveal(revision); } /** * @param text non null */ private void guessAndSelectVersion(String text) { IContentProposal[] proposals = proposalProvider.getProposals(text, text.length()); if (proposals.length == 0) { getHistoryPageSite().getWorkbenchPageSite().getActionBars().getStatusLineManager() .setErrorMessage("No matches found"); } else if (proposals.length == 1) { selectProposal(proposals[0]); } else { getHistoryPageSite().getWorkbenchPageSite().getActionBars().getStatusLineManager() .setErrorMessage("Multiple matches found"); } } /** * Set the selection provider for current history view */ void setSelectionProvider(ISelectionProvider provider) { getHistoryPageSite().setSelectionProvider(provider); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=366468: // the code below doesn't work with Eclipse 3.8 anymore, but the hack is not needed anymore if(ECLISPE_BEFORE_38) { // it looks crazy, but the fact is that the page site doesn't set global // selection provider, so we must have it set properly to support Properties view getSite().getPage().findView(IHistoryView.VIEW_ID).getSite().setSelectionProvider(provider); } } /** * @see org.eclipse.ui.part.Page#dispose() */ @Override public void dispose() { super.dispose(); mercurialHistory = null; if (rulerSelectionListener != null) { rulerSelectionListener.dispose(); rulerSelectionListener= null; } } private final class MercurialRevisionAnnotationController extends RevisionAnnotationController { public MercurialRevisionAnnotationController(IWorkbenchPage page, IFile file) { super(page, file, viewer); } public MercurialRevisionAnnotationController(IWorkbenchPage page, IStorageEditorInput editorInput) { super(page, editorInput, viewer); } @Override protected Object getHistoryEntry(Revision selected) { if (selected instanceof ShowAnnotationOperation.MercurialRevision) { return MercurialHistoryPage.this.mercurialHistory.getFileRevision(((ShowAnnotationOperation.MercurialRevision)selected).getChangeSet().getChangeset()); } return null; } } public void linkWithEditor() { if (rulerSelectionListener != null) { rulerSelectionListener.dispose(); rulerSelectionListener= null; } if (!getHistoryPageSite().isModal()) { if (resource instanceof IFile) { IFile file = (IFile) resource; rulerSelectionListener= new MercurialRevisionAnnotationController(getHistoryPageSite().getWorkbenchPageSite().getPage(), file); } else { Object input = getInput(); if (input instanceof IStorageEditorInput) { IStorageEditorInput editorInput = (IStorageEditorInput) input; rulerSelectionListener= new MercurialRevisionAnnotationController(getHistoryPageSite().getWorkbenchPageSite().getPage(), editorInput); } } } } } MercurialHistoryPageSource.java000066400000000000000000000037331173713500500361460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.core.resources.IResource; import org.eclipse.team.ui.history.HistoryPageSource; import org.eclipse.ui.part.Page; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author zingo * */ public class MercurialHistoryPageSource extends HistoryPageSource { public MercurialHistoryPageSource(MercurialHistoryProvider fileHistoryProvider) { super(); } public boolean canShowHistoryFor(Object object) { if(object instanceof HgRoot){ HgRoot hgRoot = (HgRoot) object; return hgRoot.exists(); } IResource resource = ResourceUtils.getResource(object); if(resource == null){ return false; } MercurialStatusCache cache = MercurialStatusCache.getInstance(); if(resource.exists()) { return cache.isSupervised(resource) && !cache.isAdded(ResourceUtils.getPath(resource)); } // allow to show history for files which are already deleted and committed // (neither in the cache nor on disk) return MercurialTeamProvider.isHgTeamProviderFor(resource); } public Page createPage(Object object) { return new MercurialHistoryPage(); } } MercurialHistoryProvider.java000066400000000000000000000034361173713500500357030ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.history.IFileHistory; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.core.history.provider.FileHistoryProvider; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * @author zingo * */ public class MercurialHistoryProvider extends FileHistoryProvider { public MercurialHistoryProvider() { super(); } public IFileHistory getFileHistoryFor(IResource resource, int flags, IProgressMonitor monitor) { RepositoryProvider provider = RepositoryProvider.getProvider(((IFile) resource) .getProject()); if (provider instanceof MercurialTeamProvider) { return new MercurialHistory(resource); } return null; } public IFileHistory getFileHistoryFor(IFileStore store, int flags, IProgressMonitor monitor) { return null; } public IFileRevision getWorkspaceFileRevision(IResource resource) { return null; } } MercurialRevision.java000066400000000000000000000213111173713500500343150ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2007-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Andrei Loskutov - bug fixes * John Peberdy - optimization *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IStorage; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.core.history.provider.FileRevision; import com.vectrace.MercurialEclipse.commands.HgBisectClient.Status; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.GChangeSet; import com.vectrace.MercurialEclipse.model.Signature; import com.vectrace.MercurialEclipse.model.Tag; import com.vectrace.MercurialEclipse.properties.DoNotDisplayMe; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; /** * @author zingo */ public class MercurialRevision extends FileRevision { private final IResource resource; private final ChangeSet changeSet; /** Cached data */ private MercurialRevisionStorage mercurialRevisionStorage; private final GChangeSet gChangeSet; private final int revision; private final Signature signature; private File parent; /** * Tags sorted by revision * @see #pendingTags */ private Tag [] tags; /** * List of unsorted tags not yet added to {@link #tags}. May be null. * @see #tags */ private List pendingTags; private Status bisectStatus; /** * @param changeSet must be non null * @param gChangeSet may be null * @param resource must be non null * @param sig may be null */ public MercurialRevision(ChangeSet changeSet, GChangeSet gChangeSet, IResource resource, Signature sig, Status bisectStatus) { super(); Assert.isNotNull(changeSet); Assert.isNotNull(resource); this.changeSet = changeSet; this.gChangeSet = gChangeSet; this.revision = changeSet.getChangesetIndex(); this.resource = resource; this.signature = sig; this.bisectStatus = bisectStatus; } public Signature getSignature() { return signature; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + changeSet.hashCode(); result = prime * result + resource.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof MercurialRevision)) { return false; } MercurialRevision other = (MercurialRevision) obj; if (!changeSet.equals(other.changeSet)) { return false; } if (!resource.equals(other.resource)) { return false; } return true; } /** * @return never null */ public ChangeSet getChangeSet() { return changeSet; } @DoNotDisplayMe public GChangeSet getGChangeSet() { return gChangeSet; } @DoNotDisplayMe public String getName() { return resource.getName(); } @Override @DoNotDisplayMe public boolean exists() { return true; } @Override @DoNotDisplayMe public String getContentIdentifier() { return changeSet.getChangeset(); } @Override public String getAuthor() { return changeSet.getAuthor(); } @Override public String getComment() { return changeSet.getComment(); } @Override @DoNotDisplayMe public long getTimestamp() { return resource.exists()? resource.getLocalTimeStamp() : super.getTimestamp(); } @Override public URI getURI() { return resource.getLocationURI(); } @Override public Tag [] getTags() { if (pendingTags != null) { processPendingTags(); } if(tags == null) { return changeSet.getTags(); } return tags; } /** * @return never returns null */ public String getTagsString(){ StringBuilder sb = new StringBuilder(); Tag[] allTags = getTags(); for (int i = 0; i < allTags.length; i++) { sb.append(allTags[i].getName()); if(i < allTags.length - 1) { sb.append(", "); //$NON-NLS-1$ } } return sb.toString(); } /** * Allows to add extra tags, not contained in the underlying changeset, to this revision. * The point is: we want to be able to show tag information on revisions of particular * files, which was NOT directly tagged, but we want to know which existing tags are * covered by the version. * * @param newTag must be non null */ public void addTag(Tag newTag) { if(newTag == null) { return; } if (pendingTags == null) { pendingTags = new ArrayList(4); } pendingTags.add(newTag); } private void processPendingTags() { if (pendingTags == null) { return; } SortedSet all = new TreeSet(); all.addAll(pendingTags); pendingTags = null; if(tags != null) { for (Tag tag : tags) { if(tag != null) { all.add(tag); } } } for (Tag tag : changeSet.getTags()) { if(tag != null) { all.add(tag); } } this.tags = all.toArray(new Tag[all.size()]); Arrays.sort(tags); } /** * Cleans up all extra tags we probably have on this revision */ public void cleanupExtraTags(){ tags = null; pendingTags = null; } public IStorage getStorage(IProgressMonitor monitor) throws CoreException { if (mercurialRevisionStorage == null) { if(!resource.exists() && parent != null){ IFile parentRes = ResourcesPlugin.getWorkspace().getRoot() .getFileForLocation(new Path(parent.getAbsolutePath())); mercurialRevisionStorage = new MercurialRevisionStorage(parentRes, revision, getContentIdentifier(), changeSet); } else { if(resource instanceof IFile){ mercurialRevisionStorage = new MercurialRevisionStorage((IFile) resource, revision, getContentIdentifier(), changeSet); mercurialRevisionStorage.setParent(parent); } } } return mercurialRevisionStorage; } @DoNotDisplayMe public boolean isPropertyMissing() { return false; } public IFileRevision withAllProperties(IProgressMonitor monitor) throws CoreException { return this; } /** * @return the revision */ public int getRevision() { return revision; } /** * @return never null */ @DoNotDisplayMe public IResource getResource() { return resource; } /** * @return the possible parent (after the copy or rename operation), may be null */ public File getParent() { return parent; } /** * @param parent the possible parent (after the copy or rename operation) */ public void setParent(File parent) { this.parent = parent; } /** * * @return true, if the resource represented by this revision is file */ @DoNotDisplayMe public boolean isFile(){ return resource instanceof IFile; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("hg rev ["); //$NON-NLS-1$ builder.append("revision="); //$NON-NLS-1$ builder.append(revision); builder.append(", "); //$NON-NLS-1$ builder.append("changeSet="); //$NON-NLS-1$ builder.append(changeSet); builder.append(", "); //$NON-NLS-1$ builder.append("resource="); //$NON-NLS-1$ builder.append(resource); builder.append(", "); //$NON-NLS-1$ if (signature != null) { builder.append("signature="); //$NON-NLS-1$ builder.append(signature); builder.append(", "); //$NON-NLS-1$ } if (gChangeSet != null) { builder.append("gChangeSet="); //$NON-NLS-1$ builder.append(gChangeSet); } if (parent != null) { builder.append("parent="); //$NON-NLS-1$ builder.append(parent); } if (tags != null) { builder.append("tags="); //$NON-NLS-1$ builder.append(Arrays.asList(tags)); } if (pendingTags != null) { builder.append("pendingTags="); //$NON-NLS-1$ builder.append(pendingTags); } builder.append("]"); //$NON-NLS-1$ return builder.toString(); } /** * @return the bisectStatus */ public Status getBisectStatus() { return bisectStatus; } /** * @param bisectStatus the bisectStatus to set */ public void setBisectStatus(Status bisectStatus) { this.bisectStatus = bisectStatus; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/Messages.java000066400000000000000000000034061173713500500325060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.osgi.util.NLS; /** * @author Bastian * */ public final class Messages extends NLS { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.history.messages"; //$NON-NLS-1$ public static String BisectAbstractAction_bisecting; public static String BisectAbstractAction_BisectionResult; public static String BisectAbstractAction_showBisectionResult; public static String BisectAbstractAction_successString; public static String BisectMarkBadAction_description1; public static String BisectMarkBadAction_description2; public static String BisectMarkBadAction_name; public static String BisectMarkGoodAction_markSelectionAsGood; public static String BisectMarkGoodAction_markSelectionDescription; public static String BisectMarkGoodAction_markSelectionDescription2; public static String BisectResetAction_description; public static String BisectResetAction_description2; public static String BisectResetAction_name; public static String ChangePathsTableProvider_retrievingAffectedPaths; public static String CompareRevisionAction_retrievingDiffData; static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); } private Messages() { } } SimpleLabelImageProvider.java000066400000000000000000000027301173713500500355260ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.model.FileStatus; public final class SimpleLabelImageProvider extends LabelProvider { private final Image fileImg; public SimpleLabelImageProvider() { fileImg = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); } @Override public Image getImage(Object element) { return fileImg; } @Override public String getText(Object element) { if (!(element instanceof FileStatus)) { return null; } FileStatus status = (FileStatus) element; if(status.isCopied()){ return " " + status.getRootRelativePath().toOSString() + " (" + status.getRootRelativeCopySourcePath().toOSString() + ")"; //$NON-NLS-1$ } return " " + status.getRootRelativePath().toOSString(); //$NON-NLS-1$ } }TextViewerAction.java000066400000000000000000000031251173713500500341220ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation ******************************************************************************/ package com.vectrace.MercurialEclipse.history; import org.eclipse.jface.action.Action; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextViewer; import org.eclipse.ui.texteditor.IUpdate; /** * Used by ConsoleView */ public class TextViewerAction extends Action implements IUpdate { private int operationCode = -1; private final ITextOperationTarget operationTarget; public TextViewerAction(ITextViewer viewer, int operationCode) { this.operationCode = operationCode; operationTarget = viewer.getTextOperationTarget(); update(); } public void update() { boolean wasEnabled = isEnabled(); boolean isEnabled = operationTarget != null && operationTarget.canDoOperation(operationCode); setEnabled(isEnabled); if (wasEnabled != isEnabled) { firePropertyChange(ENABLED, wasEnabled ? Boolean.TRUE : Boolean.FALSE, isEnabled ? Boolean.TRUE : Boolean.FALSE); } } @Override public void run() { if (operationCode != -1 && operationTarget != null) { operationTarget.doOperation(operationCode); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/history/messages.properties000066400000000000000000000021021173713500500340110ustar00rootroot00000000000000BisectAbstractAction_bisecting=Bisecting... BisectAbstractAction_BisectionResult=Bisection result BisectAbstractAction_showBisectionResult=Show Bisection result BisectAbstractAction_successString=The first bad revision is: BisectMarkBadAction_description1=Marks the selected changeset as erroneous. BisectMarkBadAction_description2=\nIf bisect hadn't been started before, starts bisect. BisectMarkBadAction_name=Mark Selection or Working Directory as Bad BisectMarkGoodAction_markSelectionAsGood=Mark Selection or Working Directory as Good BisectMarkGoodAction_markSelectionDescription=Marks the selected changeset as good. BisectMarkGoodAction_markSelectionDescription2=\nIf nothing is selected, stops bisect as the working directory is good BisectResetAction_description=Resets the working directory. BisectResetAction_description2=\nBisection stops therefore and can be started anew. BisectResetAction_name=Reset and Stop Bisecting ChangePathsTableProvider_retrievingAffectedPaths=Retrieving affected paths for {0} CompareRevisionAction_retrievingDiffData=Retrieving hg diff data... eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/000077500000000000000000000000001173713500500273345ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/AbortRebaseHandler.java000066400000000000000000000024461173713500500336740ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.RebaseOperation; public class AbortRebaseHandler extends RunnableHandler { @Override public void run(HgRoot hgRoot) throws CoreException { try { RebaseOperation.createAbort(MercurialEclipsePlugin.getActiveWindow(), hgRoot).run( new NullProgressMonitor()); } catch (InvocationTargetException e) { MercurialEclipsePlugin.rethrow(e); } catch (InterruptedException e) { MercurialEclipsePlugin.rethrow(e); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/AddBranchHandler.java000066400000000000000000000017641173713500500333130ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Abdrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.AddBranchWizard; public class AddBranchHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) { AddBranchWizard wizard = new AddBranchWizard(hgRoot); WizardDialog wizardDialog = new WizardDialog(getShell(), wizard); wizardDialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/AddHandler.java000066400000000000000000000115101173713500500321630ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.ui.dialogs.CheckedTreeSelectionDialog; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.views.navigator.ResourceComparator; import com.vectrace.MercurialEclipse.commands.HgAddClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.RefreshStatusJob; import com.vectrace.MercurialEclipse.ui.ResourcesTreeContentProvider; import com.vectrace.MercurialEclipse.ui.UntrackedResourcesFilter; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class AddHandler extends MultipleResourcesHandler { @Override public void run(final List resources) throws HgException { MercurialStatusCache cache = MercurialStatusCache.getInstance(); if(resources.size() == 1 && resources.get(0) instanceof IFile){ // shortcut for the single file "add..." operation. // we do not need any dialogs here. IResource resource = resources.get(0); if(cache.isUnknown(resource)) { HgAddClient.addResources(resources, null); new RefreshStatusJob(Messages.getString("AddHandler.refreshStatus"), resource .getProject()).schedule(); } return; } Map> byRoot = ResourceUtils.groupByRoot(resources); Map> untrackedFiles = new HashMap>(); Map> untrackedFolders = new HashMap>(); for (HgRoot hgRoot : byRoot.keySet()) { String[] rawFiles = HgStatusClient.getUntrackedFiles(hgRoot); Set files = new HashSet(); Set folders = new HashSet(); for (String raw : rawFiles) { IPath path = new Path(raw); if(cache.isIgnored(hgRoot.toAbsolute(path))) { continue; } files.add(path); int count = path.segmentCount(); for (int i = 1; i < count; i++) { folders.add(path.removeLastSegments(i)); } } untrackedFiles.put(hgRoot, files); untrackedFolders.put(hgRoot, folders); } ViewerFilter untrackedFilter = new UntrackedResourcesFilter(untrackedFiles, untrackedFolders); CheckedTreeSelectionDialog dialog = new CheckedTreeSelectionDialog(getShell(), WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider(), new ResourcesTreeContentProvider(ResourceUtils.groupByProject(resources).keySet())); dialog.setInput(ResourcesTreeContentProvider.ROOT); dialog.setTitle(Messages.getString("AddHandler.addToVersionControl")); //$NON-NLS-1$ dialog.setMessage(Messages.getString("AddHandler.selectFiles")); //$NON-NLS-1$ dialog.setContainerMode(true); dialog.setInitialElementSelections(resources); dialog.setComparator(new ResourceComparator(ResourceComparator.NAME)); dialog.addFilter(untrackedFilter); Set expanded = new HashSet(); for (IResource resource : resources) { IContainer parent = resource.getParent(); while(parent != null && !expanded.contains(parent)){ if(parent.getType() == IResource.ROOT){ break; } expanded.add(parent); parent = parent.getParent(); } } dialog.setExpandedElements(expanded.toArray(new IContainer[0])); if (dialog.open() == IDialogConstants.OK_ID) { HgAddClient.addResources(keepFiles(dialog.getResult()), null); for (HgRoot root : byRoot.keySet()) { new RefreshStatusJob(Messages.getString("AddHandler.refreshStatus"), root).schedule(); //$NON-NLS-1$ } } } /** * Only keep IFiles */ private List keepFiles(Object[] objects) { List files = new ArrayList(); for (Object object : objects) { if (object instanceof IFile) { files.add((IFile) object); } } return files; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/BackoutHandler.java000066400000000000000000000026001173713500500330630ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.wizards.BackoutWizard; public class BackoutHandler extends RootHandler { @Override protected void run(final HgRoot hgRoot) throws CoreException { BackoutWizard backoutWizard = new BackoutWizard(hgRoot); WizardDialog dialog = new WizardDialog(getShell(), backoutWizard); dialog.setBlockOnOpen(true); int result = dialog.open(); if(result == Window.OK){ new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.ALL).schedule(); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/BookmarkHandler.java000066400000000000000000000035471173713500500332530ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.dialogs.BookmarkDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.ResourceProperties; public class BookmarkHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) { try { if (!MercurialUtilities.isCommandAvailable("bookmarks", //$NON-NLS-1$ ResourceProperties.EXT_BOOKMARKS_AVAILABLE, "hgext.bookmarks=")) { //$NON-NLS-1$ Shell shell = getShell(); MessageDialog .openInformation( shell, Messages.getString("BookmarkHandler.extNotAvailable"), //$NON-NLS-1$ Messages.getString("BookmarkHandler.extNotAvailableLong.1") //$NON-NLS-1$ + Messages.getString("BookmarkHandler.extNotAvailableLong.2") //$NON-NLS-1$ + Messages.getString("BookmarkHandler.extNotAvailableLong.3")); //$NON-NLS-1$ } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } BookmarkDialog dialog = new BookmarkDialog(getShell(), hgRoot); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/CommitHandler.java000066400000000000000000000047411173713500500327330ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.dialogs.CommitDialog; import com.vectrace.MercurialEclipse.dialogs.CommitDialog.Options; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class CommitHandler extends MultipleResourcesHandler { private int result; private Options options; @Override public void run(List resources) throws HgException { if(resources.isEmpty() && options != null && options.allowEmptyCommit && options.hgRoot != null) { CommitDialog commitDialog = new CommitDialog(getShell(), options.hgRoot, resources); commitDialog.setOptions(options); commitDialog.setBlockOnOpen(true); result = commitDialog.open(); } else { Map> byRoot = ResourceUtils.groupByRoot(resources); Set>> entrySet = byRoot.entrySet(); for (Entry> entry : entrySet) { HgRoot hgRoot = entry.getKey(); if(MercurialStatusCache.getInstance().isMergeInProgress(hgRoot)){ new CommitMergeHandler().commitMergeWithCommitDialog(hgRoot, getShell()); return; } if(options == null){ options = new Options(); } CommitDialog commitDialog = new CommitDialog(getShell(), hgRoot, entry.getValue()); commitDialog.setOptions(options); commitDialog.setBlockOnOpen(true); result = commitDialog.open(); } } } /** * @param options commit dialog options */ public void setOptions(Options options) { this.options = options; } /** * @return {@link Window#OK} if the commit dialog was finished with the OK button */ public int getResult() { return result; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/CommitMergeHandler.java000066400000000000000000000053221173713500500337070ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.commands.HgCommitClient; import com.vectrace.MercurialEclipse.dialogs.CommitDialog; import com.vectrace.MercurialEclipse.dialogs.MergeDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; public class CommitMergeHandler extends RunnableHandler { /** * run the commit merge handler */ @Override public void run(HgRoot hgRoot) throws HgException { commitMergeWithCommitDialog(hgRoot, getShell()); } /** * Opens the Commit dialog and commits the merge if ok is pressed. * @param hgRoot * the root to commit * @return the hg command output * @throws HgException */ public String commitMergeWithCommitDialog(HgRoot hgRoot, Shell shell) throws HgException { Assert.isNotNull(hgRoot); String changesetMessage = Messages.getString("CommitMergeHandler.mergeWith"); String mergeChangesetId = MercurialStatusCache.getInstance().getMergeChangesetId(hgRoot); if(mergeChangesetId != null) { changesetMessage += " " + mergeChangesetId; } else { // TODO get the changeset id from mercurial via command call changesetMessage = "Merging..."; } CommitDialog commitDialog = new MergeDialog(shell, hgRoot, changesetMessage); // open dialog and wait for ok commitDialog.open(); return commitDialog.getCommitResult(); } /** * Commits a merge with the given message. The commit dialog is not shown. * @param hgRoot the root to be committed, not null * @return the output of hg commit * @throws HgException * @throws CoreException */ public static String commitMerge(HgRoot hgRoot, String commitName, String message) throws HgException, CoreException { Assert.isNotNull(hgRoot); Assert.isNotNull(message); // do hg call MercurialUtilities.setOfferAutoCommitMerge(true); String result = HgCommitClient.commit(hgRoot, commitName, message); return result; } } CompareWithParentHandler.java000066400000000000000000000017221173713500500350140ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.team.CompareAction; public class CompareWithParentHandler extends SingleResourceHandler { /** * @see com.vectrace.MercurialEclipse.menu.SingleResourceHandler#run(org.eclipse.core.resources.IResource) */ @Override protected void run(IResource resource) throws Exception { new CompareAction(resource).run(null); } }CompareWithRevisionHandler.java000066400000000000000000000017301173713500500353600ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.team.CompareWithAction; public class CompareWithRevisionHandler extends SingleResourceHandler { /** * @see com.vectrace.MercurialEclipse.menu.SingleResourceHandler#run(org.eclipse.core.resources.IResource) */ @Override protected void run(IResource resource) throws Exception { new CompareWithAction().run(resource); } }ContinueRebaseHandler.java000066400000000000000000000020471173713500500343270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.CoreException; import com.vectrace.MercurialEclipse.dialogs.CommitDialog; import com.vectrace.MercurialEclipse.dialogs.ContinueRebaseDialog; import com.vectrace.MercurialEclipse.model.HgRoot; public class ContinueRebaseHandler extends RunnableHandler { @Override public void run(HgRoot hgRoot) throws CoreException { CommitDialog commitDialog = new ContinueRebaseDialog(getShell(), hgRoot); // open dialog and wait for ok commitDialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/DisconnectHandler.java000066400000000000000000000024541173713500500335730ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.team.core.RepositoryProvider; import com.vectrace.MercurialEclipse.team.ResourceDecorator; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; public class DisconnectHandler extends SingleResourceHandler { @Override protected void run(IResource resource) throws Exception { IProject project = resource.getProject(); RepositoryProvider.unmap(project); MercurialStatusCache.getInstance().clear(project, false); LocalChangesetCache.getInstance().clear(project, false); ResourceDecorator.updateClientDecorations(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/ExportPatchHandler.java000066400000000000000000000027521173713500500337440ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * steeven * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.ExportPatchWizard; public class ExportPatchHandler extends MultipleResourcesHandler { @Override protected void run(List resources) throws Exception { openWizard(resources, getShell()); } public void openWizard(List resources, Shell shell) throws Exception { HgRoot root = ensureSameRoot(resources); if(root == null) { MessageDialog.openError(getShell(), "Export patch", "No hg root found"); return; } ExportPatchWizard wizard = new ExportPatchWizard(resources, root); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.setBlockOnOpen(true); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/FlagPropertyTester.java000066400000000000000000000110531173713500500340040ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch - bug fixes * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import static com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache.*; import java.io.File; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.Bits; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class FlagPropertyTester extends org.eclipse.core.expressions.PropertyTester { public static final String PROPERTY_STATUS = "status"; //$NON-NLS-1$ public static final String PROPERTY_ROOT = "root"; //$NON-NLS-1$ public static final String PROPERTY_DEF_REPO = "hasDefaultRepo"; //$NON-NLS-1$ @SuppressWarnings({ "serial", "boxing" }) private static final Map BIT_MAP = Collections.unmodifiableMap( new HashMap() { { put("added", BIT_ADDED); //$NON-NLS-1$ put("clean", BIT_CLEAN); //$NON-NLS-1$ put("deleted", BIT_MISSING); //$NON-NLS-1$ put("ignore", BIT_IGNORE); //$NON-NLS-1$ put("modified", BIT_MODIFIED); //$NON-NLS-1$ put("removed", BIT_REMOVED); //$NON-NLS-1$ put("unknown", BIT_UNKNOWN); //$NON-NLS-1$ } }); public boolean test(Object receiver, String property, Object[] args, Object expectedValue) { if(PROPERTY_STATUS.equals(property)) { try { IResource res = (IResource) receiver; int test = 0; for(Object arg: args) { Integer statusBit = BIT_MAP.get(arg); if(statusBit == null){ String message = "Could not test status " + property + " on " //$NON-NLS-1$ //$NON-NLS-2$ + receiver + " for argument: " + arg; //$NON-NLS-1$ MercurialEclipsePlugin.logWarning(message, new IllegalArgumentException(message)); continue; } test |= statusBit.intValue(); } MercurialStatusCache cache = MercurialStatusCache.getInstance(); Integer status = cache.getStatus(res); if (status != null) { test &= status.intValue(); return test != 0; } else if(Bits.contains(test, MercurialStatusCache.BIT_UNKNOWN | MercurialStatusCache.BIT_IGNORE)) { // ignored or unknown files may be not yet tracked by cache, so the state may be null // we assume it is ignored or unknown if the project state is known return !(res instanceof IProject) && cache.isStatusKnown(res.getProject()); } } catch (Exception e) { MercurialEclipsePlugin.logWarning("Could not test status " + property + " on " + receiver, e); //$NON-NLS-1$ //$NON-NLS-2$ return false; } } else if(PROPERTY_ROOT.equals(property) && args[0] != null) { IResource res = (IResource) receiver; IPath location = ResourceUtils.getPath(res); if(location.isEmpty()) { return false; } HgRoot hgRoot = MercurialTeamProvider.getHgRoot(res); if(hgRoot == null){ return false; } File file = location.toFile(); boolean bool = Boolean.valueOf(args[0].toString()).booleanValue(); if(bool) { return hgRoot.equals(file); } return !hgRoot.equals(file); } else if(PROPERTY_DEF_REPO.equals(property) && args[0] != null) { IResource res = (IResource) receiver; IPath location = ResourceUtils.getPath(res); if(location.isEmpty()) { return false; } HgRoot hgRoot = MercurialTeamProvider.getHgRoot(res); if(hgRoot == null){ return false; } IHgRepositoryLocation repoLocation = MercurialEclipsePlugin.getRepoManager().getDefaultRepoLocation(hgRoot); boolean bool = Boolean.valueOf(args[0].toString()).booleanValue(); if(bool) { return repoLocation != null; } return repoLocation == null; } return false; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/HgIgnoreHandler.java000066400000000000000000000065721173713500500332110ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.IDialogConstants; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgIgnoreClient; import com.vectrace.MercurialEclipse.dialogs.IgnoreDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.ResourceDecorator; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; public class HgIgnoreHandler extends SingleResourceHandler { @Override protected void run(IResource resource) throws Exception { IgnoreDialog dialog; switch(resource.getType()) { case IResource.FILE: dialog = new IgnoreDialog(getShell(), (IFile) resource); break; case IResource.FOLDER: dialog = new IgnoreDialog(getShell(), (IFolder) resource); break; default: dialog = new IgnoreDialog(getShell()); } if(dialog.open() == IDialogConstants.OK_ID) { switch(dialog.getResultType()) { case FILE: HgIgnoreClient.addFile(dialog.getFile()); break; case EXTENSION: HgIgnoreClient.addExtension(dialog.getFile()); break; case FOLDER: HgIgnoreClient.addFolder(dialog.getFolder()); break; case GLOB: HgIgnoreClient.addGlob(resource.getProject(), dialog.getPattern()); break; case REGEXP: HgIgnoreClient.addRegexp(resource.getProject(), dialog.getPattern()); break; } refreshStatus(resource); } } private static void refreshStatus(final IResource resource) { Job job = new Job("Refreshing status for ignored resource: " + resource.getName()){ @Override protected IStatus run(IProgressMonitor monitor) { try { // update the HgRoot of the resource. This will update all projects that contain this HgRoot HgRoot root = MercurialRootCache.getInstance().getHgRoot(resource); MercurialStatusCache.getInstance().refreshStatus(root, monitor); } catch (CoreException e) { MercurialEclipsePlugin.logError(Messages.getString("HgIgnoreHandler.unableToRefreshProject"), //$NON-NLS-1$ e); return e.getStatus(); } // fix for issue #10152: // trigger decorator update for resources being ignored // For some reasons, resource.touch() and refreshLocal() isn't enough // to get updated status into the Navigator/Explorer views ResourceDecorator.updateClientDecorations(); return Status.OK_STATUS; } }; job.schedule(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/HistoryHandler.java000066400000000000000000000016511173713500500331410ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.resources.IResource; import org.eclipse.team.ui.TeamUI; public class HistoryHandler extends SingleResourceHandler { /** * @see com.vectrace.MercurialEclipse.menu.SingleResourceHandler#run(org.eclipse.core.resources.IResource) */ @Override protected void run(IResource resource) throws Exception { TeamUI.getHistoryView().showHistoryFor(resource); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/ImportPatchHandler.java000066400000000000000000000022121173713500500337240ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * steeven * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.ImportPatchWizard; public class ImportPatchHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) { openWizard(hgRoot, getShell()); } public void openWizard(final HgRoot hgRoot, Shell shell) { ImportPatchWizard wizard = new ImportPatchWizard(hgRoot); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.setBlockOnOpen(true); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/MergeHandler.java000066400000000000000000000173601173713500500325430ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - modification *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.text.MessageFormat; import java.util.ArrayList; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.commands.HgMergeClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.dialogs.RevisionChooserDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.views.MergeView; public class MergeHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) throws CoreException { determineMergeHeadAndMerge(hgRoot, getShell(), new NullProgressMonitor(), false, true); } public static String determineMergeHeadAndMerge(HgRoot hgRoot, Shell shell, IProgressMonitor monitor, boolean autoPickOtherHead, boolean showCommitDialog) throws CoreException { // can we do the equivalent of plain "hg merge"? ChangeSet cs = getHeadForEasyMerge(hgRoot); boolean forced = false; String forceMessage = "Forced merge (this will discard all uncommitted changes!)"; boolean hasDirtyFiles = HgStatusClient.isDirty(hgRoot); if (cs != null) { if (!autoPickOtherHead) { String csSummary = " Changeset: " + cs.getRevision().toString().substring(0, 20) + "\n User: " + cs.getAuthor() + "\n Date: " + cs.getDateString() + "\n Summary: " + cs.getSummary(); String branch = cs.getBranch(); if (Branch.isDefault(branch)) { branch = Branch.DEFAULT; } String message = MessageFormat.format(Messages .getString("MergeHandler.mergeWithOtherHead"), branch, csSummary); if(hasDirtyFiles){ MessageDialogWithToggle dialog = MessageDialogWithToggle.openYesNoQuestion( shell, "Merge", message, forceMessage, false, null, null); if(dialog.getReturnCode() != IDialogConstants.YES_ID) { cs = null; } forced = dialog.getToggleState(); } else { MessageBox mb = new MessageBox(shell, SWT.ICON_QUESTION | SWT.YES | SWT.NO); mb.setText("Merge"); mb.setMessage(message); if (mb.open() == SWT.NO) { cs = null; } } } } // have to open the dialog until we get a valid changeset while (cs == null) { RevisionChooserDialog dialog = new RevisionChooserDialog(shell, Messages.getString("MergeHandler.mergeWith"), hgRoot); //$NON-NLS-1$ dialog.setDefaultShowingHeads(true); dialog.setDisallowSelectingParents(true); dialog.showForceButton(hasDirtyFiles); dialog.setForceChecked(forced); dialog.setForceButtonText(forceMessage); if (dialog.open() != IDialogConstants.OK_ID) { return ""; } cs = dialog.getChangeSet(); forced = dialog.isForceChecked(); } return mergeAndCommit(hgRoot, shell, monitor, showCommitDialog, cs, forced); } public static String mergeAndCommit(HgRoot hgRoot, Shell shell, IProgressMonitor monitor, boolean showCommitDialog, ChangeSet cs, boolean forced) throws HgException, CoreException { MercurialUtilities.setOfferAutoCommitMerge(true); String result; boolean conflict = false; try { try { result = HgMergeClient.merge(hgRoot, cs.getRevision().getChangeset(), forced); } catch (HgException e) { if (HgMergeClient.isConflict(e)) { conflict = true; result = e.getMessage(); } else { throw e; } } String mergeChangesetId = cs.getChangeset(); MercurialStatusCache.getInstance().setMergeStatus(hgRoot, mergeChangesetId); if (conflict) { MergeView.showMergeConflict(hgRoot, shell); } else { try { result += commitMerge(monitor, hgRoot, mergeChangesetId, shell, showCommitDialog); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } } } finally { new RefreshWorkspaceStatusJob(hgRoot).schedule(); } return result; } private static String commitMerge(IProgressMonitor monitor, final HgRoot hgRoot, final String mergeChangesetId, final Shell shell, boolean showCommitDialog) throws CoreException { String output = ""; monitor.subTask(com.vectrace.MercurialEclipse.wizards.Messages.getString("PullRepoWizard.pullOperation.commit")); //$NON-NLS-1$ output += com.vectrace.MercurialEclipse.wizards.Messages.getString("PullRepoWizard.pullOperation.commit.header"); if (!showCommitDialog) { output += CommitMergeHandler.commitMerge(hgRoot, HgCommitMessageManager .getDefaultCommitName(hgRoot), "Merge with " + mergeChangesetId); } else { output += new CommitMergeHandler().commitMergeWithCommitDialog(hgRoot, shell); } monitor.worked(1); return output; } private static ChangeSet getHeadForEasyMerge(HgRoot hgRoot) throws HgException { ArrayList otherHeads = getOtherHeadsInCurrentBranch(hgRoot); if (otherHeads != null && otherHeads.size() == 1) { return otherHeads.get(0); } // can not perform easy merge - need to run wizard return null; } /** * Returns list of Heads in the same branch as current head. Current head itself is not included. * @param hgRoot * @return * @throws HgException */ private static ArrayList getOtherHeadsInCurrentBranch(HgRoot hgRoot) throws HgException { ArrayList result = getHeadsInCurrentBranch(hgRoot); ChangeSet currentRevision = LocalChangesetCache.getInstance().getChangesetForRoot(hgRoot); ChangeSet csToRemove = null; for (ChangeSet cs : result) { // can't be the current if (cs.getChangeset().equals(currentRevision.getChangeset())) { csToRemove = cs; break; } } if (csToRemove != null) { result.remove(csToRemove); } return result; } /** * Returns list of all Heads in the same branch as current head * @param hgRoot * @return * @throws HgException */ public static ArrayList getHeadsInCurrentBranch(HgRoot hgRoot) throws HgException { ArrayList otherHeads = new ArrayList(); ChangeSet[] heads = HgLogClient.getHeads(hgRoot); ChangeSet currentRevision = LocalChangesetCache.getInstance().getChangesetForRoot(hgRoot); if (currentRevision == null) { return otherHeads; } String branch = currentRevision.getBranch(); for (ChangeSet cs : heads) { // must match branch if (!Branch.same(branch, cs.getBranch())) { continue; } otherHeads.add(cs); } return otherHeads; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/Messages.java000066400000000000000000000021211173713500500317420ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.menu.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } MultipleResourcesHandler.java000066400000000000000000000064261173713500500351140ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/******************************************************************************* * Copyright (c) 2006-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.util.ArrayList; import java.util.List; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IResource; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.handlers.HandlerUtil; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * * @author Jerome Negre * */ public abstract class MultipleResourcesHandler extends AbstractHandler { private final List selection = new ArrayList(); private ExecutionEvent event; protected static Shell getShell() { return MercurialEclipsePlugin.getActiveShell(); } /** * * @return never null, list with resources selected by user */ protected List getSelectedResources() { return selection; } public Object execute(ExecutionEvent event1) throws ExecutionException { this.event = event1; ISelection selectionObject = HandlerUtil.getCurrentSelection(event); selection.clear(); if (selectionObject instanceof IStructuredSelection) { selection.addAll(ResourceUtils.getResources((IStructuredSelection) selectionObject)); } if (selection.isEmpty()) { selection.add(ResourceUtils.getActiveResourceFromEditor()); } try { run(getSelectedResources()); } catch (Exception e) { MessageDialog .openError( getShell(), Messages .getString("MultipleResourcesHandler.hgSays"), e.getMessage() + Messages.getString("MultipleResourcesHandler.seeErrorLog")); //$NON-NLS-1$ //$NON-NLS-2$ throw new ExecutionException(e.getMessage(), e); } finally { selection.clear(); } this.event = null; return null; } protected static HgRoot ensureSameRoot(List resources) throws HgException { final HgRoot root = MercurialTeamProvider.getHgRoot(resources.get(0)); if(root == null) { return null; } for (IResource res : resources) { if (!root.equals(MercurialTeamProvider.getHgRoot(res))) { throw new HgException( Messages .getString("MultipleResourcesHandler.allResourcesMustBeInSameProject")); //$NON-NLS-1$ } } return root; } protected abstract void run(List resources) throws Exception; public ExecutionEvent getEvent() { return event; } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/PullHandler.java000066400000000000000000000020121173713500500324040ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.PullRepoWizard; public class PullHandler extends RootHandler { @Override protected void run(final HgRoot hgRoot) { PullRepoWizard pullRepoWizard = new PullRepoWizard(hgRoot); WizardDialog pullWizardDialog = new WizardDialog(getShell(), pullRepoWizard); pullWizardDialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/PushHandler.java000066400000000000000000000023001173713500500324070ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.PushRepoWizard; public class PushHandler extends RootHandler { private String message; @Override public void run(final HgRoot hgRoot) { PushRepoWizard pushRepoWizard = new PushRepoWizard(hgRoot); WizardDialog pushWizardDialog = new WizardDialog(getShell(), pushRepoWizard); if (message != null) { pushRepoWizard.setInitialMessage(message); } pushWizardDialog.open(); } public void setInitialMessage(String message) { this.message = message; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/QDeleteHandler.java000066400000000000000000000024371173713500500330260ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.mq.QDeleteWizard; /** * @author bastian * */ public class QDeleteHandler extends RootHandler { /** * @see com.vectrace.MercurialEclipse.menu.RootHandler#run(com.vectrace.MercurialEclipse.model.HgRoot) */ @Override protected void run(HgRoot root) { openWizard(root, getShell(), true); } public static void openWizard(HgRoot root, Shell shell, boolean bShowRevSelector) { QDeleteWizard wizard = new QDeleteWizard(root, bShowRevSelector); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.setBlockOnOpen(true); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/QImportHandler.java000066400000000000000000000023551173713500500330750ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.mq.QImportWizard; /** * @author bastian * */ public class QImportHandler extends RootHandler { /** * @see com.vectrace.MercurialEclipse.menu.RootHandler#run(com.vectrace.MercurialEclipse.model.HgRoot) */ @Override protected void run(HgRoot root) { openWizard(root, getShell()); } public static void openWizard(HgRoot root, Shell shell) { QImportWizard wizard = new QImportWizard(root); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.setBlockOnOpen(true); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/QInitHandler.java000066400000000000000000000017631173713500500325300ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.resources.IResource; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.wizards.mq.QInitWizard; public class QInitHandler extends SingleResourceHandler { @Override protected void run(IResource resource) throws Exception { QInitWizard wizard = new QInitWizard(resource); WizardDialog dialog = new WizardDialog(getShell(), wizard); dialog.setBlockOnOpen(true); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/QNewHandler.java000066400000000000000000000022201173713500500323430ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.mq.QNewWizard; public class QNewHandler extends RootHandler { @Override protected void run(HgRoot root) { openWizard(root, getShell()); } public static void openWizard(HgRoot root, Shell shell) { Assert.isNotNull(root); QNewWizard wizard = new QNewWizard(root); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.setBlockOnOpen(true); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/QRefreshHandler.java000066400000000000000000000022421173713500500332140ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.mq.QRefreshWizard; public class QRefreshHandler extends RootHandler { @Override protected void run(HgRoot root) { openWizard(root, getShell()); } public static void openWizard(HgRoot root, Shell shell) { Assert.isNotNull(root); QRefreshWizard wizard = new QRefreshWizard(root); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.setBlockOnOpen(true); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/RebaseHandler.java000066400000000000000000000035621173713500500327040ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - initial implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.commands.extensions.HgRebaseClient; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.RebaseWizard; public class RebaseHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) throws CoreException { if (HgRebaseClient.isRebasing(hgRoot)) { MessageDialog dialog = new MessageDialog(null, Messages .getString("RebaseHandler.inProgress"), null, Messages .getString("RebaseHandler.inProgressAbortOrContinue"), MessageDialog.QUESTION, new String[] { Messages.getString("RebaseHandler.cancel"), Messages.getString("RebaseHandler.abort"), Messages.getString("RebaseHandler.continue") }, 2); switch (dialog.open()) { case 1: // Shouldn't fail HgRebaseClient.abortRebase(hgRoot); break; case 2: ContinueRebaseHandler handler = new ContinueRebaseHandler(); handler.setShell(getShell()); handler.run(hgRoot); break; } } else { RebaseWizard wizard = new RebaseWizard(hgRoot); WizardDialog wizardDialog = new WizardDialog(getShell(), wizard); wizardDialog.open(); } } } RefreshStatusHandler.java000066400000000000000000000113061173713500500342210ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.RefreshStatusJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class RefreshStatusHandler extends MultipleResourcesHandler { @Override protected void run(List resources) throws Exception { for (IResource res : resources) { MercurialRootCache.uncache(res); } if(resources.size() == 1){ refreshSingleResource(resources.get(0)); return; } // separate files or projects are selected Set singleFiles = collectSingleFiles(resources); for (IResource resource : singleFiles) { refreshSingleResource(resource); } resources.removeAll(singleFiles); if(resources.isEmpty()){ return; } Set singleProjects = collectSingleProjects(resources); for (IProject project : singleProjects) { refreshSingleProject(project); } resources.removeAll(singleProjects); if(resources.isEmpty()){ return; } for (HgRoot hgRoot : ResourceUtils.groupByRoot(resources).keySet()) { refreshRoot(hgRoot); } } static Set collectSingleFiles(List resources){ Map> byProject = ResourceUtils.groupByProject(resources); Set>> resSet = byProject.entrySet(); Set singleResources = new HashSet(); for (Entry> entry : resSet) { if(!resources.contains(entry.getKey())){ singleResources.addAll(entry.getValue()); } } // filter out resources contained in other resources Iterator iterator = singleResources.iterator(); while (iterator.hasNext()) { IResource resource = iterator.next(); for (IResource other : singleResources) { if(other != resource && other.contains(resource)){ iterator.remove(); break; } } } return singleResources; } static Set collectSingleProjects(List resources){ Set singleProjects = new HashSet(); Map> byRoot = ResourceUtils.groupByRoot(resources); Set>> entrySet = byRoot.entrySet(); for (Entry> entry : entrySet) { HgRoot hgRoot = entry.getKey(); List hgProjects = MercurialTeamProvider.getKnownHgProjects(hgRoot); List selected = entry.getValue(); if(selected.size() < hgProjects.size() / 2){ singleProjects.addAll((Collection) selected); } } return singleProjects; } private static void refreshRoot(final HgRoot hgRoot) { new RefreshStatusJob("Refreshing hg root " + hgRoot.getName(), hgRoot).schedule(); } private static void refreshSingleProject(final IProject project) { new RefreshStatusJob("Refreshing project " + project.getName(), project).schedule(); } private static void refreshSingleResource(final IResource resource) { new Job( Messages.getString("RefreshStatusHandler.refreshingResource") + " " + resource.getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$ @Override protected IStatus run(IProgressMonitor monitor) { try { MercurialStatusCache.getInstance().refreshStatus(resource, monitor); } catch (HgException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } finally { monitor.done(); } return Status.OK_STATUS; } }.schedule(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/RevertHandler.java000066400000000000000000000021551173713500500327470ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.StructuredSelection; import com.vectrace.MercurialEclipse.team.ActionRevert; public class RevertHandler extends MultipleResourcesHandler { /** * @see com.vectrace.MercurialEclipse.menu.MultipleResourcesHandler#run(java.util.List) */ @Override protected void run(List resources) throws Exception { final ActionRevert revert = new ActionRevert(); revert.selectionChanged(null, new StructuredSelection(resources)); revert.run(null); } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/RollbackHandler.java000066400000000000000000000021161173713500500332260ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.dialogs.MessageDialog; import com.vectrace.MercurialEclipse.commands.HgRollbackClient; import com.vectrace.MercurialEclipse.model.HgRoot; public class RollbackHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) throws CoreException { String result = HgRollbackClient.rollback(hgRoot); MessageDialog.openInformation(getShell(), Messages.getString("RollbackHandler.output"), result); //$NON-NLS-1$ } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/RootHandler.java000066400000000000000000000065671173713500500324360ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.handlers.HandlerUtil; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Andrei */ public abstract class RootHandler extends AbstractHandler { private HgRoot selection; private Shell shell; protected Shell getShell() { return shell != null? shell : MercurialEclipsePlugin.getActiveShell(); } protected HgRoot getSelectedRoot() { return selection; } /** * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) */ public Object execute(ExecutionEvent event) throws ExecutionException { selection = null; ISelection selectionObject = HandlerUtil.getCurrentSelection(event); try { if (selectionObject != null && selectionObject instanceof IStructuredSelection) { Object listEntry = ((IStructuredSelection) selectionObject).getFirstElement(); if (listEntry instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) listEntry; selection = MercurialEclipsePlugin.getAdapter(adaptable, HgRoot.class); } if (selection == null) { IResource resource = ResourceUtils.getResource(listEntry); if (resource != null) { selection = MercurialTeamProvider.getHgRoot(resource); } } } if (selection == null) { IFile file = ResourceUtils.getActiveResourceFromEditor(); if (file != null) { selection = MercurialTeamProvider.getHgRoot(file); } } if (selection == null) { MessageDialog.openError(getShell(), "Error", "Hg root not known!"); return null; } run(getSelectedRoot()); } catch (CoreException e) { MessageDialog .openError( getShell(), Messages.getString("SingleResourceHandler.hgSays"), e.getMessage() + Messages.getString("SingleResourceHandler.seeErrorLog")); //$NON-NLS-1$ //$NON-NLS-2$ throw new ExecutionException(e.getMessage(), e); } return null; } /** * @param shell the shell to set, may be null */ public void setShell(Shell shell) { this.shell = shell; } /** * @param hgRoot never null * @throws HgException */ protected abstract void run(HgRoot hgRoot) throws CoreException; }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/RootHistoryHandler.java000066400000000000000000000014721173713500500340060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.team.ui.TeamUI; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author Andrei */ public class RootHistoryHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) { TeamUI.getHistoryView().showHistoryFor(hgRoot); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/RunnableHandler.java000066400000000000000000000014501173713500500332430ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.CoreException; import com.vectrace.MercurialEclipse.model.HgRoot; public abstract class RunnableHandler extends RootHandler { @Override public abstract void run(HgRoot hgRoot) throws CoreException; } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/SearchHandler.java000066400000000000000000000034561173713500500327120ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.search.ui.NewSearchUI; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.handlers.HandlerUtil; public class SearchHandler extends AbstractHandler { /** * Mercurial search page id, as defined in plugin.xml */ public static final String MERCURIAL_ECLIPSE_SEARCH_PAGE = "MercurialEclipse.searchPage"; public Object execute(ExecutionEvent event) throws ExecutionException { NewSearchUI.openSearchDialog(HandlerUtil.getActiveWorkbenchWindow(event), MERCURIAL_ECLIPSE_SEARCH_PAGE); return null; } public static class SearchAction implements IWorkbenchWindowActionDelegate { private IWorkbenchWindow window; public void run(IAction action) { NewSearchUI.openSearchDialog(window, MERCURIAL_ECLIPSE_SEARCH_PAGE); } public void selectionChanged(IAction action, ISelection selection) { // noop } public void dispose() { window = null; } public void init(IWorkbenchWindow window1) { this.window = window1; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/ServeHandler.java000066400000000000000000000017441173713500500325670ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.ServeWizard; public class ServeHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) { ServeWizard wizard = new ServeWizard(hgRoot); WizardDialog wizardDialog = new WizardDialog(getShell(), wizard); wizardDialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/ShelveHandler.java000066400000000000000000000051501173713500500327240ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeWorkspaceJob; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.ShelveOperation; /** * @author bastian */ public class ShelveHandler extends RootHandler { @Override protected void run(final HgRoot hgRoot) { new SafeWorkspaceJob(Messages.getString("ShelveHandler.Shelving")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor) { final ShelveOperation op = new ShelveOperation((IWorkbenchPart) null, hgRoot); try { op.run(monitor); return super.runSafe(monitor); } catch (InvocationTargetException e) { if (op.getShelveFileConflict() != null) { getShell().getDisplay().asyncExec(new Runnable() { public void run() { MessageDialog dialog = new MessageDialog(getShell(), "Shelve file exists. Delete shelved changes?", null, "Shelve file exists. You must unshelve before shelving anew. " + "Would you like to delete shelved changes instead?", MessageDialog.QUESTION, new String[] { "Delete shelved changes", "Retain" }, 1) { { setShellStyle(getShellStyle() | SWT.SHEET); } }; if (dialog.open() == 0) { op.getShelveFileConflict().delete(); ShelveHandler.this.run(hgRoot); } } }); return Status.OK_STATUS; } return new Status(IStatus.WARNING, MercurialEclipsePlugin.ID, 0, e .getLocalizedMessage(), e); } catch (InterruptedException e) { return new Status(IStatus.INFO, MercurialEclipsePlugin.ID, 0, e .getLocalizedMessage(), e); } } }.schedule(); } } ShowAnnotationsHandler.java000066400000000000000000000017331173713500500345600ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/******************************************************************************* * Copyright (c) 2011 John Peberdy and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.team.ActionAnnotate; public class ShowAnnotationsHandler extends SingleResourceHandler { /** * @see com.vectrace.MercurialEclipse.menu.SingleResourceHandler#run(org.eclipse.core.resources.IResource) */ @Override protected void run(IResource resource) throws Exception { if (resource != null) { new ActionAnnotate().run(resource); } } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/SignHandler.java000066400000000000000000000025571173713500500324060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.SignWizard; public class SignHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) { SignWizard signWizard = new SignWizard(hgRoot); WizardDialog dialog = new WizardDialog(getShell(), signWizard); dialog.open(); // if(result == Window.OK) { // Andrei: I do not see any reason to update anything after the sign operation. // the only change is the changeset info, which is not shown anywhere in Eclipse except // the history view, and the history view has a "refresh" button // new RefreshJob(Messages.getString("SignHandler.refreshingStatusAndChangesetCache"), project).schedule(); //$NON-NLS-1$ // } } } SingleResourceHandler.java000066400000000000000000000046551173713500500343610ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IResource; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.handlers.HandlerUtil; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * * @author Jerome Negre * */ public abstract class SingleResourceHandler extends AbstractHandler { private IResource selection; private Shell shell; protected Shell getShell() { return shell != null? shell : MercurialEclipsePlugin.getActiveShell(); } public Object execute(ExecutionEvent event) throws ExecutionException { selection = null; ISelection selectionObject = HandlerUtil.getCurrentSelection(event); try { if (selectionObject instanceof IStructuredSelection) { IStructuredSelection ssel = (IStructuredSelection) selectionObject; selection = ResourceUtils.getResource(ssel.getFirstElement()); } if (selection == null) { selection = ResourceUtils.getActiveResourceFromEditor(); } if (selection != null) { run(selection); } } catch (Exception e) { MessageDialog .openError( getShell(), Messages.getString("SingleResourceHandler.hgSays"), e.getMessage() + Messages.getString("SingleResourceHandler.seeErrorLog")); //$NON-NLS-1$ //$NON-NLS-2$ throw new ExecutionException(e.getMessage(), e); } return null; } /** * @param shell the shell to set, may be null */ public void setShell(Shell shell) { this.shell = shell; } protected abstract void run(IResource resource) throws Exception; }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/StripHandler.java000066400000000000000000000023411173713500500325760ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.StripWizard; public class StripHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) { openWizard(hgRoot, getShell(), null); } public static void openWizard(HgRoot hgRoot, Shell shell, ChangeSet changeset) { StripWizard stripWizard = new StripWizard(hgRoot, changeset); WizardDialog dialog = new WizardDialog(shell, stripWizard); dialog.setBlockOnOpen(true); dialog.open(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/SwitchHandler.java000066400000000000000000000033541173713500500327430ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.dialogs.RevisionChooserDialog; import com.vectrace.MercurialEclipse.model.HgRoot; public class SwitchHandler extends RootHandler { @Override public void run(HgRoot hgRoot) throws CoreException { boolean lossConfirmed = false; if (HgStatusClient.isDirty(hgRoot)) { if (!MessageDialog .openQuestion(getShell(), Messages.getString("SwitchHandler.pendingChangesConfirmation.1"), //$NON-NLS-1$ Messages.getString("SwitchHandler.pendingChangesConfirmation.2"))) { //$NON-NLS-1$ return; } lossConfirmed = true; } RevisionChooserDialog dialog = new RevisionChooserDialog(getShell(), Messages.getString("SwitchHandler.switchTo"), hgRoot); //$NON-NLS-1$ int result = dialog.open(); if (result == IDialogConstants.OK_ID) { UpdateJob job = new UpdateJob(dialog.getRevision(), true, hgRoot, false); job.setDataLossConfirmed(lossConfirmed); job.schedule(); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/SyncHandler.java000066400000000000000000000070471173713500500324210ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeParticipant; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.wizards.MercurialParticipantSynchronizeWizard; public class SyncHandler extends MultipleResourcesHandler { @Override protected void run(List resources) throws Exception { if(resources.isEmpty()) { return; } boolean showLocalChanges = getId().equals("com.vectrace.MercurialEclipse.menu.SyncHandler3"); MercurialParticipantSynchronizeWizard wizard = new MercurialParticipantSynchronizeWizard(); wizard.init(PlatformUI.getWorkbench(), new StructuredSelection(resources)); if(showLocalChanges || !shouldShowWizard(wizard)) { if(showLocalChanges) { HgRoot root = MercurialTeamProvider.getHgRoot(resources.get(0)); if(root == null) { return; } IProject[] projects; if(syncAllProjectsInRepo()) { projects = new IProject[] { root.getResource() }; } else { projects = MercurialTeamProvider.getKnownHgProjects(root).toArray(new IProject[0]); } MercurialSynchronizeParticipant participant = MercurialParticipantSynchronizeWizard.createParticipant(root, projects); MercurialParticipantSynchronizeWizard.openSyncView(participant); } else { wizard.performFinish(); } } else { WizardDialog wizardDialog = new WizardDialog(getShell(), wizard); wizardDialog.open(); } } private boolean shouldShowWizard(MercurialParticipantSynchronizeWizard wizard){ if(wizard.prepareSettings() == null){ return true; } String id = getId(); return !"com.vectrace.MercurialEclipse.menu.SyncHandler".equals(id); } private String getId() { ExecutionEvent executionEvent = getEvent(); return executionEvent.getCommand().getId(); } @Override protected List getSelectedResources() { List resources = super.getSelectedResources(); if(syncAllProjectsInRepo()) { Map> byRoot = ResourceUtils.groupByRoot(resources); resources.clear(); Set roots = byRoot.keySet(); for (HgRoot root : roots) { IProject rootProj = root.getResource(); resources.add(rootProj); } } return resources; } private static boolean syncAllProjectsInRepo() { return MercurialEclipsePlugin.getDefault().getPreferenceStore() .getBoolean(MercurialPreferenceConstants.PREF_SYNC_ALL_PROJECTS_IN_REPO); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/TagHandler.java000066400000000000000000000032131173713500500322070ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - Initial implementation * Bastian Doetsch - implemented some safeguards for the ok button * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.dialogs.IDialogConstants; import com.vectrace.MercurialEclipse.commands.HgTagClient; import com.vectrace.MercurialEclipse.dialogs.TagDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; /** * @author Jerome Negre */ public class TagHandler extends RootHandler { @Override protected void run(HgRoot hgRoot) throws CoreException { TagDialog dialog = new TagDialog(getShell(), hgRoot); if (dialog.open() != IDialogConstants.OK_ID) { return; } String name = dialog.getName(); if (name != null && name.trim().length() > 0) { HgTagClient.addTag(hgRoot, name.trim(), dialog.getTargetRevision(), dialog.getUser(), dialog .isLocal(), dialog.isForced()); new RefreshRootJob( Messages.getString("TagHandler.refreshing"), hgRoot, RefreshRootJob.LOCAL_AND_OUTGOING).schedule(); //$NON-NLS-1$ } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/TransplantHandler.java000066400000000000000000000042121173713500500336220ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.wizard.WizardDialog; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.TransplantOperation; import com.vectrace.MercurialEclipse.wizards.TransplantWizard; public class TransplantHandler extends RootHandler { @Override protected void run(final HgRoot hgRoot) throws CoreException { if (HgStatusClient.isDirty(hgRoot)) { MessageDialog dialog = new MessageDialog(null, Messages .getString("TransplantHandler.dirtyTitle"), null, Messages .getString("TransplantHandler.dirtyMessage"), MessageDialog.QUESTION, new String[] { Messages.getString("TransplantHandler.cancel"), Messages.getString("TransplantHandler.continue") }, 0); if (dialog.open() == 1) { TransplantOperation op = TransplantOperation.createContinueOperation(MercurialEclipsePlugin.getActiveWindow(), hgRoot); try { op.run(); } catch (InvocationTargetException e) { MercurialEclipsePlugin.showError(e.getTargetException()); } catch (InterruptedException e) { MercurialEclipsePlugin.logError(e); } } } else { TransplantWizard transplantWizard = new TransplantWizard(hgRoot); WizardDialog transplantWizardDialog = new WizardDialog(getShell(), transplantWizard); transplantWizardDialog.open(); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/UnShelveHandler.java000066400000000000000000000065721173713500500332400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeWorkspaceJob; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.dialogs.RejectsDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.UnShelveOperation; /** * @author bastian */ public class UnShelveHandler extends RootHandler { @Override protected void run(final HgRoot hgRoot) { final UnshelveJob job = new UnshelveJob(Messages.getString("UnShelveHandler.Unshelving"), hgRoot); try { if (HgStatusClient.isDirty(hgRoot)) { getShell().getDisplay().asyncExec(new Runnable() { public void run() { if (MessageDialog.openQuestion(getShell(), "Outstanding uncommitted changes!", "There are outstanding uncommitted changes. Force unshelve?")) { job.setForce(true); job.schedule(); } } }); return; } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } job.schedule(); } private final class UnshelveJob extends SafeWorkspaceJob { private final HgRoot hgRoot; private boolean force; private UnshelveJob(String name, HgRoot hgRoot) { super(name); this.hgRoot = hgRoot; } public void setForce(boolean force) { this.force = force; } @Override protected IStatus runSafe(IProgressMonitor monitor) { try { final UnShelveOperation op = new UnShelveOperation((IWorkbenchPart) null, hgRoot, force); op.run(monitor); if (op.isConflict()) { getShell().getDisplay().asyncExec(new Runnable() { public void run() { try { new RejectsDialog(getShell(), hgRoot, op.getResult(), "UnshelveRejectsDialog.title", "UnshelveRejectsDialog.conflict").open(); } catch (HgException e) { // Fallback if couldn't parse rejects MessageDialog.openInformation(getShell(), Messages .getString("UnShelveHandler.Unshelving"), Messages .getString("UnShelveHandler.conflict") + "\n" + op.getResult()); MercurialEclipsePlugin.logError(e); } } }); } return super.runSafe(monitor); } catch (InvocationTargetException e) { return new Status(IStatus.WARNING, MercurialEclipsePlugin.ID, 0, e .getLocalizedMessage(), e); } catch (InterruptedException e) { return new Status(IStatus.INFO, MercurialEclipsePlugin.ID, 0, e .getLocalizedMessage(), e); } } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/UpdateHandler.java000066400000000000000000000034301173713500500327170ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; public class UpdateHandler extends RunnableHandler { private String revision; private boolean cleanEnabled; private boolean handleCrossBranches = true; public UpdateHandler() { } public UpdateHandler(boolean handleCrossBranches) { this.handleCrossBranches = handleCrossBranches; } /** * @param hgRoot * non null * @throws HgException */ @Override public void run(HgRoot hgRoot) throws HgException { UpdateJob job = new UpdateJob(revision, cleanEnabled, hgRoot, handleCrossBranches); if (cleanEnabled && !job.confirmDataLoss(getShell())) { return; } job.schedule(); } /** * @param revision * the revision to use for the '-r' option, can be null */ public void setRevision(String revision) { this.revision = revision; } public void setRevision(HgRevision rev) { this.revision = rev.getChangeset(); } /** * @param cleanEnabled * true to add '-C' option */ public void setCleanEnabled(boolean cleanEnabled) { this.cleanEnabled = cleanEnabled; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/UpdateJob.java000066400000000000000000000126521173713500500320620ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Bastian Doetsch. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - modifications * Zsolt Koppany (Intland) *******************************************************************************/ package com.vectrace.MercurialEclipse.menu; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.commands.HgUpdateClient; import com.vectrace.MercurialEclipse.dialogs.NewHeadsDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * Update to a revision, optionally with the clean flag. * * Always call {@link #confirmDataLoss(Shell)} or {@link #setDataLossConfirmed(boolean)}. * * @author Bastian */ public class UpdateJob extends Job { private final HgRoot hgRoot; private final boolean cleanEnabled; private final String revision; private boolean handleCrossBranches = false; private boolean dataLossConfirmed; /** * Job to do a working directory update to the specified version. * @param revision the target revision * @param cleanEnabled if true, discard all local changes. * @param handleCrossBranches */ public UpdateJob(String revision, boolean cleanEnabled, HgRoot hgRoot, boolean handleCrossBranches) { super("Updating working directory"); this.hgRoot = hgRoot; this.cleanEnabled = cleanEnabled; this.revision = revision; this.handleCrossBranches = handleCrossBranches; } @Override public IStatus run(IProgressMonitor monitor) { String jobName = "Updating " + hgRoot.getName(); if (revision != null && revision.length()>0) { jobName += " to revision " + revision; } if (cleanEnabled) { jobName += " discarding all local changes (-C option)."; } monitor.beginTask(jobName, 3); monitor.subTask("Calling Mercurial..."); monitor.worked(1); try { if (cleanEnabled && !dataLossConfirmed) { // The root could have become dirty since confirmDataLoss() was called if (HgStatusClient.isDirty(hgRoot)) { return new HgException("The root has become dirty. Update cancelled").getStatus(); } // TODO: in some cases it is possible to turn off cleanEnabled. } monitor.worked(1); HgUpdateClient.update(hgRoot, revision, cleanEnabled); monitor.worked(1); // if revision != null then it's an update operation to particular change set, // don't need to handle cross branches in this case if (MergeHandler.getHeadsInCurrentBranch(hgRoot).size() > 1 && revision == null && handleCrossBranches) { handleMultipleHeads(hgRoot, cleanEnabled); } } catch (HgException e) { if (handleCrossBranches && HgUpdateClient.isCrossesBranchError(e)) { // don't log this error because it's a common situation and can be handled handleMultipleHeads(hgRoot, cleanEnabled); return new Status(IStatus.OK, MercurialEclipsePlugin.ID, "Update canceled - merge needed"); } MercurialEclipsePlugin.logError(e); return e.getStatus(); } finally { monitor.done(); } return new Status(IStatus.OK, MercurialEclipsePlugin.ID, "Update to revision " + revision + " succeeded."); } public static void handleMultipleHeads(final HgRoot root, final boolean clean) { Display.getDefault().syncExec(new Runnable() { public void run() { NewHeadsDialog dialog; try { dialog = new NewHeadsDialog(Display.getDefault().getActiveShell(), root); dialog.setClean(clean); // dialog.setBlockOnOpen(true); dialog.open(); } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); } } }); } /** * Call from the UI thread. * @return True if loss was confirmed. */ private static boolean showConfirmDataLoss(Shell shell) { MessageDialog dialog = new MessageDialog( shell, Messages.getString("UpdateJob.uncommittedChanges1"), null, Messages.getString("UpdateJob.uncommittedChanges2"), MessageDialog.CONFIRM, new String[]{ Messages.getString("UpdateJob.continueAndDiscard"), IDialogConstants.CANCEL_LABEL}, 1 // default index - cancel ); dialog.setBlockOnOpen(true); return dialog.open() == 0; } public boolean confirmDataLoss(final Shell shell) throws HgException { if (HgStatusClient.isDirty(hgRoot)) { final boolean[] result = new boolean[1]; if (Display.getCurrent() == null) { Display.getDefault().syncExec(new Runnable() { public void run() { result[0] = showConfirmDataLoss(shell); } }); } else { result[0] = showConfirmDataLoss(shell); } if (!result[0]) { return false; } dataLossConfirmed = true; return true; } return true; } public void setDataLossConfirmed(boolean lossOk) { dataLossConfirmed = lossOk; } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/menu/messages.properties000066400000000000000000000062471173713500500332720ustar00rootroot00000000000000AddHandler.addToVersionControl=Add to Version Control... AddHandler.refreshStatus=Refreshing status after adding resources... AddHandler.selectFiles=Select the files to add to Mercurial BookmarkHandler.extNotAvailable=Bookmarks extension not available BookmarkHandler.extNotAvailableLong.1=The bookmarks extension is not available in your Mercurial installation.\n BookmarkHandler.extNotAvailableLong.2=Please consider updating your installation to a Mercurial development version\n BookmarkHandler.extNotAvailableLong.3=as stable Mercurial releases < 1.1 don't provide this extension. CommitHandler.refreshing=Refreshing local changesets after commit... CommitMergeHandler.clearingMergeView=Clearing merge view... CommitMergeHandler.failedToSetMergeStatus=Failed to set merge status CommitMergeHandler.mergeWith=Merge with CommitMergeHandler.refreshStatusAndChangesetsAfterMergeCommit=Refresh status and changesets after merge commit... HgIgnoreHandler.unableToRefreshProject=Unable to refresh project: MergeHandler.mergeWith=Merge With... MergeHandler.mergeWithOtherHead=There is only one other head in current branch ({0}):\n\n{1}\n\nDo you wish to merge with this head? MultipleResourcesHandler.allResourcesMustBeInSameProject=All resources must be in the same project. It will be fixed soon ;) MultipleResourcesHandler.hgSays=Hg says... MultipleResourcesHandler.seeErrorLog=\nSee Error Log for more details. RefreshStatusHandler.refreshingResource=Refreshing resource RebaseHandler.inProgress=Mercurial Rebase in Progress RebaseHandler.inProgressAbortOrContinue=Rebase in progress. Would you like to continue or abort the rebase? RebaseHandler.abort=Abort RebaseHandler.cancel=Cancel RebaseHandler.continue=Continue RollbackHandler.output=Rollback output RollbackHandler.refresh=Refreshing status and changesets after rollback... ShelveHandler.Shelving=Shelving... ShowAnnotationHandler.hgSays=Hg says... ShowAnnotationHandler.seeErrorLogForMoreDetails=\nSee error log for more details. SignHandler.refreshingStatusAndChangesetCache=Refreshing status and changeset cache after signing... SingleResourceHandler.hgSays=Hg says... SingleResourceHandler.seeErrorLog=\nSee Error Log for more details. SwitchHandler.pendingChangesConfirmation.1=Do you really want to switch changesets? SwitchHandler.pendingChangesConfirmation.2=The Mercurial repository has uncommitted changes. Do you want to continue and discard them? SwitchHandler.switchTo=Switch to... TagHandler.refreshing=Refreshing status and changesets after changing tags... TransplantHandler.cancel=Cancel TransplantHandler.continue=Continue transplant TransplantHandler.dirtyMessage=There are outstanding uncommitted changes. Transplant is not possible with outstanding uncommitted changes. If this is because of a transplant in progress you can continue the transplant. Otherwise press cancel. TransplantHandler.dirtyTitle=Transplant UnShelveHandler.Unshelving=Unshelving... UnShelveHandler.conflict=A conflict occurred while unshelving: UpdateJob.uncommittedChanges1=Uncommitted changes UpdateJob.uncommittedChanges2=There are uncommitted changes. Continuing will discard uncommitted changes! Do you want to continue? UpdateJob.continueAndDiscard=Continue and discard changeseclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/messages.properties000066400000000000000000000024201173713500500323130ustar00rootroot00000000000000DefaultConfiguration.notCorrectlyConfigured=\ not correctly configured in preferences. DefaultConfiguration.timeoutForCommand=Timeout for command DefaultConfiguration.timoutLessThanEqual=Timeout < 0 MercurialEclipsePlugin.checkingMercurialInstallation=Checking Mercurial installation. MercurialEclipsePlugin.expectedAtLeast=. Expected is at least MercurialEclipsePlugin.loadingKnownMercurialRepositories=Loading known Mercurial repositories. MercurialEclipsePlugin.openingMercurialConsole=Opening Mercurial console... MercurialEclipsePlugin.showError=Show Error MercurialEclipsePlugin.startedSuccessfully=MercurialEclipse started successfully. MercurialEclipsePlugin.startingCommitMessageManager=Starting Commit Message manager. MercurialEclipsePlugin.startingMercurialEclipse=Starting MercurialEclipse MercurialEclipsePlugin.unableToStart=Errors occured during startup of MercurialEclipse plugin MercurialEclipsePlugin.unexpectedError=Unexpected error MercurialEclipsePlugin.unexpectedErrors=Unexpected errors :-( MercurialEclipsePlugin.unexpectedErrorsOccured=There are some unexpected Mercurial errors occured. \ \nPlease check the Error Log view for detailed information. MercurialEclipsePlugin.unsupportedHgVersion=Unsupported hg version: Dialogs.DontShowAgain=Don't show this message againeclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/000077500000000000000000000000001173713500500274705ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/Bookmark.java000066400000000000000000000043271173713500500321060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import org.eclipse.core.runtime.Assert; public class Bookmark { /** name of the branch, unique in the repository */ private final String name; private final int revision; private final String shortNode; private final boolean active; public Bookmark(String name, int revision, String globalId, boolean active) { super(); this.name = name; this.revision = revision; this.shortNode = globalId; this.active = active; } public Bookmark(String line) { Assert.isTrue(line.length() > 0); Assert.isTrue(!line.startsWith("no bookmarks set")); //$NON-NLS-1$ active = line.startsWith(" *"); //$NON-NLS-1$ int lastSpace = line.lastIndexOf(" "); //$NON-NLS-1$ name = line.substring(3, lastSpace).trim(); int colon = line.lastIndexOf(":"); //$NON-NLS-1$ revision = Integer.parseInt(line.substring(lastSpace + 1, colon)); shortNode = line.substring(colon + 1); } public String getName() { return name; } public int getRevision() { return revision; } public String getShortNodeId() { return shortNode; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Bookmark other = (Bookmark) obj; if (name == null) { if (other.name != null) { return false; } } else if (!name.equals(other.name)) { return false; } return true; } /** * @return the active */ public boolean isActive() { return active; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/Branch.java000066400000000000000000000051541173713500500315350ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.util.Comparator; public class Branch { public static final Comparator COMPARATOR = new BranchComparator(); public static final String DEFAULT = "default"; /** name of the branch, unique in the repository */ private final String name; private final int revision; private final String globalId; private final boolean active; public Branch(String name, int revision, String globalId, boolean active) { super(); this.name = name; this.revision = revision; this.globalId = globalId; this.active = active; } public String getName() { return name; } public int getRevision() { return revision; } public String getGlobalId() { return globalId; } public boolean isActive() { return active; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Branch other = (Branch) obj; return same(name, other.name); } /** * @param name1 may be null * @param name2 may be null * @return true if both names can represent same hg branch */ public static boolean same(String name1, String name2){ if(name1 == null || name2 == null){ return name1 == name2; } if(name1.equals(name2)){ return true; } if(isDefault(name1) && isDefault(name2)){ return true; } return false; } /** * @param name may be null * @return true if the given name matches the hg default branch name * (this is also the case if given name is null) */ public static boolean isDefault(String name){ return name == null || (name.length() == 0 || name.equals(DEFAULT)); } private static class BranchComparator implements Comparator { /** * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(Branch o1, Branch o2) { return o2.getRevision() - o1.getRevision(); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/ChangeSet.java000066400000000000000000000507411173713500500322030ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2007-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Charles O'Farrell - HgRevision * Bastian Doetsch - some more info fields * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) - bug fixes * Adam Berkes (Intland) - bug fixes * Philip Graf - bug fix *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.io.File; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.team.core.synchronize.SyncInfoTree; import org.eclipse.team.internal.core.subscribers.CheckedInChangeSet; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.FileStatus.Action; import com.vectrace.MercurialEclipse.properties.DoNotDisplayMe; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.utils.ChangeSetUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.utils.StringUtils; @SuppressWarnings("restriction") public class ChangeSet extends CheckedInChangeSet implements Comparable { private static final List EMPTY_STATUS = Collections.unmodifiableList(new ArrayList()); private static final Tag[] EMPTY_TAGS = new Tag[0]; private final IFile[] EMPTY_FILES = new IFile[0]; private static final SimpleDateFormat INPUT_DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd HH:mm Z"); private static final SimpleDateFormat DISPLAY_DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd HH:mm"); public static final Date UNKNOWN_DATE = new Date(0); public static enum Direction { INCOMING, OUTGOING, LOCAL; } private final HgRevision revision; private final int changesetIndex; private final String changeset; private final String branch; private final String user; private final String date; private String tagsStr; private List changedFiles; private String comment; private String nodeShort; private String[] parents; private Date realDate; File bundleFile; private IHgRepositoryLocation repository; Direction direction; private final HgRoot hgRoot; Set files; private Tag[] tags; /** * A "dummy" changeset containing no additional information except given data */ public static class ShallowChangeSet extends ChangeSet { /** * Creates a shallow changeset containing only provided data * @param changesetIndex * @param changeSet non null * @param root non null */ public ShallowChangeSet(int changesetIndex, String changeSet, HgRoot root) { super(changesetIndex, changeSet, null, null, null, null, "", null, root); } } /** * A more or less dummy changeset containing only index and global id. Such changeset is useful * and can be constructed from the other changesets "parent" ids */ public static class ParentChangeSet extends ShallowChangeSet { /** * @param indexAndId * a semicolon separated index:id pair * @param child * this changeset's child from which we are constructing the parent */ public ParentChangeSet(String indexAndId, ChangeSet child) { super(getIndex(indexAndId), getChangeset(indexAndId), child.getHgRoot()); this.bundleFile = child.getBundleFile(); this.direction = child.direction; } static int getIndex(String parentId) { if (parentId == null || parentId.length() < 3) { return 0; } String[] parts = parentId.split(":"); if (parts.length != 2) { return 0; } try { return Integer.valueOf(parts[0]).intValue(); } catch (NumberFormatException e) { return 0; } } static String getChangeset(String parentId) { if (parentId == null || parentId.length() < 3) { return null; } String[] parts = parentId.split(":"); if (parts.length != 2) { return null; } try { return parts[1]; } catch (NumberFormatException e) { return null; } } } /** * This class is getting too tangled up with everything else, has a a large amount of fields * (17) and worse is that it is not immutable, which makes the entanglement even more dangerous. * * My plan is to make it immutable by using the builder pattern and remove all setters. * FileStatus fetching may(or may not) be feasable to put elsewhere or fetched "on-demand" by * this class itself. Currently, it has no operations and it purely a data class which isn't * very OO efficent. * * Secondly, remove getDirection by tester methods (isIncoming, isOutgoing, isLocal) * */ public static class Builder { private ChangeSet cs; public Builder(int revision, String changeSet, String branch, String date, String user, HgRoot root) { this.cs = new ChangeSet(revision, changeSet, user, date, branch == null ? "" : branch, root); } public Builder tags(String tags) { this.cs.tagsStr = tags; return this; } public Builder description(String description) { cs.setComment(description); return this; } public Builder parents(String[] parents) { this.cs.setParents(parents); return this; } public Builder direction(Direction direction) { this.cs.direction = direction; return this; } public Builder changedFiles(FileStatus[] changedFiles) { this.cs.changedFiles = changedFiles == null ? EMPTY_STATUS : Collections .unmodifiableList(Arrays.asList(changedFiles)); return this; } public Builder bundleFile(File bundleFile) { this.cs.bundleFile = bundleFile; return this; } public Builder repository(IHgRepositoryLocation repository) { this.cs.repository = repository; return this; } // nodeShort should be first X of changeset, this is superfluous public Builder nodeShort(String nodeShort) { this.cs.nodeShort = nodeShort; return this; } public ChangeSet build() { ChangeSet result = this.cs; this.cs = null; return result; } } ChangeSet(int changesetIndex, String changeSet, String tags, String branch, String user, String date, String description, String[] parents, HgRoot root) { this.changesetIndex = changesetIndex; this.changeset = changeSet; this.revision = new HgRevision(changeset, changesetIndex); this.tagsStr = tags; this.branch = branch; this.user = user; this.date = date; this.hgRoot = root; setComment(description); setParents(parents); // remember index:fullchangesetid setName(getIndexAndName()); } private ChangeSet(int changesetIndex, String changeSet, String user, String date, String branch, HgRoot root) { this(changesetIndex, changeSet, null, branch, user, date, "", null, root); //$NON-NLS-1$ } public int getChangesetIndex() { return changesetIndex; } public String getChangeset() { return changeset; } /** * @return tags array (all tags associated with current changeset). May return empty array, but * never null * @see ChangeSetUtils#getPrintableTagsString(ChangeSet) */ public Tag[] getTags() { if (tags == null) { if (!StringUtils.isEmpty(tagsStr)) { String[] tagsStrArr = tagsStr.split("_,_"); List tagList = new ArrayList(); for (String ctag : tagsStrArr) { if (StringUtils.isEmpty(ctag)) { continue; } Tag tag = new Tag(hgRoot, ctag, this, false); tagList.add(tag); } if (!tagList.isEmpty()) { tags = tagList.toArray(new Tag[tagList.size()]); } } if(tags == null) { tags = EMPTY_TAGS; } } return tags; } /** * @param tags the tags to set */ public void setTags(Tag[] tags) { this.tags = tags; } /** * @param tagsStr the tagsStr to set */ public void setTagsStr(String tagsStr) { this.tagsStr = tagsStr; } /** * @return the tagsStr */ public String getTagsStr() { return tagsStr; } public String getBranch() { return branch; } public String getDateString() { Date d = getRealDate(); if (d != null) { // needed because static date format instances are not thread safe synchronized (DISPLAY_DATE_FORMAT) { return DISPLAY_DATE_FORMAT.format(d); } } return date; } @Override public String getComment() { return comment; } public HgRevision getRevision() { return revision; } @Override public String toString() { return getIndexAndName(); } protected String getIndexAndName() { if (nodeShort != null) { return changesetIndex + ":" + nodeShort; //$NON-NLS-1$ } return changesetIndex + ":" + changeset; //$NON-NLS-1$ } /** * @return the changedFiles, never null. The returned list is non modifiable so any * attempt to modify it will lead to an exception. */ public List getChangedFiles() { return changedFiles == null? EMPTY_STATUS : changedFiles; } /** * @param changedFiles the changedFiles to set */ public void setChangedFiles(List changedFiles) { this.changedFiles = (changedFiles == null ? EMPTY_STATUS : Collections .unmodifiableList(changedFiles)); } public boolean hasFileStatus() { return changedFiles != null; } /** * @param resource * non null * @return true if the given resource was removed in this changeset */ public boolean isRemoved(IResource resource) { return contains(resource, FileStatus.Action.REMOVED); } /** * @param resource * non null * @return true if the given resource was moved in this changeset */ public boolean isMoved(IResource resource) { return contains(resource, FileStatus.Action.MOVED); } /** * @param resource * non null * @return true if the given resource was added in this changeset */ public boolean isAdded(IResource resource) { return contains(resource, FileStatus.Action.ADDED); } /** * @param resource * non null * @return true if the given resource was modified in this changeset */ public boolean isModified(IResource resource) { return contains(resource, FileStatus.Action.MODIFIED); } /** * @param resource * non null * @return file status object if this changeset contains given resource, null otherwise */ public FileStatus getStatus(IResource resource) { if (getChangedFiles().isEmpty()) { return null; } IPath path = ResourceUtils.getPath(resource); if(path.isEmpty()) { return null; } for (FileStatus fileStatus : getChangedFiles()) { if (path.equals(fileStatus.getAbsolutePath())) { return fileStatus; } } return null; } /** * @param resource * non null * @param action * non null * @return true if this changeset contains a resource with given action state */ private boolean contains(IResource resource, Action action) { if (getChangedFiles().isEmpty()) { return false; } boolean match = false; IPath path = null; for (FileStatus fileStatus : getChangedFiles()) { if (fileStatus.getAction() == action) { if (path == null) { path = ResourceUtils.getPath(resource); } if (path.equals(fileStatus.getAbsolutePath())) { match = true; break; } } } return match; } /** * @return the ageDate */ public String getAgeDate() { double delta = (System.currentTimeMillis() - getRealDate().getTime()); delta /= 1000 * 60; // units is minutes if (delta <= 1) { return "less than a minute ago"; } if (delta <= 60) { return makeAgeString(delta, "minute"); } delta /= 60; if (delta <= 24) { return makeAgeString(delta, "hour"); } // 1 day to 31 days delta /= 24; // units is days if (delta <= 31) { return makeAgeString(delta, "day"); } // 4 weeks - 3 months if (delta / 7 <= 12) { return makeAgeString(delta / 7, "week"); } // 3 months - 1 year if (delta / 30 <= 12) { return makeAgeString(delta / 30, "month"); } return makeAgeString(delta / 365, "year"); } private static String makeAgeString(double d, String unit) { int i = (int) Math.max(1, Math.round(d)); return i + " " + unit + ((i == 1) ? "" : "s") + " ago"; } /** * @return the nodeShort */ public String getNodeShort() { return nodeShort; } public int compareTo(ChangeSet o) { if (o.getChangeset().equals(this.getChangeset())) { return 0; } int result = this.getChangesetIndex() - o.getChangesetIndex(); if (result != 0) { return result; } if (getRealDate() != UNKNOWN_DATE && o.getRealDate() != UNKNOWN_DATE) { return getRealDate().compareTo(o.getRealDate()); } return 0; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof ChangeSet) { ChangeSet other = (ChangeSet) obj; if (getChangeset().equals(other.getChangeset()) && getChangesetIndex() == other.getChangesetIndex()) { return true; } } return false; } @Override public int hashCode() { return 31 + ((changeset == null) ? 0 : changeset.hashCode()) + changesetIndex; } /** * @return never returns null. Returns {@link ChangeSet#UNKNOWN_DATE} if the date can't be * parsed */ public Date getRealDate() { try { if (realDate == null) { if (date != null) { // needed because static date format instances are not thread safe synchronized (INPUT_DATE_FORMAT) { realDate = INPUT_DATE_FORMAT.parse(date); } } else { realDate = UNKNOWN_DATE; } } } catch (ParseException e) { realDate = UNKNOWN_DATE; } return realDate; } /** * @return the bundleFile, may be null. The file can contain additional changeset information, * if this is a changeset used by "incoming" or "pull" operation */ public File getBundleFile() { return bundleFile; } public String[] getParents() { return parents; } public HgRevision getParentRevision(int ordinal, boolean bQuery) { if (bQuery && getChangesetIndex() != 0 && (parents == null || parents.length == 0)) { try { parents = HgParentClient.getParentNodeIds(this, "{rev}:{node}"); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } return getParentRevision(ordinal); } public HgRevision getParentRevision(int ordinal) { if (parents != null && 0 <= ordinal && ordinal < parents.length) { return HgRevision.parse(parents[ordinal]); } return null; } public void setParents(String[] parents) { // filter null parents (hg uses -1 to signify a null parent) if (parents != null) { List temp = new ArrayList(parents.length); for (int i = 0; i < parents.length; i++) { String parent = parents[i]; if (parent.charAt(0) != '-') { temp.add(parent); } } this.parents = temp.toArray(new String[temp.size()]); } } /** * @return True if this is a merge changeset. */ public boolean isMerge() { return parents != null && 1 < parents.length && !StringUtils.isEmpty(parents[0]) && !StringUtils.isEmpty(parents[1]); } public void setComment(String comment) { if (comment != null) { this.comment = comment; } else { this.comment = ""; } } public String getSummary() { return StringUtils.removeLineBreaks(getComment()); } /** * @return the repository */ public IHgRepositoryLocation getRepository() { return repository; } /** * @return the direction */ public Direction getDirection() { return direction; } /** * @return the hgRoot file (always as canonical path) * @see File#getCanonicalPath() */ public HgRoot getHgRoot() { return hgRoot; } @Override public boolean contains(IResource local) { return getFiles().contains(local); } public boolean contains(IPath local) { for (IFile resource : getFiles()) { if (local.equals(ResourceUtils.getPath(resource))) { return true; } } return false; } @Override public boolean containsChildren(final IResource local, int depth) { return contains(local); } /** * This method should NOT be used directly by clients of Mercurial plugin except those from * "synchronize" packages. It exists only to fulfill contract with Team "synchronize" API and is * NOT performant, as it may create dynamic proxy objects. {@inheritDoc} */ @Override @DoNotDisplayMe public IFile[] getResources() { return getFiles().toArray(EMPTY_FILES); } @DoNotDisplayMe public FileFromChangeSet[] getChangesetFiles() { List fcs = new ArrayList(); for (FileStatus fileStatus : getChangedFiles()) { int action = 0; int dir = 0; switch (fileStatus.getAction()) { case ADDED: case MOVED: case COPIED: action = Differencer.ADDITION; break; case MODIFIED: action = Differencer.CHANGE; break; case REMOVED: action = Differencer.DELETION; break; } switch (getDirection()) { case INCOMING: dir |= Differencer.LEFT; break; case OUTGOING: dir |= Differencer.RIGHT; break; case LOCAL: dir |= Differencer.RIGHT; break; } fcs.add(new FileFromChangeSet(this, fileStatus, action | dir)); if(fileStatus.getAction() == FileStatus.Action.MOVED){ // for moved files, include an extra FileFromChangeset for the deleted file FileStatus fs = new FileStatus(Action.REMOVED, fileStatus.getRootRelativeCopySourcePath().toString(), this.hgRoot); fcs.add(new FileFromChangeSet(this, fs, dir | Differencer.DELETION)); } } return fcs.toArray(new FileFromChangeSet[0]); } /** * @return not modifiable set of files changed/added/removed in this changeset, never null. The * returned file references might not exist (yet/anymore) on the disk or in the Eclipse * workspace. */ @DoNotDisplayMe public Set getFiles() { if (files != null) { return files; } Set files1 = new LinkedHashSet(); if (changedFiles != null) { for (FileStatus fileStatus : changedFiles) { IFile fileHandle = ResourceUtils.getFileHandle(fileStatus.getAbsolutePath()); if (fileHandle != null) { files1.add(fileHandle); } } } files = Collections.unmodifiableSet(files1); return files; } @Override @DoNotDisplayMe public SyncInfoTree getSyncInfoSet() { return super.getSyncInfoSet(); } @Override public boolean isEmpty() { return getChangedFiles().isEmpty(); } @Override public String getAuthor() { return user; } /** * Roughly corresponds to Mercurial's template filter named "person" except if * an email is provided includes everything left of the '@'. * * See also: http://www.javaforge.com/issue/13809 *

	 * def person(author):
	 * '''get name of author, or else username.'''
	 * if not '@' in author:
	 *     return author
	 * f = author.find('<')
	 * if f == -1:
	 *     return util.shortuser(author)
	 * return author[:f].rstrip()
	 * 
*/ @DoNotDisplayMe public String getPerson() { String sUser = getAuthor(); if (sUser != null) { int a = sUser.indexOf('@'); if (a < 0) { return sUser; } int b = sUser.indexOf('<'); if (b >= 0) { return sUser.substring(0, b).trim(); } return sUser.substring(0, a).trim(); } return null; } @Override public Date getDate() { return getRealDate(); } /** * Returns index:fullchangesetid pair */ @Override public String getName() { return super.getName(); } /** * @return Whether the repository is currently on this revision */ public boolean isCurrentOutgoing() { return direction == Direction.OUTGOING && isCurrent(); } /** * @return Whether the repository is currently on this revision */ public boolean isCurrent() { if (hgRoot != null) { try { return equals(LocalChangesetCache.getInstance().getChangesetForRoot(hgRoot)); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } return false; } @Override public void remove(IResource resource) { // not supported } @Override public void rootRemoved(IResource resource, int depth) { // not supported } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/FileFromChangeSet.java000066400000000000000000000113671173713500500336300ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.properties.DoNotDisplayMe; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetResourceMapping; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Andrei */ public class FileFromChangeSet implements IAdaptable{ /** * May be null. Eg a resource is removed */ private final IFile file; /** May be null. Only not null when a file has been copied or moved. */ private final IFile copySrcFile; /** * Not null */ private final ChangeSet changeset; private final int kind; private FileStatus fileStatus; /** * @param changeset non null * @param fileStatus non null * @param diffKind see {@link Differencer} */ public FileFromChangeSet(ChangeSet changeset, FileStatus fileStatus, int diffKind) { this(changeset, ResourceUtils.getFileHandle(fileStatus.getAbsolutePath()), ResourceUtils.getFileHandle(fileStatus.getAbsoluteCopySourcePath()), diffKind); this.fileStatus = fileStatus; } /** * @param changeset non null * @param file may be null * @param diffKind */ public FileFromChangeSet(ChangeSet changeset, IFile file, IFile copySourceFile, int diffKind) { this.changeset = changeset; this.file = file; this.copySrcFile = copySourceFile; this.kind = diffKind; } public Object getAdapter(Class adapter) { // Resource adapter is enabled for "working" changeset only to avoid "dirty" // decorations shown in the tree on changeset files from already commited changesets if((changeset instanceof WorkingChangeSet) && adapter == IResource.class){ return file; } if (adapter == IFile.class /* || adapter == IResource.class*/) { return file; } if(adapter == ResourceMapping.class){ return new HgChangeSetResourceMapping(this); } return null; } /** * @return see {@link Differencer} */ @DoNotDisplayMe public int getDiffKind() { return kind; } /** * @return Path relative to the hg root or the containing project, whichever has the greater * number of segments. May return null. */ public IPath getPath() { if (fileStatus != null) { return fileStatus.getRootRelativePath(); } else if (file != null) { HgRoot root = changeset.getHgRoot(); if (root == null) { root = MercurialTeamProvider.getHgRoot(file); } IPath path1, path2 = file.getProjectRelativePath(); if (root != null && (path1 = root.toRelative(file)) != null) { if (path2 == null) { return path1; } return path1.segmentCount() > path2.segmentCount() ? path1 : path2; } return path2; } return null; } @Override public String toString() { return file != null? file.toString() : fileStatus.getAbsolutePath().toOSString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((changeset == null) ? 0 : changeset.hashCode()); result = prime * result + ((file == null) ? 0 : file.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof FileFromChangeSet)) { return false; } FileFromChangeSet other = (FileFromChangeSet) obj; if (changeset == null) { if (other.changeset != null) { return false; } } else if (!changeset.equals(other.changeset)) { return false; } if (file == null) { if (other.file != null) { return false; } } else if (!file.equals(other.file)) { return false; } return true; } public IFile getFile() { return file; } /** * Getter for the original source file handle of copied or moved files (if any) * @return source file handle (must not exist) if the file was copied or moved, null otherwise */ public IFile getCopySourceFile(){ return copySrcFile; } public boolean isCopy(){ return copySrcFile != null; } @DoNotDisplayMe public ChangeSet getChangeset() { return changeset; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/FileStatus.java000066400000000000000000000074461173713500500324310ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; public class FileStatus { public static enum Action { /** 'M' */ MODIFIED(), /** 'A' */ ADDED(), /** 'R' */ REMOVED(), /** Not a canonical file status */ COPIED(), /** Not a canonical file status either */ MOVED(); } private final Action action; private final IPath path; private final IPath copySourcePath; //< when action is COPIED or MOVED, indicates which file it was copied from private final HgRoot hgRoot; private IPath absPath; private IPath absCopySourcePath; public FileStatus(Action action, String path, HgRoot hgRoot) { if(action == Action.COPIED || action == Action.MOVED){ throw new IllegalArgumentException("copy source path must be provided for actions COPIED or MOVED"); } this.action = action; this.hgRoot = hgRoot; this.path = new Path(path); this.copySourcePath = null; } public FileStatus(Action action, String path, String copySrcPath, HgRoot hgRoot) { if(action != Action.COPIED && action != Action.MOVED){ throw new IllegalArgumentException("copy source path can only be provided for actions COPIED and MOVED"); } this.action = action; this.hgRoot = hgRoot; this.path = new Path(path); this.copySourcePath = new Path(copySrcPath); } public Action getAction() { return action; } public boolean isCopied(){ return action == Action.COPIED || action == Action.MOVED; } public IPath getRootRelativePath() { return path; } public IPath getRootRelativeCopySourcePath() { return copySourcePath; } public IPath getAbsolutePath(){ if(absPath == null && getRootRelativePath() != null){ absPath = hgRoot.toAbsolute(getRootRelativePath()); } return absPath; } public IPath getAbsoluteCopySourcePath(){ if(absCopySourcePath == null && getRootRelativeCopySourcePath() != null){ absCopySourcePath = hgRoot.toAbsolute(getRootRelativeCopySourcePath()); } return absCopySourcePath; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("FileStatus ["); if (action != null) { builder.append("action="); builder.append(action.name()); builder.append(", "); } if (path != null) { builder.append("path="); builder.append(path); } builder.append("]"); return builder.toString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((action == null) ? 0 : action.hashCode()); result = prime * result + ((hgRoot == null) ? 0 : hgRoot.hashCode()); result = prime * result + ((path == null) ? 0 : path.toPortableString().hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof FileStatus)) { return false; } FileStatus other = (FileStatus) obj; if (action != other.action) { return false; } if (hgRoot == null) { if (other.hgRoot != null) { return false; } } else if (!hgRoot.equals(other.hgRoot)) { return false; } if (path == null) { if (other.path != null) { return false; } } else if (!path.toPortableString().equals(other.path.toPortableString())) { return false; } return true; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/FlaggedAdaptable.java000066400000000000000000000025051173713500500334640ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import org.eclipse.core.runtime.IAdaptable; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; public class FlaggedAdaptable implements IAdaptable { private final IAdaptable adaptable; private final char flag; public FlaggedAdaptable(IAdaptable adaptable, char flag) { this.adaptable = adaptable; this.flag = flag; } @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { if(adaptable == null){ return null; } return adaptable.getAdapter(adapter); } public char getFlag() { return this.flag; } public String getStatus() { return flag == MercurialStatusCache.CHAR_UNRESOLVED ? Messages.getString("FlaggedAdaptable.unresolvedStatus") : Messages.getString("FlaggedAdaptable.resolvedStatus"); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/GChangeSet.java000066400000000000000000000200471173713500500323060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import com.vectrace.MercurialEclipse.model.GChangeSet.Edge.EdgeType; /** * Don't look at this code - your eyes will bleed. * * Seriously. Turn back now. */ public class GChangeSet { private final EdgeList middle; private final EdgeList after; private final int index; private final RowCount rowCount; private final int rev; public GChangeSet(RowCount rowCount, int index, String middleS, String afterS) { this.rowCount = rowCount; this.index = index; middle = new EdgeList(true); after = new EdgeList(false); middle.parse(middleS); after.parse(afterS); if (middleS != null && middleS.length() > 0) { rev = Integer.parseInt(middleS.substring(middleS.indexOf('*') + 1)); } else { rev = 0; } } public int getRev() { return rev; } public GChangeSet clean(GChangeSet last) { middle.clean(last); return this; } public int getIndex() { return index; } public EdgeList getBefore() { return getMiddle(); } public EdgeList getMiddle() { return middle; } public EdgeList getAfter() { return after; } public class EdgeList { private final List edges = new ArrayList(); private final Set above = new HashSet(); private final boolean straight; private int[] jumps; public EdgeList(boolean straight) { this.straight = straight; } public void parse(String string) { int length = string.length(); int count = 0; for (int i = 0; i < length; i++) { if (string.charAt(i) != '*') { count += addEdge(string, i, count); } else { break; } } rowCount.endRow(); if (string.indexOf('+') >= 0) { rowCount.jump = string.indexOf('o'); jumps = new int[] { string.indexOf('+') / 2, rowCount.jump / 2, }; } } private int addEdge(String string, int i, int count) { char c = string.charAt(i); if (c == ' ') { return rowCount.space(i, count); } Edge edge = new Edge(c, count); return rowCount.update(this, edge); } public int[] getJump() { return jumps; } public void add(Edge edge) { if (straight) { edge.straighten(); } above.add(Integer.valueOf(edge.bottom)); edges.add(edge); } public List getEdges() { return edges; } public void clean(GChangeSet last) { for (Edge e : edges) { e.setFinish(e.isDot() && (last == null || !last.after.above.contains(Integer.valueOf(e.top)))); } } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("EdgeList ["); if (above != null) { builder.append("above="); builder.append(above); builder.append(", "); } if (edges != null) { builder.append("edges="); builder.append(edges); builder.append(", "); } if (jumps != null) { builder.append("jumps="); builder.append(Arrays.toString(jumps)); builder.append(", "); } builder.append("straight="); builder.append(straight); builder.append("]"); return builder.toString(); } } public static class RowCount { public int jump; public List cols = new ArrayList(); private int unique; private Edge lastEdge; private int dec = -1; public RowCount() { cols.add(Integer.valueOf(0)); } public int space(int i, int count) { lastEdge = null; if (jump == i) { dec = count; return 1; } return 0; } public int update(EdgeList edges, Edge edge) { Integer col; boolean lastLine = lastEdge != null && lastEdge.type == EdgeType.line; int count = 1; if (edge.type == EdgeType.backslash && lastLine) { unique++; cols.add(edge.col, col = Integer.valueOf(unique)); } else if (edge.type == EdgeType.slash && lastLine) { dec = edge.col; col = cols.get(edge.col); } else if (edge.type == EdgeType.line && lastEdge != null && lastEdge.type == EdgeType.backslash) { count = 0; edge.dec(); cols.remove(edge.col); col = cols.get(edge.col); } else if (edge.type == EdgeType.line && lastEdge != null && lastEdge.type == EdgeType.slash) { count = 0; edge.dec(); col = cols.get(edge.col); dec = -1; } else if (edge.type == EdgeType.dash && (lastEdge == null || lastEdge.type != EdgeType.dash)) { lastEdge = edge; return 0; } else if (edge.col >= cols.size()) { unique++; cols.add(col = Integer.valueOf(unique)); } else { col = cols.get(edge.col); } edge.lane = col.intValue(); if (edge.type == EdgeType.dash) { lastEdge = null; } else { lastEdge = edge; } edges.add(edge); return count; } public void endRow() { lastEdge = null; if (dec > -1) { cols.remove(dec); dec = -1; } jump = -1; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("RowCount ["); if (cols != null) { builder.append("cols="); builder.append(cols); builder.append(", "); } builder.append("dec="); builder.append(dec); builder.append(", jump="); builder.append(jump); builder.append(", "); if (lastEdge != null) { builder.append("lastEdge="); builder.append(lastEdge); builder.append(", "); } builder.append("unique="); builder.append(unique); builder.append("]"); return builder.toString(); } } public static class Edge { public static enum EdgeType { line, dot, working, plus, dash, slash, backslash } private int top; private int bottom; private int col; private int lane; private boolean finish; private EdgeType type; public Edge(char c, int i) { col = top = bottom = i; type = EdgeType.line; switch (c) { case '/': type = EdgeType.slash; bottom--; break; case '\\': type = EdgeType.backslash; top--; break; case 'o': type = EdgeType.dot; break; case '@': type = EdgeType.working; break; case '+': type = EdgeType.plus; break; case '-': type = EdgeType.dash; break; } } public void setFinish(boolean finish) { this.finish = finish; } public boolean isFinish() { return finish; } public void straighten() { top = bottom = Math.max(top, bottom); } public void dec() { top = bottom = col = col - 1; } public int getTop() { return top; } public int getBottom() { return bottom; } public int getLane() { return lane; } public boolean isDot() { return type == EdgeType.dot || type == EdgeType.working || type == EdgeType.plus; } public boolean isPlus() { return type == EdgeType.plus; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Edge [bottom="); builder.append(bottom); builder.append(", col="); builder.append(col); builder.append(", finish="); builder.append(finish); builder.append(", lane="); builder.append(lane); builder.append(", top="); builder.append(top); builder.append(", "); if (type != null) { builder.append("type="); builder.append(type); } builder.append("]"); return builder.toString(); } } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("GChangeSet [rev="); builder.append(rev); builder.append(", index="); builder.append(index); builder.append(", "); if (rowCount != null) { builder.append("rowCount="); builder.append(rowCount); } builder.append("]"); return builder.toString(); } } GroupedUncommittedChangeSet.java000066400000000000000000000036001173713500500356530ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation * John Peberdy - refactoring *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import org.eclipse.core.resources.IFile; import com.vectrace.MercurialEclipse.synchronize.cs.UncommittedChangesetGroup; /** * @author Andrei */ public class GroupedUncommittedChangeSet extends WorkingChangeSet { private boolean isDefault; private final UncommittedChangesetGroup group; public GroupedUncommittedChangeSet(String name, UncommittedChangesetGroup group) { super(name); this.group = group; group.add(this); } public void removeFile(IFile file) { // TODO check group files // boolean contains = group.contains(file); // boolean added = contains; synchronized (files){ files.remove(file); } } public void setDefault(boolean isDefault) { this.isDefault = isDefault; } /** * @return true if all changes should go to this changeset first (if there are more then one * uncommitted changeset available) */ public boolean isDefault() { return isDefault; } public boolean add(IFile file){ boolean contains = group.contains(file); boolean added = contains; if(!contains) { added = group.add(file, this); } if(added) { synchronized (files){ added = files.add(file); } } return added; } /** * @return the group, never null */ public UncommittedChangesetGroup getGroup() { return group; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/HgFile.java000066400000000000000000000077351173713500500315050ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ge.zhong implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgCatClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; /** * @author Ge Zhong * */ public class HgFile extends HgResource implements IHgFile { protected static final ByteArrayInputStream EMPTY_STREAM = new ByteArrayInputStream(new byte[0]); /** * @param hgRoot * @param changeset global changeset id * @param path relative path to HgRoot */ public HgFile(HgRoot hgRoot, String changeset, IPath path) { super(hgRoot, changeset, path); } public HgFile(HgRoot hgRoot, ChangeSet changeset, IPath path) { super(hgRoot, changeset, path); } public HgFile(HgRoot hgRoot, IFile file) { super(hgRoot, file); } /** * @see org.eclipse.core.resources.IEncodedStorage#getCharset() */ public String getCharset() throws CoreException { return this.getHgRoot().getEncoding(); } /** * @see org.eclipse.core.resources.IStorage#getContents() */ @Override public InputStream getContents() throws CoreException { return new ByteArrayInputStream(super.getContent()); } /** * @see org.eclipse.core.resources.IStorage#getFullPath() */ public IPath getFullPath() { IPath p = this.getHgRoot().getIPath().append(path); if (resource == null) { p = p.append(" [" + changeset.getChangesetIndex() + "]"); } return p; } /** * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ @Override public Object getAdapter(Class adapter) { // TODO Auto-generated method stub return null; } /** * @see org.eclipse.compare.BufferedContent#createStream() */ @Override protected InputStream createStream() throws CoreException { if (resource != null) { if (resource instanceof IStorage) { InputStream is= null; IStorage storage= (IStorage) resource; try { is= storage.getContents(); } catch (CoreException e) { if (e.getStatus().getCode() == IResourceStatus.OUT_OF_SYNC_LOCAL) { resource.refreshLocal(IResource.DEPTH_INFINITE, null); is= storage.getContents(); } else { // if the file is deleted or inaccessible // log the error and return empty stream MercurialEclipsePlugin.logError(e); } } if (is != null) { return is; } } return EMPTY_STREAM; } byte[] result = null; // Setup and run command if (changeset.getDirection() == Direction.INCOMING && changeset.getBundleFile() != null) { // incoming: overlay repository with bundle and extract then via cat try { result = HgCatClient.getContentFromBundle(this, changeset.getRevision().getChangeset(), changeset.getBundleFile()); } catch (IOException e) { throw new HgException("Unable to determine canonical path for " + changeset.getBundleFile(), e); } } else { try { result = HgCatClient.getContent(this); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } if(result != null){ return new ByteArrayInputStream(result); } return EMPTY_STREAM; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/HgFolder.java000066400000000000000000000112401173713500500320230ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ge.zhong implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SortedSet; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Ge Zhong * */ public class HgFolder extends HgResource implements IHgFolder { private final ArrayList members = new ArrayList(); private static final String separator = System.getProperty("file.separator"); /** * Create a new HgFolder and recursively instantiate sub-files and folders * * @param root The root to use * @param changeset The changeset id * @param path relative path from root * @param listing List of files in the folder * @param filter white list of files that can be included */ public HgFolder(HgRoot root, String changeset, IPath path, String[] listing, SortedSet filter) { super(root, changeset, path); parseListing(listing, filter); } public HgFolder(HgRoot root, ChangeSet changeset, IPath path, String[] listing, SortedSet filter) { super(root, changeset, path); parseListing(listing, filter); } public HgFolder(HgRoot root, IContainer container) { super(root, container); try { IResource wMembers[]= container.members(); for (IResource res : wMembers) { if (res instanceof IContainer) { members.add(new HgFolder(root, (IContainer)res)); } else if (res instanceof IFile) { members.add(new HgFile(root, (IFile)res)); } } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } public HgFolder(HgRoot root, IContainer container, SortedSet filter) { super(root, container); try { IResource wMembers[]= container.members(); for (IResource res : wMembers) { if (res instanceof IContainer) { HgFolder hgFolder = new HgFolder(root, (IContainer)res, filter); if (hgFolder.members().length != 0) { members.add(hgFolder); } } else if (res instanceof IFile) { IPath relPath = ResourceUtils.getPath(res).makeRelativeTo(root.getIPath()); if (filter == null || filter.contains(relPath.toOSString())) { members.add(new HgFile(root, (IFile)res)); } } } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } /** * Parse the list of files and then apply the filer */ private void parseListing(String[] listing, SortedSet filter) { Map> sublisting = new HashMap>(); String dir = path.addTrailingSeparator().toOSString(); for(String line : listing) { String result = dir.length() > 1 ? line.substring(dir.length()) : line; int index = result.indexOf(separator); if (index == -1) { IPath filePath = path.append(result); if (filter == null || filter.contains(filePath.toOSString())) { IHgResource file = new HgFile(root, changeset, filePath); this.members.add(file); } } else { String folderName = result.substring(0, index); ArrayList subfolder = sublisting.get(folderName); if (subfolder == null ) { subfolder = new ArrayList(); subfolder.add(line); sublisting.put(folderName, subfolder); } else { subfolder.add(line); } } } if (sublisting.size() != 0) { Set folderNames = sublisting.keySet(); Iterator it = folderNames.iterator(); while(it.hasNext()){ String folderName = it.next(); ArrayList folder = sublisting.get(folderName); HgFolder hgFolder = new HgFolder(root, changeset, path.append(folderName), folder.toArray(new String[folder.size()]), filter); if(hgFolder.members().length != 0) { this.members.add(hgFolder); } } } } /** * @see com.vectrace.MercurialEclipse.model.IHgFolder#members() */ public IHgResource[] members() { return members.toArray(new IHgResource[members.size()]); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/HgPath.java000066400000000000000000000136121173713500500315110ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.model.IWorkbenchAdapter; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * A virtual (but always canonical) path object which can be used to show plain files and * directories together with those known by Eclipse workspace. * * @author Andrei */ public class HgPath extends File implements IWorkbenchAdapter, IAdaptable { private final Path path; public HgPath(String pathname) throws IOException { this(new File(pathname)); } public HgPath(File file) throws IOException { super(file.getCanonicalPath()); path = new Path(getAbsolutePath()); } public Object[] getChildren(Object o) { if (isFile()) { return new Object[0]; } File[] files = listFiles(); if (files == null) { return new Object[0]; } List children = new ArrayList(); for (File file : files) { IResource workspaceHandle; try { workspaceHandle = ResourceUtils.convert(file); if (workspaceHandle != null && workspaceHandle.exists()) { children.add(workspaceHandle); } else { if (isHgRoot(file)) { children.add(new HgRoot(file)); } else { if (!".hg".equals(file.getName())) { children.add(new HgPath(file)); } } } } catch (Exception e) { MercurialEclipsePlugin.logError(e); continue; } } return children.toArray(); } public ImageDescriptor getImageDescriptor(Object object) { if (isFile()) { return PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( ISharedImages.IMG_OBJ_FILE); } return PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( ISharedImages.IMG_OBJ_FOLDER); } public String getLabel(Object o) { return getAbsolutePath(); } public Object getParent(Object o) { try { File parentFile = getParentFile(); if(parentFile != null) { return new HgPath(parentFile); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } return null; } public Object getAdapter(Class adapter) { if (adapter == IWorkbenchAdapter.class) { return this; } if (adapter == IResource.class || adapter == IFile.class || adapter == IProject.class) { try { IResource resource = ResourceUtils.convert(this); if (adapter == IFile.class && !(resource instanceof IFile)) { // do NOT return folder objects for iFile! return null; } return resource; } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } return null; } /** * @return the {@link IPath} object corresponding to this root, never null */ public IPath getIPath() { return path; } public IPath toAbsolute(IPath relative) { return path.append(relative); } public IPath toAbsolute(String relative) { return path.append(relative); } /** * Converts given path to the relative * * @param child * a possible child path, non null * @return a hg root relative path of a given file, if the given file is located under this * root, otherwise the path of a given file. If the given path matches the root, * returns an empty string */ public String toRelative(File child) { return ResourceUtils.toRelative(this, child); } /** * Converts given path to the relative * * @param child * a possible child path, non null * @return a hg root relative path of a given file, if the given file is located under this * root, otherwise the path of a given file. If the given path matches the root, * returns an empty string */ public IPath toRelative(IPath child) { return child.makeRelativeTo(getIPath()); } /** * Converts given file to the relative path (if the file exists) * * @param child * a possible child path, non null * @return a hg root relative path of a given file, if the given file is located under this * root, otherwise the path of a given file. If the given path matches the root, returns * an empty path. If the file location can not be computed, returns null. * @see IResource#getLocation() * @see ResourceUtils#getPath(IResource) */ public IPath toRelative(IFile file) { IPath location = ResourceUtils.getPath(file); if(location.isEmpty()) { return null; } return new Path(toRelative(location.toFile())); } public static boolean isHgRoot(File path) { if (path == null || !path.isDirectory()) { return false; } FileFilter hg = new FileFilter() { public boolean accept(File path1) { return path1.getName().equalsIgnoreCase(".hg") && path1.isDirectory(); //$NON-NLS-1$ } }; File[] rootContent = path.listFiles(hg); return rootContent != null && rootContent.length == 1; } @Override public boolean equals(Object obj) { return super.equals(obj); } @Override public int hashCode() { return super.hashCode(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/HgResource.java000066400000000000000000000103431173713500500324020ustar00rootroot00000000000000package com.vectrace.MercurialEclipse.model; import java.io.InputStream; import org.eclipse.compare.BufferedContent; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ge.zhong implementation *******************************************************************************/ /** * @author Ge Zhong * */ public abstract class HgResource extends BufferedContent implements IHgResource { /** * Not null */ protected HgRoot root; /** * Not null */ protected IPath path; /** * If not null representing a local file in Hg working copy */ protected IResource resource; /** * If a local resource then then null */ protected ChangeSet changeset; /** * @param root the HgRoot, not null * @param changeset is null if and only if resource != null, or this is a NullHgFile * @param path relative path to HgRoot, not null */ public HgResource(HgRoot root, String changeset, IPath path) { try { if(changeset != null && changeset.length() != 0) { LocalChangesetCache cache = LocalChangesetCache.getInstance(); this.changeset = cache.getOrFetchChangeSetById(root, changeset); if (this.changeset == null) { // refetch cache and try again cache.fetchRevisions(root, false, 0, 0, false); this.changeset = cache.getOrFetchChangeSetById(root, changeset); } } this.root = root; this.path = path.removeTrailingSeparator(); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } /** * @param root the HgRoot, not null * @param changeset =null if and only if wResource != null or this is a NullHgFile * @param path relative path to HgRoot, not null */ public HgResource(HgRoot root, ChangeSet changeset, IPath path) { if(changeset != null){ this.changeset = changeset; this.root = root; this.path = path.removeTrailingSeparator(); } } /** * Wraps a local resource as HgResource * @param root the HgRoot, not null * @param resource a local resource */ public HgResource(HgRoot root, IResource resource) { this.root = root; this.resource = resource; path = root.toRelative(ResourceUtils.getPath(resource)); } /** * @see com.vectrace.MercurialEclipse.model.IHgResource#getHgRoot() */ public HgRoot getHgRoot() { return root; } public String getHgRootRelativePath() { return path.toOSString(); } public String getName() { String name = path.lastSegment(); if(name == null) { return root.getIPath().lastSegment(); } return name; } public String getFileExtension() { return path.getFileExtension(); } public ChangeSet getChangeSet() { return changeset; } public IPath getIPath() { return path; } public Object getAdapter(Class adapter) { return null; } public boolean isReadOnly() { if (resource != null) { ResourceAttributes attributes = resource.getResourceAttributes(); if (attributes != null) { return attributes.isReadOnly(); } } return true; } @Override public boolean equals(Object other) { if (other instanceof IHgResource) { IHgResource res = (IHgResource)other; return root.equals(res.getHgRoot()) && path.equals(res.getIPath()); } return false; } /** * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (root.hashCode() << 16) & path.hashCode(); } public IResource getResource() { return resource; } /** * @see org.eclipse.compare.BufferedContent#createStream() */ @Override protected InputStream createStream() throws CoreException { return null; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/HgRoot.java000066400000000000000000000167741173713500500315540ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.resource.ImageDescriptor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.utils.IniFile; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * Hg root represents the root of hg repository as canonical path * (see {@link File#getCanonicalPath()}) * * @author bastian */ public class HgRoot extends HgPath implements IHgRepositoryLocation { private static final String PATHS_SECTION = "paths"; private static final String HG_HGRC = ".hg/hgrc"; private static final long serialVersionUID = 3L; /** Place holder for a (not valid) hg root object */ public static final HgRoot NO_ROOT; static { HgRoot root = null; try { root = new HgRoot(""); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } finally { NO_ROOT = root; } } /** * Preferred encoding */ private String encoding; /** * Cached encoding fall back encoding as specified in the config file */ private transient Charset fallbackencoding; /** * Cached config file (.hg/hgrc) */ private transient File config; /** * Cached user name or empty string if not specified in the config file */ private transient String user; private final IProject projectAdapter; public HgRoot(String pathname) throws IOException { this(new File(pathname)); } public HgRoot(File file) throws IOException { super(file); Object adapter = super.getAdapter(IProject.class); if(adapter instanceof IProject) { projectAdapter = (IProject) adapter; } else { projectAdapter = new HgRootContainer(this); } } public void setEncoding(String charset) { this.encoding = charset; } /** * @return never null, root specific encoding (may differ from the OS default encoding) */ public String getEncoding() { if(encoding == null){ setEncoding(MercurialEclipsePlugin.getDefaultEncoding()); } return encoding; } /** * Gets the resource hgrc as a {@link java.io.File}. * * @return the {@link java.io.File} referencing the hgrc file, null if it doesn't exist. */ protected File getConfig() { if (config == null) { File hgrc = new File(this, HG_HGRC); if (hgrc.isFile()) { config = hgrc; return hgrc; } } return config; } protected String getConfigItem(String section, String key) { getConfig(); if (config != null) { try { IniFile iniFile = new IniFile(config.getAbsolutePath()); return iniFile.getKeyValue(section, key); } catch (FileNotFoundException e) { } } return null; } /** * Get the entries from the paths section of the config file if available * @return A map from logical names to paths * @throws FileNotFoundException If the config file doesn't exist */ public Map getPaths() throws FileNotFoundException { File hgrc = getConfig(); Map paths = new HashMap(); if (hgrc == null) { return paths; } IniFile ini = new IniFile(hgrc.getAbsolutePath()); Map section = ini.getSection(PATHS_SECTION); if (section != null) { for (Entry entry : section.entrySet()) { String logicalName = entry.getKey(); String path = entry.getValue(); if(!StringUtils.isEmpty(logicalName) && !StringUtils.isEmpty(path)) { paths.put(logicalName, path); } } } return paths; } /** * @return The fallback encoding as specified in the config file, otherwise windows-1251 */ public Charset getFallbackencoding() { if(fallbackencoding == null){ // set fallbackencoding to windows standard codepage String fallback = getConfigItem("ui", "fallbackencoding"); if (fallback == null || fallback.length() == 0) { fallback = "windows-1251"; } fallbackencoding = Charset.forName(fallback); } return fallbackencoding; } @Override public boolean equals(Object obj) { return super.equals(obj); } @Override public int hashCode() { return super.hashCode(); } public int compareTo(IHgRepositoryLocation loc) { if(getLocation() == null) { return -1; } if(loc.getLocation() == null){ return 1; } return getLocation().compareToIgnoreCase(loc.getLocation()); } public String getLocation() { return getAbsolutePath(); } public URI getUri() throws HgException { return toURI(); } public String getLogicalName() { return null; } public String getPassword() { return null; } public String getUser() { if(user == null){ String configItem = getConfigItem("ui", "username"); if(StringUtils.isEmpty(configItem)){ // set to empty string to avoid multiple reads from file user = ""; } else { user = configItem.trim(); } } return StringUtils.isEmpty(user)? null : user; } @Override public Object[] getChildren(Object o) { IProject[] projects = MercurialTeamProvider.getKnownHgProjects(this).toArray( new IProject[0]); if (projects.length == 1) { if (getIPath().equals(ResourceUtils.getPath(projects[0]))) { return projects; } } try { return getResource().members(); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return new Object[0]; } } @Override public ImageDescriptor getImageDescriptor(Object object) { return MercurialEclipsePlugin.getImageDescriptor("root.gif"); } @Override public Object getAdapter(Class adapter) { if(adapter == IHgRepositoryLocation.class){ return this; } Object object = super.getAdapter(adapter); if (object == null && (adapter == IProject.class || adapter == IResource.class)) { return getResource(); } return object; } public boolean isLocal() { return true; } public IProject getResource() { if(projectAdapter instanceof HgRootContainer) { HgRootContainer container = (HgRootContainer) projectAdapter; container.init(); } else { // Ideally we'd open the project. See: http://www.javaforge.com/issue/19998 // TODO: find a way to do this caching more explicitly. a get method shouldn't have side effects. // projectAdapter.open(IResource.BACKGROUND_REFRESH, null); if(projectAdapter.isOpen()) { if(!MercurialRootCache.isHgTeamProviderFor(projectAdapter)) { try { MercurialRootCache.markAsCached(projectAdapter, this); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } } return projectAdapter; } public HgRoot toHgRoot() { return this; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/HgRootContainer.java000066400000000000000000000050151173713500500334010ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.resources.HgProjectAdapter; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; /** * @author Andrei */ public final class HgRootContainer extends HgProjectAdapter { private boolean initDone; public HgRootContainer(HgRoot hgRoot) { super(hgRoot); init(); } public void init() { // TODO implement REAL project/folders for each hg root // things to think about (inspired by ExternalFoldersManager in JDT): // - refresh on startup or first access // - cleanup on shutdown (to avoid endless growth of non existent roots) // - traversal of REAL tree instead of faked one in members() call if(true) { return; } if(initDone || !getHgRoot().exists()) { return; } final IProject project = getWorkspace().getRoot().getProject(".hg_repo_roots"); try { if(!project.exists()) { IProjectDescription description = getWorkspace().newProjectDescription(project.getName()); IPath location = MercurialEclipsePlugin.getDefault().getStateLocation().append(project.getName()); description.setLocation(location); project.create(description, IResource.HIDDEN, null); } if(!project.isOpen()) { project.open(IResource.BACKGROUND_REFRESH, null); } IFolder folder = project.getFolder(getName()); if (!folder.exists()) { folder.createLink(getLocation(), IResource.ALLOW_MISSING_LOCAL, null); } else { folder.refreshLocal(DEPTH_INFINITE, null); } MercurialRootCache.markAsCached(folder, getHgRoot()); MercurialRootCache.markAsCached(project, getHgRoot()); initDone = true; } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/IHgFile.java000066400000000000000000000013151173713500500316020ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ge.zhong implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import org.eclipse.core.resources.IEncodedStorage; /** * @author Ge Zhong * */ public interface IHgFile extends IHgResource, IEncodedStorage { } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/IHgFolder.java000066400000000000000000000012531173713500500321370ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ge.zhong implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; /** * @author Ge Zhong * */ public interface IHgFolder extends IHgResource { public IHgResource[] members(); } IHgRepositoryLocation.java000066400000000000000000000034731173713500500345230ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.io.File; import java.net.URI; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.ui.model.IWorkbenchAdapter; import com.vectrace.MercurialEclipse.exception.HgException; /** * Interface for hg repository, which might be either local (file) or remote (url) * @author Andrei */ public interface IHgRepositoryLocation extends IWorkbenchAdapter, IAdaptable { int compareTo(IHgRepositoryLocation loc); int compareTo(File loc); /** * @return might return null */ String getUser(); /** * @return might return null */ String getPassword(); /** * Return unsafe (with password) URI for repository location if possible * @return a valid URI of the repository or null if repository is local directory * @throws HgException unable to parse to URI or location is invalid. */ URI getUri() throws HgException; /** * @return might return null */ String getLocation(); /** * @return might return null */ String getLogicalName(); /** * @return true if the repository is on a local file system */ boolean isLocal(); /** * * @return null if the repository is NOT local, otherwise the corresponding hg root on the file * system (representing same absolute (but resolved, canonical) file path) */ HgRoot toHgRoot(); }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/IHgResource.java000066400000000000000000000017701173713500500325170ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; /** * @author andrei */ public interface IHgResource extends IAdaptable { /** * @return the hgRoot, never null */ HgRoot getHgRoot(); String getHgRootRelativePath(); String getName(); String getFileExtension(); ChangeSet getChangeSet(); IPath getIPath(); boolean isReadOnly(); IResource getResource(); }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/Messages.java000066400000000000000000000021231173713500500321000ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.model.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/NullHgFile.java000066400000000000000000000022011173713500500323170ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ge.zhong implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.io.InputStream; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; /** * @author Ge Zhong * */ public class NullHgFile extends HgFile { public NullHgFile(HgRoot hgRoot, ChangeSet changeset, IPath path) { super(hgRoot, changeset, path); } public NullHgFile(HgRoot hgRoot, String revision, IPath path) { super(hgRoot, revision, path); } @Override public InputStream getContents() throws CoreException { return EMPTY_STREAM; } @Override public String getName() { return super.getName() + ": DOES NOT EXIST"; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/Patch.java000066400000000000000000000054611173713500500314000ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; /** * @author bastian * */ public class Patch { private int index; private String name; private String summary; private boolean applied; /** * @param name * @param date * @param author * @param applied */ public Patch(String name, boolean applied, String summary, int index) { this.name = name; this.applied = applied; this.summary = summary; this.index = index; } public Patch() { } /** * @return the name */ public String getName() { return name; } /** * @param name * the name to set */ public void setName(String name) { this.name = name; } /** * @return the applied */ public boolean isApplied() { return applied; } /** * @param applied * the applied to set */ public void setApplied(boolean applied) { this.applied = applied; } /** * @return the summary */ public String getSummary() { return summary; } /** * @param summary * the summary to set */ public void setSummary(String summary) { this.summary = summary; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((summary == null) ? 0 : summary.hashCode()); return result; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Patch)) { return false; } final Patch other = (Patch) obj; if (name == null) { if (other.name != null) { return false; } } else if (!name.equals(other.name)) { return false; } if (summary == null) { if (other.summary != null) { return false; } } else if (!summary.equals(other.summary)) { return false; } return true; } /** * @return the index */ public int getIndex() { return index; } /** * @param index * the index to set */ public void setIndex(int index) { this.index = index; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return this.name; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/PathFromChangeSet.java000066400000000000000000000036171173713500500336440ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IAdaptable; public abstract class PathFromChangeSet implements IAdaptable { private final Object parent; private final String label; protected IResource resource; protected PathFromChangeSet(Object prnt, String leadingSegment) { parent = prnt; label = leadingSegment; } @Override public String toString() { if(isProjectClosed()) { return label + " (closed!)"; } return label; } public boolean isProjectClosed() { return resource!= null && !resource.getProject().isOpen(); } @Override public boolean equals(Object other) { if (other instanceof PathFromChangeSet) { PathFromChangeSet o = (PathFromChangeSet) other; if (o.label.equals(label) && o.parent.equals(parent)) { if (o.resource == null) { return resource == null; } return o.resource.equals(resource); } } return false; } @Override public int hashCode() { return 73 ^ label.hashCode() + parent.hashCode(); } public final Object getAdapter(Class adapter) { if (IResource.class.equals(adapter)) { return resource; } return null; } public abstract Object[] getChildren(); /** * @return non null set with all files (recursive) contained under the given path */ public abstract Set getFiles(); }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/Signature.java000066400000000000000000000061711173713500500323010ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.extensions.HgSigsClient; import com.vectrace.MercurialEclipse.exception.HgException; /** * @author bastian * */ public class Signature { private final HgRoot root; private String key; private String nodeId; private boolean valid; private boolean checked; public Signature(String key, String nodeId, HgRoot root) { this.key = key; this.nodeId = nodeId; this.root = root; } public boolean validate() { if (checked) { return isValid(); } try { String result = HgSigsClient.checkSig(root, nodeId); if (result != null && !result.contains("No valid signature for")) { //$NON-NLS-1$ valid = true; key = result.split("\n")[1].trim(); //$NON-NLS-1$ } checked = true; return valid; } catch (HgException e) { checked = true; valid = false; MercurialEclipsePlugin.logError(e); return false; } } @Override public String toString() { return valid + ":" + key + ", " + nodeId; //$NON-NLS-1$ //$NON-NLS-2$ } public void setKey(String key) { this.key = key; } public String getKey() { return key; } /** * @param changeSetId * the changeSetId to set */ public void setNodeId(String changeSetId) { this.nodeId = changeSetId; } /** * @return the changeSetId */ public String getNodeId() { return nodeId; } public void setValid(boolean valid) { this.valid = valid; } public boolean isValid() { return valid; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((key == null) ? 0 : key.hashCode()); result = prime * result + ((nodeId == null) ? 0 : nodeId.hashCode()); result = prime * result + ((root == null) ? 0 : root.hashCode()); result = prime * result + (valid ? 1231 : 1237); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Signature)) { return false; } Signature other = (Signature) obj; if (key == null) { if (other.key != null) { return false; } } else if (!key.equals(other.key)) { return false; } if (nodeId == null) { if (other.nodeId != null) { return false; } } else if (!nodeId.equals(other.nodeId)) { return false; } if (root == null) { if (other.root != null) { return false; } } else if (!root.equals(other.root)) { return false; } if (valid != other.valid) { return false; } return true; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/Tag.java000066400000000000000000000102011173713500500310400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.util.Set; import org.eclipse.team.core.history.ITag; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet.ShallowChangeSet; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; /** * @author Bastian */ public class Tag implements ITag, Comparable { private static final String TIP = HgRevision.TIP.getChangeset(); /** name of the tag, unique in the repository */ private final String name; private final int revision; private final String globalId; private final boolean local; private ChangeSet changeSet; private final HgRoot hgRoot; public Tag(HgRoot hgRoot, String name, int revision, String globalId, boolean local) { super(); this.hgRoot = hgRoot; this.name = name; this.revision = revision; this.globalId = globalId; this.local = local; } public Tag(HgRoot hgRoot, String name, ChangeSet changeSet, boolean local) { this(hgRoot, name, changeSet.getChangesetIndex(), changeSet.getChangeset(), local); this.changeSet = changeSet; } /** * Note: this method may trigger Mercurial call to retrieve the changeset info, if * the tag was created with {@link #Tag(HgRoot, String, int, String, boolean)} constructor * and the local changeset cache doesn't contain the tag version! * @return never null */ public ChangeSet getChangeSet() { if(changeSet != null) { return changeSet; } LocalChangesetCache cache = LocalChangesetCache.getInstance(); try { changeSet = cache.getOrFetchChangeSetById(hgRoot, revision + ":" + globalId); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } if(changeSet == null) { try { Set revisions = cache.fetchRevisions(hgRoot, true, 1, revision, false); if(revisions.size() == 1) { changeSet = revisions.iterator().next(); } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } if(changeSet == null) { changeSet = new ShallowChangeSet(revision, globalId, hgRoot); } } return changeSet; } public String getName() { return name; } public int getRevision() { return revision; } public String getGlobalId() { return globalId; } public boolean isLocal() { return local; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Tag other = (Tag) obj; if (name == null) { if (other.name != null) { return false; } } else if (!name.equals(other.name)) { return false; } return true; } @Override public String toString() { return name + " [" + revision + ':' + globalId + ']'; } public int compareTo(Tag tag) { /* "tip" must be always the first in the collection */ if (tag == null || name == null || isTip()) { return -1; } if (tag.isTip()) { return 1; } int cmp = tag.getRevision() - revision; if(cmp != 0){ // sort by revision first return cmp; } // sort by name cmp = name.compareToIgnoreCase(tag.getName()); if (cmp == 0) { // Check it case sensitive cmp = name.compareTo(tag.getName()); } return cmp; } public boolean isTip(){ return TIP.equals(name); } } UncommittedChangeSet.java000066400000000000000000000205611173713500500343320ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.util.HashSet; import java.util.List; import java.util.Observable; import java.util.Observer; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import com.vectrace.MercurialEclipse.synchronize.HgSubscriberMergeContext; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * A temporary changeset which holds not commited resources. This changeset cannot be used * as a usual changeset, as many of it's functionality is not supported or limited. *

* This changeset CAN observe changes of the status cache. If it is added as a listener * to the {@link MercurialStatusCache}, it only tracks the state of the enabled (root) * projects (see {@link #setProjects(IProject[])}). * * For history see WorkingChangeSet * * @author Andrei */ public class UncommittedChangeSet extends WorkingChangeSet implements Observer, IUncommitted { private final List listeners; private volatile boolean updateRequired; private volatile boolean cachingOn; private final Set projects; private HgSubscriberMergeContext context; private final PropertyChangeEvent event; private final MercurialStatusCache cache = MercurialStatusCache.getInstance(); public UncommittedChangeSet() { super("Uncommitted"); listeners = new CopyOnWriteArrayList(); projects = new HashSet(); files = new HashSet(); event = new PropertyChangeEvent(this, "", null, ""); } public boolean add(IFile file){ if(context != null && context.isHidden(file)){ return false; } if(cache.isDirectory(ResourceUtils.getPath(file))){ return false; } boolean added; synchronized (files){ added = files.add(file); } if(added) { // we need only one event if(cachingOn){ updateRequired = true; } else { notifyListeners(); } } return added; } private void notifyListeners() { Job updateJob = new Job("Uncommitted changeset update"){ @Override protected IStatus run(IProgressMonitor monitor) { for (IPropertyChangeListener listener : listeners) { listener.propertyChange(event); } monitor.done(); return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return family == ExclusiveRule.class; } @Override public boolean shouldSchedule() { Job[] jobs = Job.getJobManager().find(ExclusiveRule.class); for (Job job : jobs) { ExclusiveRule rule = (ExclusiveRule) job.getRule(); if(UncommittedChangeSet.this.equals(rule.cs)){ // do not schedule me because exactly the same job is waiting to be started! return false; } } return true; } }; updateJob.setRule(new ExclusiveRule(this)); updateJob.schedule(50); } public void hide(IPath[] paths){ if(context == null){ return; } boolean changed = false; MercurialStatusCache statusCache = MercurialStatusCache.getInstance(); for (IPath path : paths) { if(path.segmentCount() < 2){ continue; } IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IProject project = root.getProject(path.segment(0)); synchronized (projects) { if(project == null || !projects.contains(project)){ continue; } } IResource res = project.findMember(path.removeFirstSegments(1)); // only allow to hide files which are dirty if(res instanceof IFile && !statusCache.isClean(res)){ IFile file = (IFile) res; synchronized (files) { if(files.contains(file)){ context.hide(file); files.remove(file); changed = true; } } } } if(changed){ updateRequired = true; endInput(null); } } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#addListener(org.eclipse.jface.util.IPropertyChangeListener) */ public void addListener(IPropertyChangeListener listener){ if(!listeners.contains(listener)) { listeners.add(listener); } } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#removeListener(org.eclipse.jface.util.IPropertyChangeListener) */ public void removeListener(IPropertyChangeListener listener){ listeners.remove(listener); } public void beginInput() { cachingOn = true; } public void endInput(IProgressMonitor monitor) { cachingOn = false; if(!updateRequired){ return; } updateRequired = false; notifyListeners(); } /** * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void update(Observable o, Object arg) { boolean changed = false; try { beginInput(); clear(); synchronized (projects) { for (IProject project : projects) { changed |= update(project); } } } finally { updateRequired |= changed; endInput(null); } } private boolean update(IProject project){ if(!projects.contains(project)){ return false; } final int bits = MercurialStatusCache.MODIFIED_MASK; Set files2 = cache.getFiles(bits, project); if(files2.isEmpty()){ return true; } boolean changed = false; for (IFile file : files2) { changed |= add(file); } return changed; } /** * @param projects non null project list the changeset is responsible for * * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#setProjects(org.eclipse.core.resources.IProject[]) */ public void setProjects(IProject[] projects) { synchronized (this.projects) { this.projects.clear(); for (IProject project : projects) { this.projects.add(project); HgRoot root = MercurialTeamProvider.getHgRoot(project); if(root != null) { this.projects.add(root.getResource()); } } } } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#getProjects() */ public IProject[] getProjects() { synchronized (this.projects) { return this.projects.toArray(new IProject[projects.size()]); } } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#dispose() */ public void dispose() { MercurialStatusCache.getInstance().deleteObserver(this); clear(); synchronized (projects) { projects.clear(); } } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#setContext(com.vectrace.MercurialEclipse.synchronize.HgSubscriberMergeContext) */ public void setContext(HgSubscriberMergeContext context) { this.context = context; } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#getContext() */ public HgSubscriberMergeContext getContext() { return context; } private final class ExclusiveRule implements ISchedulingRule { private final UncommittedChangeSet cs; public ExclusiveRule(UncommittedChangeSet cs) { this.cs = cs; } public boolean isConflicting(ISchedulingRule rule) { return contains(rule); } public boolean contains(ISchedulingRule rule) { return rule instanceof ExclusiveRule && cs.equals(((ExclusiveRule) rule).cs); } } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/WorkingChangeSet.java000066400000000000000000000046121173713500500335400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; /** * A temporary changeset which holds not commited resources. This changeset cannot be used * as a usual changeset, as many of it's functionality is not supported or limited. * @author Andrei */ public abstract class WorkingChangeSet extends ChangeSet { public WorkingChangeSet(String name) { super(-1, name, null, null, "", null, "", null, null); //$NON-NLS-1$ direction = Direction.OUTGOING; files = new LinkedHashSet(); setName(name); } @Override public Set getFiles() { return Collections.unmodifiableSet(files); } @Override public void remove(IResource file){ // simply not supported, as it may be called not only from our code } @Override public boolean equals(Object obj) { return this == obj; } @Override public int hashCode() { return System.identityHashCode(this); } @Override public String toString() { String changeset = getChangeset(); int size = getFiles().size(); if(size == 0){ return changeset + " (empty)"; } return changeset + " (" + size + ")"; } public void clear(){ synchronized (files){ files.clear(); } } @Override public void setName(String name) { super.setName(name); } @Override public FileFromChangeSet[] getChangesetFiles() { Set files2 = getFiles(); int diffKind = Differencer.CHANGE | Differencer.RIGHT; List fcs = new ArrayList(files2.size()); for (IFile file : files2) { fcs.add(new FileFromChangeSet(this, file, null, diffKind)); } return fcs.toArray(new FileFromChangeSet[0]); } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/messages.properties000066400000000000000000000002021173713500500334070ustar00rootroot00000000000000FlagManager.unknownStatus=Unknown status: ' FlaggedAdaptable.unresolvedStatus=Unresolved FlaggedAdaptable.resolvedStatus=Resolved eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/resources/000077500000000000000000000000001173713500500315025ustar00rootroot00000000000000DummyResourceAdapter.java000066400000000000000000000122001173713500500363650ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/resources/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model.resources; import java.util.Collections; import java.util.Map; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IPathVariableManager; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.team.internal.core.TeamPlugin; import com.vectrace.MercurialEclipse.exception.HgCoreException; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; public abstract class DummyResourceAdapter implements IResource { static V throwEx() throws CoreException { throw new HgException("Unsupported operation"); } static V throwCoreEx() throws HgCoreException { throw new HgCoreException("Unsupported operation"); } public boolean isDerived() { return false; } public boolean isDerived(int options) { return false; } public boolean isLinked() { return false; } public boolean isLinked(int options) { return false; } public boolean isLocal(int depth) { return true; } public boolean isPhantom() { return false; } public Map getPersistentProperties() throws CoreException { return Collections.EMPTY_MAP; } public String getPersistentProperty(QualifiedName key) throws CoreException { if(TeamPlugin.PROVIDER_PROP_KEY.equals(key)) { return MercurialTeamProvider.ID; } return null; } public boolean isSynchronized(int depth) { return true; } public boolean isTeamPrivateMember() { return false; } public boolean isTeamPrivateMember(int options) { return false; } public void clearHistory(IProgressMonitor monitor) throws CoreException { // noop } public void copy(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException { throwEx(); } public void copy(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void copy(IProjectDescription description, boolean force, IProgressMonitor monitor) throws CoreException { throwEx(); } public void copy(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public IMarker createMarker(String type) throws CoreException { return throwEx(); } public void delete(boolean force, IProgressMonitor monitor) throws CoreException { throwEx(); } public void delete(int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void deleteMarkers(String type, boolean includeSubtypes, int depth) throws CoreException { throwEx(); } public void move(IPath destination, boolean force, IProgressMonitor monitor) throws CoreException { throwEx(); } public void move(IPath destination, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void move(IProjectDescription description, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { throwEx(); } public void move(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void setDerived(boolean isDerived) throws CoreException { throwEx(); } public void setHidden(boolean isHidden) throws CoreException { throwEx(); } public void setLocal(boolean flag, int depth, IProgressMonitor monitor) throws CoreException { throwEx(); } public void setPersistentProperty(QualifiedName key, String value) throws CoreException { throwEx(); } public void setReadOnly(boolean readOnly) { throwCoreEx(); // 1.6! // file.setWritable(!readOnly); } public void setResourceAttributes(ResourceAttributes attributes) throws CoreException { throwCoreEx(); } public void setTeamPrivateMember(boolean isTeamPrivate) throws CoreException { throwCoreEx(); } public IMarker findMarker(long id) throws CoreException { return null; } public IMarker[] findMarkers(String type, boolean includeSubtypes, int depth) throws CoreException { return new IMarker[0]; } public int findMaxProblemSeverity(String type, boolean includeSubtypes, int depth) throws CoreException { return -1; } // 3.6 API public IPathVariableManager getPathVariableManager() { return null; } // 3.7 API public boolean isVirtual() { return false; } // 3.6 API public void setDerived(boolean isDerived, IProgressMonitor monitor) throws CoreException { throwCoreEx(); } } HgContainerAdapter.java000066400000000000000000000153361173713500500360000ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/resources/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model.resources; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.FileInfoMatcherDescription; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceFilterDescription; import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.model.HgRoot; public abstract class HgContainerAdapter extends HgResourceAdapter implements IContainer { public HgContainerAdapter(File file, HgRoot root, HgContainerAdapter parent) { super(file, root, parent); } @Override public Object getAdapter(Class adapter) { if(adapter == IContainer.class) { return this; } return super.getAdapter(adapter); } public void accept(IResourceProxyVisitor visitor, int memberFlags) throws CoreException { boolean ok = visitor.visit(createProxy()); if(ok) { IResource[] members = members(); for (IResource resource : members) { resource.accept(visitor, memberFlags); } } } public void accept(IResourceVisitor visitor, int depth, int memberFlags) throws CoreException { boolean ok = visitor.visit(this); if(ok) { IResource[] members = members(); for (IResource resource : members) { resource.accept(visitor, depth, memberFlags); } } } public boolean exists(IPath path) { return getLocation().append(path).toFile().exists(); } public IResource findMember(String name) { return findMember(getLocation().append(name)); } public IResource findMember(String name, boolean includePhantoms) { return findMember(name); } public IResource findMember(IPath path, boolean includePhantoms) { return findMember(path); } public IResource findMember(IPath path) { if(path.isEmpty()) { return this; } File member = getLocation().append(path).toFile(); if (!member.exists()) { return null; } if (member.isFile()) { return getFile(path); } return getFolder(path); } public IFile getFile(IPath path) { return getChild(IFile.class, path); } public IFolder getFolder(IPath path) { return getChild(IFolder.class, path); } private V getChild(Class clazz, IPath child) { if(child.isEmpty()) { if(!clazz.isAssignableFrom(getClass())) { return null; } return clazz.cast(this); } String name = child.segment(0); File memberFile = getLocation().append(name).toFile(); if (!memberFile.exists()) { if (clazz == IFile.class) { return clazz.cast(getFile(child.toOSString())); } return null; } if (child.segmentCount() == 1) { if (memberFile.isFile()) { if (clazz == IFile.class) { return clazz.cast(getFile(name)); } return null; } else if(clazz == IFolder.class) { return clazz.cast(getFolder(name)); } else { return null; } } IFolder folder = getFolder(name); child = child.removeFirstSegments(1); return ((HgContainerAdapter) folder).getChild(clazz, child); } public IFile getFile(String name) { File member = getLocation().append(name).toFile(); return new HgFileAdapter(member, getHgRoot(), this); } public IFolder getFolder(String name) { File member = getLocation().append(name).toFile(); return new HgFolderAdapter(member, getHgRoot(), this); } public IResource[] members() throws CoreException { File[] files = toFile().listFiles(); if(files == null || files.length == 0) { return new IResource[0]; } List members = new ArrayList(files.length); // Intentionally NOT using MercurialTeamProvider.getProjects(getRoot()) // to get ALL projects containing in this root, even if they are not configured yet IProject[] projects = null; IPath[] projectLocations = null; for (int i = 0; i < files.length; i++) { if (files[i].isFile()) { members.add(new HgFileAdapter(files[i], getHgRoot(), this)); } else { if(files[i].getName().equals(".hg")) { continue; } if (projects == null) { projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); projectLocations = new IPath[projects.length]; int j = 0; for (IProject project : projects) { projectLocations[j++] = project.getLocation(); } } HgFolderAdapter folder = new HgFolderAdapter(files[i], getHgRoot(), this); IProject project = getProject(folder, projects, projectLocations); if(project != null) { members.add(project); } else { members.add(folder); } } } return members.toArray(new IResource[members.size()]); } static IProject getProject(HgFolderAdapter folder, IProject[] projects, IPath[] projectLocations) { int i = 0; for (IProject project : projects) { if(folder.getLocation().equals(projectLocations[i++])) { return project; } } return null; } public final String getDefaultCharset() throws CoreException { return getHgRoot().getEncoding(); } public String getDefaultCharset(boolean checkImplicit) throws CoreException { return getDefaultCharset(); } public IResource[] members(boolean includePhantoms) throws CoreException { return members(); } public IResource[] members(int memberFlags) throws CoreException { return members(); } public String getFileExtension() { return null; } public IFile[] findDeletedMembersWithHistory(int depth, IProgressMonitor monitor) throws CoreException { return new IFile[0]; } public void setDefaultCharset(String charset) throws CoreException { throwEx(); } public void setDefaultCharset(String charset, IProgressMonitor monitor) throws CoreException { throwEx(); } // 3.6 API public IResourceFilterDescription createFilter(int type, FileInfoMatcherDescription matcherDescription, int updateFlags, IProgressMonitor monitor) throws CoreException { return throwCoreEx(); } // 3.6 API public IResourceFilterDescription[] getFilters() throws CoreException { return new IResourceFilterDescription[0]; } } HgFileAdapter.java000066400000000000000000000144341173713500500347330ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/resources/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model.resources; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.net.URI; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFileState; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.content.IContentDescription; import org.eclipse.core.runtime.content.IContentTypeManager; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; public class HgFileAdapter extends HgResourceAdapter implements IFile { public HgFileAdapter(File file, HgRoot root, HgContainerAdapter parent) { super(file, root, parent); } public void appendContents(InputStream source, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { int updateFlags = force ? IResource.FORCE : IResource.NONE; updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE; appendContents(source, updateFlags, monitor); } public void appendContents(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void create(InputStream source, boolean force, IProgressMonitor monitor) throws CoreException { create(source, (force ? IResource.FORCE : IResource.NONE), monitor); } public void create(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void createLink(IPath localLocation, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void createLink(URI location, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void delete(boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { toFile().delete(); } public String getCharset() throws CoreException { return getHgRoot().getEncoding(); } public String getCharset(boolean checkImplicit) throws CoreException { return getCharset(); } public String getCharsetFor(Reader reader) throws CoreException { // tries to obtain a description from the contents provided IContentDescription description; try { IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); description = contentTypeManager.getDescriptionFor(reader, getName(), new QualifiedName[] {IContentDescription.CHARSET}); } catch (IOException e) { throw new HgException("Failed to retrieve contents charset", e); } if (description != null) { String charset; if ((charset = description.getCharset()) != null) { return charset; } } return getCharset(); } public IContentDescription getContentDescription() throws CoreException { return null; } public InputStream getContents() throws CoreException { try { return new FileInputStream(toFile()); } catch (IOException e) { throw new HgException("Failed to open stream", e); } } public InputStream getContents(boolean force) throws CoreException { return getContents(); } @SuppressWarnings("deprecation") public int getEncoding() throws CoreException { return IFile.ENCODING_UTF_8; } public IFileState[] getHistory(IProgressMonitor monitor) throws CoreException { return new IFileState[0]; } public void move(IPath destination, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { throwEx(); } public void setCharset(String newCharset) throws CoreException { throwEx(); } public void setCharset(String newCharset, IProgressMonitor monitor) throws CoreException { throwEx(); } public void setContents(InputStream source, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { int updateFlags = force ? IResource.FORCE : IResource.NONE; updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE; setContents(source, updateFlags, monitor); } public void setContents(IFileState source, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { int updateFlags = force ? IResource.FORCE : IResource.NONE; updateFlags |= keepHistory ? IResource.KEEP_HISTORY : IResource.NONE; setContents(source.getContents(), updateFlags, monitor); } public void setContents(InputStream source, int updateFlags, IProgressMonitor monitor) throws CoreException { if(source == null) { source = new ByteArrayInputStream(new byte[0]); } try { FileOutputStream fos = new FileOutputStream(toFile()); byte [] buf = new byte [8096]; int size; while((size = source.read(buf)) > 0) { fos.write(buf, 0, size); } } catch (IOException e) { throw new HgException("Failed to write into file", e); } } public void setContents(IFileState source, int updateFlags, IProgressMonitor monitor) throws CoreException { setContents(source.getContents(), updateFlags, monitor); } public int getType() { return IResource.FILE; } @Override public Object getAdapter(Class adapter) { if(adapter == IFile.class) { return this; } return super.getAdapter(adapter); } public String getFileExtension() { return getLocation().getFileExtension(); } public void accept(IResourceProxyVisitor visitor, int memberFlags) throws CoreException { visitor.visit(createProxy()); } public void accept(IResourceVisitor visitor, int depth, int memberFlags) throws CoreException { visitor.visit(this); } } HgFolderAdapter.java000066400000000000000000000037721173713500500352720ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/resources/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model.resources; import java.io.File; import java.net.URI; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.model.HgRoot; public class HgFolderAdapter extends HgContainerAdapter implements IFolder { public HgFolderAdapter(File file, HgRoot root, HgContainerAdapter parent) { super(file, root, parent); } public void create(boolean force, boolean local, IProgressMonitor monitor) throws CoreException { throwEx(); } public void create(int updateFlags, boolean local, IProgressMonitor monitor) throws CoreException { throwEx(); } public void createLink(IPath localLocation, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void createLink(URI location, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void delete(boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { toFile().delete(); } public void move(IPath destination, boolean force, boolean keepHistory, IProgressMonitor monitor) throws CoreException { throwEx(); } @Override public Object getAdapter(Class adapter) { if(adapter == IFolder.class) { return this; } return super.getAdapter(adapter); } public int getType() { return IResource.FOLDER; } } HgProjectAdapter.java000066400000000000000000000135301173713500500354560ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/resources/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model.resources; import java.net.URI; import java.util.Map; import org.eclipse.core.internal.resources.ProjectDescription; import org.eclipse.core.resources.IBuildConfiguration; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IProjectNature; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.content.IContentTypeMatcher; import org.eclipse.team.internal.core.TeamPlugin; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; @SuppressWarnings("restriction") public class HgProjectAdapter extends HgContainerAdapter implements IProject { public HgProjectAdapter(HgRoot root) { super(root, root, null); try { setSessionProperty(TeamPlugin.PROVIDER_PROP_KEY, new MercurialTeamProvider()); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } public void build(int kind, IProgressMonitor monitor) throws CoreException { return; } public void close(IProgressMonitor monitor) throws CoreException { return; } public void create(IProjectDescription description, IProgressMonitor monitor) throws CoreException { throwEx(); } public void create(IProgressMonitor monitor) throws CoreException { throwEx(); } public void create(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } public void delete(boolean deleteContent, boolean force, IProgressMonitor monitor) throws CoreException { throwEx(); } public IContentTypeMatcher getContentTypeMatcher() throws CoreException { return Platform.getContentTypeManager(); } public IProjectDescription getDescription() throws CoreException { ProjectDescription description = new ProjectDescription(); description.setLocation(getLocation()); description.setName(getName()); return description; } public IProjectNature getNature(String natureId) throws CoreException { return null; } @SuppressWarnings("deprecation") public IPath getPluginWorkingLocation(org.eclipse.core.runtime.IPluginDescriptor plugin) { if (plugin == null) { return null; } return getWorkingLocation(plugin.getUniqueIdentifier()); } public IPath getWorkingLocation(String id) { if (id == null || !exists()) { return null; } IPath stateLocation = ResourcesPlugin.getPlugin().getStateLocation(); IPath result = stateLocation.append(".projects").append(getName()).append(id); result.toFile().mkdirs(); return result; } public void move(IProjectDescription description, boolean force, IProgressMonitor monitor) throws CoreException { throwEx(); } public int getType() { return IResource.PROJECT; } @Override public IPath getFullPath() { return new Path(getName()); } @Override public Object getAdapter(Class adapter) { if(adapter == IProject.class) { return this; } return super.getAdapter(adapter); } public IProject[] getReferencedProjects() throws CoreException { return new IProject[0]; } public IProject[] getReferencingProjects() { return new IProject[0]; } public boolean hasNature(String natureId) throws CoreException { return false; } public boolean isNatureEnabled(String natureId) throws CoreException { return false; } public boolean isOpen() { return true; } public void open(int updateFlags, IProgressMonitor monitor) throws CoreException { open(monitor); } public void open(IProgressMonitor monitor) throws CoreException { return; } public void setDescription(IProjectDescription description, IProgressMonitor monitor) throws CoreException { throwEx(); } public void setDescription(IProjectDescription description, int updateFlags, IProgressMonitor monitor) throws CoreException { throwEx(); } // Map/**/ is 3.6 API... public void build(int kind, String builderName, Map/**/ args, IProgressMonitor monitor) throws CoreException { throwCoreEx(); } // 3.6 API public void build(IBuildConfiguration config, int kind, IProgressMonitor monitor) throws CoreException { throwCoreEx(); } // 3.7 API public IBuildConfiguration getActiveBuildConfig() throws CoreException { return throwCoreEx(); } // 3.7 API public IBuildConfiguration getBuildConfig(String configName) throws CoreException { return throwCoreEx(); } // 3.7 API public IBuildConfiguration[] getBuildConfigs() throws CoreException { return throwCoreEx(); } // 3.7 API public IBuildConfiguration[] getReferencedBuildConfigs(String configName, boolean includeMissing) throws CoreException { return throwCoreEx(); } // 3.7 API public boolean hasBuildConfig(String configName) throws CoreException { return false; } // 3.6 API public void loadSnapshot(int options, URI snapshotLocation, IProgressMonitor monitor) throws CoreException { throwCoreEx(); } // 3.6 API public void saveSnapshot(int options, URI snapshotLocation, IProgressMonitor monitor) throws CoreException { throwCoreEx(); } } HgResourceAdapter.java000066400000000000000000000162431173713500500356430ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/resources/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model.resources; import java.io.File; import java.net.URI; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.MultiRule; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgPath; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgResource; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; public abstract class HgResourceAdapter extends DummyResourceAdapter implements IHgResource { private final File file; private final IPath path; private final HgRoot root; private final IContainer parent; private final Map sessionProps; public HgResourceAdapter(File file, HgRoot root, HgContainerAdapter parent) { this.file = file; this.root = root; this.parent = parent == null? getWorkspace().getRoot() : parent; this.path = file instanceof HgPath? ((HgPath)file).getIPath() : new Path(file.getAbsolutePath()); this.sessionProps = new HashMap(); } @Override public String toString() { return file.toString(); } public HgRoot getHgRoot() { return root; } public File toFile() { return file; } public IResourceProxy createProxy() { return new ResourceProxyAdapter(this); } public void accept(IResourceVisitor visitor) throws CoreException { accept(visitor, IResource.DEPTH_INFINITE, 0); } public void accept(IResourceVisitor visitor, int depth, boolean includePhantoms) throws CoreException { accept(visitor, depth, includePhantoms ? IContainer.INCLUDE_PHANTOMS : 0); } public boolean exists() { return file.exists(); } public IPath getFullPath() { int matchingFirstSegments = getLocation().matchingFirstSegments(getProject().getLocation()); return getLocation().removeFirstSegments(matchingFirstSegments - 1); } public long getLocalTimeStamp() { return file.lastModified(); } public IPath getLocation() { return path; } public URI getLocationURI() { return file.toURI(); } public IMarker getMarker(long id) { return throwCoreEx(); } public long getModificationStamp() { return getLocalTimeStamp(); } public String getName() { return file.getName(); } public final IContainer getParent() { return parent; } public final IProject getProject() { return getHgRoot().getResource(); } public IPath getProjectRelativePath() { return getFullPath().removeFirstSegments(1); } public IPath getRawLocation() { return getLocation(); } public URI getRawLocationURI() { return getLocationURI(); } public ResourceAttributes getResourceAttributes() { ResourceAttributes ra = new ResourceAttributes(); ra.setArchive(true); ra.setSymbolicLink(false); ra.setExecutable(file.canExecute()); ra.setHidden(file.isHidden()); ra.setReadOnly(!file.canWrite()); return ra; } public Map getSessionProperties() throws CoreException { return sessionProps; } public Object getSessionProperty(QualifiedName key) throws CoreException { return sessionProps.get(key); } public IWorkspace getWorkspace() { return ResourcesPlugin.getWorkspace(); } public boolean isAccessible() { return exists(); } public boolean isHidden() { return file.isHidden(); } public boolean isHidden(int options) { return isHidden(); } public boolean isReadOnly() { return !file.canWrite(); } public void refreshLocal(int depth, IProgressMonitor monitor) throws CoreException { MercurialStatusCache.getInstance().refreshStatus(this, monitor); } public void touch(IProgressMonitor monitor) throws CoreException { MercurialStatusCache.getInstance().refreshStatus(this, monitor); } public void revertModificationStamp(long value) throws CoreException { file.setLastModified(value); } public long setLocalTimeStamp(long value) throws CoreException { file.setLastModified(value); return getLocalTimeStamp(); } public void setSessionProperty(QualifiedName key, Object value) throws CoreException { sessionProps.put(key, value); } public Object getAdapter(Class adapter) { if(adapter == IResource.class) { return this; } return Platform.getAdapterManager().getAdapter(this, adapter); } public boolean contains(ISchedulingRule rule) { if (this == rule) { return true; } if (rule instanceof MultiRule) { MultiRule multi = (MultiRule) rule; ISchedulingRule[] children = multi.getChildren(); for (int i = 0; i < children.length; i++) { if (!contains(children[i])) { return false; } } return true; } if (!(rule instanceof IResource)) { return false; } IPath location = ((IResource) rule).getLocation(); if (location == null) { return false; } return getLocation().isPrefixOf(location); } public boolean isConflicting(ISchedulingRule rule) { if (!(rule instanceof IResource)) { return false; } IPath otherPath = ((IResource) rule).getLocation(); return getLocation().isPrefixOf(otherPath) || otherPath.isPrefixOf(getLocation()); } @Override public int hashCode() { return file.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof HgResourceAdapter)) { return false; } HgResourceAdapter other = (HgResourceAdapter) obj; return file.equals(other.file); } /** * @see com.vectrace.MercurialEclipse.model.IHgResource#getHgRootRelativePath() */ public String getHgRootRelativePath() { // TODO Auto-generated method stub return null; } /** * @see com.vectrace.MercurialEclipse.model.IHgResource#getChangeSet() */ public ChangeSet getChangeSet() { // TODO Auto-generated method stub return null; } /** * @see com.vectrace.MercurialEclipse.model.IHgResource#getIPath() */ public IPath getIPath() { // TODO Auto-generated method stub return null; } /** * @see com.vectrace.MercurialEclipse.model.IHgResource#getResource() */ public IResource getResource() { // TODO Auto-generated method stub return null; } } ResourceProxyAdapter.java000066400000000000000000000037171173713500500364300ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/model/resources/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.model.resources; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.QualifiedName; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; public class ResourceProxyAdapter implements IResourceProxy { private final HgResourceAdapter resource; public ResourceProxyAdapter(HgResourceAdapter resource) { this.resource = resource; } public long getModificationStamp() { return resource.getModificationStamp(); } public boolean isAccessible() { return resource.isAccessible(); } public boolean isDerived() { return resource.isDerived(); } public boolean isLinked() { return resource.isLinked(); } public boolean isPhantom() { return resource.isPhantom(); } public boolean isHidden() { return resource.isHidden(); } public boolean isTeamPrivateMember() { return resource.isTeamPrivateMember(); } public String getName() { return resource.getName(); } public Object getSessionProperty(QualifiedName key) { try { return resource.getSessionProperty(key); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return null; } } public int getType() { return resource.getType(); } public IPath requestFullPath() { return resource.getFullPath(); } public IResource requestResource() { return resource; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/mylyn/000077500000000000000000000000001173713500500275405ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/mylyn/IMylynFacade.java000066400000000000000000000021661173713500500327150ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * zluspai implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.mylyn; import org.eclipse.core.resources.IResource; /** * Facade to the mylyn accessor methods. * * @author zluspai */ public interface IMylynFacade { /** * Get the comment for the current mylyn task. * @param resources * @return The comment text, or null if no task is active, or mylyn is not used */ String getCurrentTaskComment(IResource[] resources); /** * Get the resources for the current task (this is the current the mylyn context). * @return The resources, or null if no task active or mylyn is not used */ IResource[] getCurrentTaskResources(); } MylynFacadeFactory.java000066400000000000000000000034011173713500500340460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/mylyn/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * zluspai implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.mylyn; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * Factory for mylyn facade. Used to avoid ClassCastException when mylyn is not available. * * @author zluspai * */ public final class MylynFacadeFactory { private MylynFacadeFactory() { // hide constructor of utility class. } /** * Get the IMylynFacade instance. * @return The mylyn facade */ public static IMylynFacade getMylynFacade() { Object facade = Proxy.newProxyInstance(MylynFacadeFactory.class.getClassLoader(), new Class[] {IMylynFacade.class}, new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { MylynFacadeImpl impl = new MylynFacadeImpl(); return method.invoke(impl, args); } catch (InvocationTargetException th) { // expected if Mylin is not installed => so NO logs here. } catch (Throwable t){ // unexpected => log MercurialEclipsePlugin.logError(t); } return null; } }); return (IMylynFacade) facade; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/mylyn/MylynFacadeImpl.java000066400000000000000000000050161173713500500334230ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * zluspai implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.mylyn; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Platform; import org.eclipse.mylyn.context.core.ContextCore; import org.eclipse.mylyn.context.core.IInteractionContext; import org.eclipse.mylyn.internal.resources.ui.ResourcesUiBridgePlugin; import org.eclipse.mylyn.internal.team.ui.ContextChangeSet; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.ui.TasksUi; /** * The real mylyn facade class wraps all mylyn functionality accessed from this plugin. * * @author zluspai */ @SuppressWarnings("restriction") class MylynFacadeImpl implements IMylynFacade { static ITask getCurrentTask() { return TasksUi.getTaskActivityManager().getActiveTask(); } static IInteractionContext getActiveContext() { return ContextCore.getContextManager().getActiveContext(); } /** * Get comment for the current mylyn task. * @param resources * @return The comment created by mylyn from the task-template */ public String getCurrentTaskComment(IResource[] resources) { if (resources == null) { return null; } ITask task = getCurrentTask(); if (task == null) { return null; } boolean checkTaskRepository = true; String comment = ContextChangeSet.getComment(checkTaskRepository, task, resources); return comment; } /** * Get the resources for the current task, which is the mylyn context * @return The resources, or null if no current task present */ public IResource[] getCurrentTaskResources() { ITask task = getCurrentTask(); if (task == null) { return null; } if (Platform.isRunning() && ResourcesUiBridgePlugin.getDefault() != null && task.isActive()) { IInteractionContext context = getActiveContext(); if (context == null) { return null; } List resources = ResourcesUiBridgePlugin.getDefault().getInterestingResources(context); if (resources == null) { return null; } return resources.toArray(new IResource[0]); } return null; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/000077500000000000000000000000001173713500500305535ustar00rootroot00000000000000BundleOperation.java000066400000000000000000000042651173713500500344400ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgBundleClient; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; public class BundleOperation extends HgOperation { private final HgRoot root; private final String bundleFile; private final ChangeSet rev; private final ChangeSet base; private final String repo; public BundleOperation(IRunnableContext ctx, HgRoot hgRoot, ChangeSet revision, ChangeSet base, String bundleFileName, String repo) { super(ctx); root = hgRoot; rev = revision; this.base = base; bundleFile = bundleFileName; this.repo = repo; } @Override protected String getActionDescription() { return "Create bundle of repository " + root; } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask("Starting to create bundle...", 2); //$NON-NLS-1$ monitor.subTask("Calling Mercurial bundle command..."); monitor.worked(1); this.result = HgBundleClient.bundle(root, rev, repo, bundleFile, false, base.getChangeset()); monitor.worked(1); } catch (CoreException e) { throw new InvocationTargetException(e); } finally { monitor.done(); } } }CloneOperation.java000066400000000000000000000110061173713500500342560ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.Timer; import java.util.TimerTask; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.swt.widgets.Display; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgCloneClient; import com.vectrace.MercurialEclipse.commands.extensions.HgSvnClient; import com.vectrace.MercurialEclipse.commands.extensions.forest.HgFcloneClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.wizards.Messages; public class CloneOperation extends HgOperation { private final File parentDirectory; private final IHgRepositoryLocation repo; private final boolean noUpdate; private final boolean pull; private final boolean uncompressed; private final boolean timeout; private final String rev; private final String cloneName; private final boolean forest; private final boolean svn; /** * * @param context * @param parentDirectory the root directory for the cloned repository * @param repo non null repository to clone from * @param noUpdate true to clone only the repo (.hg) and do not create a working copy (it will be at version 0) * @param pull true to use pull protocoll to copy metadata * @param uncompressed true to NOT compress the data * @param timeout * @param rev the LAST revision which will be at the cloned repo, all subsequent revisions will be present * @param cloneName the base name of new repository. If null, basename of remote will be used * @param forest true to use forest extension * @param svn to use svn extension */ public CloneOperation(IRunnableContext context, File parentDirectory, IHgRepositoryLocation repo, boolean noUpdate, boolean pull, boolean uncompressed, boolean timeout, String rev, String cloneName, boolean forest, boolean svn) { super(context); this.parentDirectory = parentDirectory; this.repo = repo; this.noUpdate = noUpdate; this.pull = pull; this.uncompressed = uncompressed; this.timeout = timeout; this.rev = rev; this.cloneName = cloneName; this.forest = forest; this.svn = svn; } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(final IProgressMonitor m) throws InvocationTargetException, InterruptedException { m.beginTask(Messages.getString("CloneRepoWizard.operation.name"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$ // Timer which is used to monitor the moniktor cancellation Timer t = new Timer("Clone watcher", false); // only start timer if the operation is NOT running in the UI thread if(Display.getCurrent() == null){ final Thread threadToCancel = Thread.currentThread(); t.scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (m.isCanceled() && !threadToCancel.isInterrupted()) { threadToCancel.interrupt(); } } }, 1000, 50); } try { if (svn) { HgSvnClient.clone(parentDirectory, repo, timeout, cloneName); } else if (!forest) { HgCloneClient.clone(parentDirectory, repo, noUpdate, pull, uncompressed, timeout, rev, cloneName); } else { HgFcloneClient.fclone(parentDirectory, repo, noUpdate, pull, uncompressed, timeout, rev, cloneName); } m.worked(1); } catch (HgException e) { if(e.getCause() instanceof InterruptedException){ throw (InterruptedException) e.getCause(); } throw new InvocationTargetException(e); } finally { t.cancel(); } } @Override protected String getActionDescription() { return Messages.getString("CloneRepoWizard.actionDescription.1") + repo + Messages.getString("CloneRepoWizard.actionDescription.2") + cloneName; //$NON-NLS-1$ //$NON-NLS-2$ } public File getParentDirectory() { return parentDirectory; } }ImportPatchOperation.java000066400000000000000000000075421173713500500354620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Andrei Loskutov - bug fixes * John Peberdy - Move from ImportPatchWizard *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.operation.IRunnableContext; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.ui.LocationChooser.Location; import com.vectrace.MercurialEclipse.ui.LocationChooser.LocationType; import com.vectrace.MercurialEclipse.utils.ClipboardUtils; public class ImportPatchOperation extends HgOperation { private final Location location; private final HgRoot hgRoot; private final ArrayList options; /** * Whether the operation resulted in a conflict */ private boolean conflict = false; public ImportPatchOperation(IRunnableContext context, HgRoot hgRoot, Location location, ArrayList options) { super(context); this.hgRoot = hgRoot; this.location = location; this.options = options; } @Override protected String getActionDescription() { return Messages.getString("ImportOperation.importing"); } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(getActionDescription(), 1); try { result = performOperation(); } catch (HgException e) { if (HgPatchClient.isPatchImportConflict(e)) { conflict = true; result = e.getLocalizedMessage(); } else { throw new InvocationTargetException(e, e.getLocalizedMessage()); } } finally { int refreshFlags = RefreshRootJob.LOCAL_AND_OUTGOING; if (options != null && options.contains("--no-commit")) { refreshFlags = RefreshRootJob.LOCAL; } Job job = new RefreshWorkspaceStatusJob(hgRoot, refreshFlags); job.schedule(); if (conflict) { job.join(); } monitor.done(); } } protected String performOperation() throws HgException { if (location.getLocationType() == LocationType.Clipboard) { File file = null; try { file = ClipboardUtils.clipboardToTempFile("mercurial_", //$NON-NLS-1$ HgPatchClient.PATCH_EXTENSION); if (file != null) { return HgPatchClient.importPatch(hgRoot, file, options); } } finally { if (file != null && file.exists()) { boolean deleted = file.delete(); if (!deleted) { MercurialEclipsePlugin.logError("Failed to delete clipboard content file: " + file, null); } } } } else { return HgPatchClient.importPatch(hgRoot, location.getFile(), options); } // fail return null; } /** * @return Whether the operation resulted in a conflict */ public boolean isConflict() { return conflict ; } }InitOperation.java000066400000000000000000000054171173713500500341320ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.io.File; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.team.core.RepositoryProvider; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgInitClient; import com.vectrace.MercurialEclipse.model.HgPath; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.RefreshStatusJob; public class InitOperation extends HgOperation { private final IProject project; private final File newHgRoot; public InitOperation(IRunnableContext ctx, IProject project, File newHgRoot) { super(ctx); this.newHgRoot = newHgRoot; this.project = project; } @Override protected String getActionDescription() { return Messages.getString("InitOperation.creatingRepo"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask(Messages.getString("InitOperation.share"), 3); //$NON-NLS-1$ if (!HgPath.isHgRoot(newHgRoot)) { monitor.subTask(Messages.getString("InitOperation.call")); //$NON-NLS-1$ HgInitClient.init(newHgRoot); monitor.worked(1); } monitor.subTask(Messages.getString("InitOperation.mapping.1") + " " + project.getName() //$NON-NLS-1$ + Messages.getString("InitOperation.mapping.2")); //$NON-NLS-1$ RepositoryProvider.map(project, MercurialTeamProvider.class.getName()); monitor.worked(1); project.touch(monitor); monitor.subTask(Messages.getString("InitOperation.schedulingRefresh")); //$NON-NLS-1$ new RefreshStatusJob(Messages.getString("InitOperation.refresh.1") + " " + project //$NON-NLS-1$ + Messages.getString("InitOperation.refresh.2"), project) //$NON-NLS-1$ .schedule(); monitor.worked(1); } catch (CoreException e) { throw new InvocationTargetException(e); } finally { monitor.done(); } } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/Messages.java000066400000000000000000000021351173713500500331660ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.operations.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } QImportOperation.java000066400000000000000000000055521173713500500346220ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.operation.IRunnableContext; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQImportClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.views.PatchQueueView; /** * @author bastian * */ public class QImportOperation extends HgOperation { private final IPath patchFile; private final ChangeSet[] changesets; private final boolean existing; private final boolean force; private final HgRoot root; public QImportOperation(IRunnableContext context, IPath patchFile, ChangeSet[] changesets, boolean existing, boolean force, HgRoot root) { super(context); this.patchFile = patchFile; this.changesets = changesets; this.existing = existing; this.force = force; this.root = root; } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(getActionDescription(), 3); try { monitor.worked(1); monitor.subTask(Messages.getString("QImportOperation.call")); //$NON-NLS-1$ HgQImportClient.qimport(root, force, existing, changesets, patchFile); monitor.worked(1); monitor.subTask(Messages.getString("QImportOperation.refreshingView")); //$NON-NLS-1$ new SafeUiJob(Messages.getString("QImportOperation.refreshingView")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor1) { PatchQueueView.getView().populateTable(); return super.runSafe(monitor1); } }.schedule(); monitor.worked(1); } catch (HgException e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } finally { monitor.done(); } } @Override protected String getActionDescription() { return Messages.getString("QImportOperation.importingPatch"); //$NON-NLS-1$ } } RebaseOperation.java000066400000000000000000000115451173713500500344270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PartInitException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.extensions.HgRebaseClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.views.MergeView; /** * @author bastian * * The operation doesn't fail if a rebase conflict occurs. */ public class RebaseOperation extends HgOperation { private final HgRoot hgRoot; private int sourceRev = -1; private int destRev = -1; private int baseRev = -1; private final boolean collapse; private final boolean abort; private final boolean cont; private boolean keepBranches; private boolean keep; private final String user; public RebaseOperation(IRunnableContext context, HgRoot hgRoot, int sourceRev, int destRev, int baseRev, boolean collapse, boolean abort, boolean cont) { this(context, hgRoot, sourceRev, destRev, baseRev, collapse, abort, cont, false, null); } protected RebaseOperation(IRunnableContext context, HgRoot hgRoot, int sourceRev, int destRev, int baseRev, boolean collapse, boolean abort, boolean cont, boolean keepBranches, String user) { super(context); this.hgRoot = hgRoot; this.sourceRev = sourceRev; this.destRev = destRev; this.baseRev = baseRev; this.collapse = collapse; this.abort = abort; this.cont = cont; this.keepBranches = keepBranches; this.user = user; } public void setKeep(boolean keep) { this.keep = keep; } public void setKeepBranches(boolean keepBranches) { this.keepBranches = keepBranches; } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(getActionDescription(), 2); boolean rebaseConflict = false; try { monitor.worked(1); monitor.subTask(Messages.getString("RebaseOperation.calling")); //$NON-NLS-1$ boolean useExternalMergeTool = MercurialEclipsePlugin.getDefault().getPreferenceStore() .getBoolean(MercurialPreferenceConstants.PREF_USE_EXTERNAL_MERGE); result = HgRebaseClient.rebase(hgRoot, sourceRev, baseRev, destRev, collapse, cont, abort, keepBranches, keep, useExternalMergeTool, user); monitor.worked(1); } catch (HgException e) { rebaseConflict = HgRebaseClient.isRebaseConflict(e); if(rebaseConflict) { result = e.getMessage(); } else { throw new InvocationTargetException(e, e.getLocalizedMessage()); } } finally { RefreshWorkspaceStatusJob job = new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.ALL); job.schedule(); job.join(); monitor.done(); if(rebaseConflict) { showMergeView(); } } } /** * show Merge view, as it offers to abort a merge and revise the automatically merged files */ private void showMergeView() { Runnable runnable = new Runnable() { public void run() { try { MergeView.showRebaseConflict(hgRoot, MercurialEclipsePlugin.getActiveShell()); } catch (PartInitException e1) { MercurialEclipsePlugin.logError(e1); } } }; Display.getDefault().asyncExec(runnable); } @Override protected String getActionDescription() { return Messages.getString("RebaseOperation.rebasing"); //$NON-NLS-1$ } /** * Factory method to create a continue rebase operation */ public static RebaseOperation createContinue(IRunnableContext context, HgRoot root, String user) { return new RebaseOperation(context, root, -1, -1, -1, false, false, true, false, user); } /** * Factory method to create a abort rebase operation */ public static RebaseOperation createAbort(IRunnableContext context, HgRoot root) { return new RebaseOperation(context, root, -1, -1, -1, false, true, false); } } ResolveOperation.java000066400000000000000000000055101173713500500346400ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgResolveClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; public class ResolveOperation extends HgOperation { private final boolean checkStatus; private final Object[] resources; /** * @param part * The workbench part * @param resources * The resources to resolve * @param checkStatus * Whether the status of the resources has already been checked */ public ResolveOperation(IWorkbenchPart part, Object[] resources, boolean checkStatus) { super(part); this.resources = resources; this.checkStatus = checkStatus; } @Override protected String getActionDescription() { return Messages.getString("ResolveOperation.resolving"); //$NON-NLS-1$; } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { Object[] filtered = filter(resources); monitor.beginTask(getActionDescription(), filtered.length); if (filtered.length == 0) { throw new HgException("Please select conflicted files to resolve"); } for (Object resource : filtered) { if (resource instanceof IFile) { HgResolveClient.markResolved((IFile) resource); } } } catch (HgException e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } finally { monitor.worked(1); monitor.done(); } } private Object[] filter(Object[] objs) { List l = new ArrayList(); MercurialStatusCache cache = MercurialStatusCache.getInstance(); // Do not include projects or folders. One of the reasons is we'd have to ask for // confirmation. for (Object cur : objs) { if (cur instanceof IFile) { if (!checkStatus || cache.isConflict((IFile) cur)) { l.add(cur); } } } return l.toArray(); } } ShelveOperation.java000066400000000000000000000121671173713500500344550ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgIdentClient; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.commands.HgUpdateClient; import com.vectrace.MercurialEclipse.commands.extensions.HgAtticClient; import com.vectrace.MercurialEclipse.exception.HgCoreException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.ResourceProperties; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author bastian */ public class ShelveOperation extends HgOperation { private final HgRoot hgRoot; private File shelveFileConflict; public ShelveOperation(IWorkbenchPart part, HgRoot hgRoot) { super(part); this.hgRoot = hgRoot; } @Override protected String getActionDescription() { return Messages.getString("ShelveOperation.shelvingChanges"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { File shelveDir = new File(hgRoot, ".hg" + File.separator //$NON-NLS-1$ + "mercurialeclipse-shelve-backups"); //$NON-NLS-1$ try { // get modified files monitor.beginTask(Messages.getString("ShelveOperation.shelving"), 5); //$NON-NLS-1$ // check if hgattic is available if (MercurialUtilities.isCommandAvailable("attic-shelve", // $NON-NLS-1$ ResourceProperties.EXT_HGATTIC_AVAILABLE, "")) { // $NON-NLS-1$ String output = HgAtticClient.shelve(hgRoot, "MercurialEclipse shelve operation", // $NON-NLS-1$ true, HgCommitMessageManager.getDefaultCommitName(hgRoot), hgRoot.getName()); monitor.worked(1); new RefreshWorkspaceStatusJob(hgRoot).schedule(); monitor.worked(1); HgClients.getConsole().printMessage(output, null); } else { monitor.subTask(Messages.getString("ShelveOperation.determiningChanges")); //$NON-NLS-1$ // if (!HgStatusClient.isDirty(hgRoot)) { throw new HgCoreException(Messages.getString("ShelveOperation.error.nothingToShelve")); //$NON-NLS-1$ } monitor.worked(1); monitor.subTask(Messages.getString("ShelveOperation.shelvingChanges")); //$NON-NLS-1$ boolean mkdir = shelveDir.mkdir(); if(!mkdir && !shelveDir.exists()){ throw new HgCoreException(Messages.getString("ShelveOperation.error.shelfDirCreateFailed")); //$NON-NLS-1$ } File shelveFile = new File(shelveDir, hgRoot.getName() + "-patchfile.patch"); //$NON-NLS-1$ if (shelveFile.exists()) { shelveFileConflict = shelveFile; throw new HgCoreException(Messages.getString("ShelveOperation.error.shelfNotEmpty")); //$NON-NLS-1$ } // use empty resources to be able to shelve ALL files, also deleted/added List resources = Collections.emptyList(); // getDirtyFiles(hgRoot); List options = new ArrayList(1); options.add("--git"); HgPatchClient.exportPatch(hgRoot, resources, shelveFile, options); monitor.worked(1); monitor.subTask(Messages.getString("ShelveOperation.determiningCurrentChangeset")); //$NON-NLS-1$ String currRev = HgIdentClient.getCurrentChangesetId(hgRoot); monitor.worked(1); monitor.subTask(Messages.getString("ShelveOperation.cleaningDirtyFiles")); //$NON-NLS-1$ HgUpdateClient.cleanUpdate(hgRoot, currRev); } } catch (HgCoreException e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } catch (CoreException e) { // cleanup directory which otherwise may contain empty or invalid files and // block next shelve operation to execute if(shelveDir.isDirectory()){ ResourceUtils.delete(shelveDir, true); } throw new InvocationTargetException(e, e.getLocalizedMessage()); } finally { monitor.done(); } } public File getShelveFileConflict() { return shelveFileConflict; } } TransplantOperation.java000066400000000000000000000104761173713500500353560ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.lang.reflect.InvocationTargetException; import java.util.Timer; import java.util.TimerTask; import java.util.regex.Pattern; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.swt.widgets.Display; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.extensions.HgTransplantClient; import com.vectrace.MercurialEclipse.commands.extensions.HgTransplantClient.TransplantOptions; import com.vectrace.MercurialEclipse.dialogs.TransplantRejectsDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; public class TransplantOperation extends HgOperation { private static final Pattern HAS_REJECTS_PATTERN = Pattern.compile("abort:.*run hg transplant --continue"); private final TransplantOptions options; private final IHgRepositoryLocation repo; private final HgRoot hgRoot; public TransplantOperation(IRunnableContext context, HgRoot hgRoot, TransplantOptions options, IHgRepositoryLocation repo) { super(context); this.hgRoot = hgRoot; this.options = options; this.repo = repo; } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Transplanting changesets...", IProgressMonitor.UNKNOWN); //$NON-NLS-1$ // Timer which is used to monitor the monitor cancellation Timer t = new Timer("Transplant watcher", false); // only start timer if the operation is NOT running in the UI thread if(Display.getCurrent() == null){ final Thread threadToCancel = Thread.currentThread(); t.scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (monitor.isCanceled() && !threadToCancel.isInterrupted()) { threadToCancel.interrupt(); } } }, 500, 50); } try { try { result = HgTransplantClient.transplant(hgRoot, repo, options); } finally { RefreshWorkspaceStatusJob job = new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.LOCAL_AND_OUTGOING); job.schedule(); job.join(); t.cancel(); } } catch (HgException e) { if (handleTransplantException(e)) { result = e.getMessage(); } else { throw new InvocationTargetException(e); } } if (result != null && result.length() != 0) { HgClients.getConsole().printMessage(result, null); } } private boolean handleTransplantException(HgException e) { final String message = e.getMessage(); if (!HAS_REJECTS_PATTERN.matcher(message).find()) { return false; } try { final TransplantRejectsDialog dialog = new TransplantRejectsDialog(getShell(), hgRoot, message); getShell().getDisplay().asyncExec(new Runnable() { public void run() { dialog.open(); } }); return true; } catch (Exception ex) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); return false; } } @Override protected String getActionDescription() { return "Transplanting to " + hgRoot.getName(); } public static TransplantOperation createContinueOperation(IRunnableContext context, HgRoot hgRoot) { TransplantOptions options = new TransplantOptions(); options.continueLastTransplant = true; return new TransplantOperation(context, hgRoot, options, null); } public IHgRepositoryLocation getRepo() { return repo; } }UnShelveOperation.java000066400000000000000000000106661173713500500347620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2005-2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.ui.IWorkbenchPart; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.commands.extensions.HgAtticClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.ResourceProperties; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; /** * Check {@link #isConflict()} after running and display appropriate message to user. * * @author bastian */ public class UnShelveOperation extends HgOperation { private final HgRoot hgRoot; private boolean conflict; private final boolean force; public UnShelveOperation(IWorkbenchPart part, HgRoot hgRoot, boolean force) { super(part); this.hgRoot = hgRoot; this.force = force; } @Override protected String getActionDescription() { return Messages.getString("UnShelveOperation.UnshelvingChanges"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { // get modified files monitor.beginTask(Messages.getString("UnShelveOperation.Unshelving"), 4); //$NON-NLS-1$ // check if hgattic is available if (MercurialUtilities.isCommandAvailable("attic-shelve", // $NON-NLS-1$ ResourceProperties.EXT_HGATTIC_AVAILABLE, "")) { // $NON-NLS-1$ String output = HgAtticClient.unshelve(hgRoot, false, true, hgRoot.getName()); monitor.worked(1); new RefreshWorkspaceStatusJob(hgRoot).schedule(); monitor.worked(1); HgClients.getConsole().printMessage(output, null); } else { monitor.subTask(Messages .getString("UnShelveOperation.GettingChanges")); //$NON-NLS-1$ File shelveDir = new File(hgRoot, ".hg" + File.separator //$NON-NLS-1$ + "mercurialeclipse-shelve-backups"); //$NON-NLS-1$ if (shelveDir.exists()) { File shelveFile = new File(shelveDir, hgRoot.getName() + "-patchfile.patch"); if (shelveFile.exists()) { monitor.worked(1); monitor.subTask(Messages.getString("UnShelveOperation.applyingChanges")); //$NON-NLS-1$ ArrayList opts = new ArrayList(); opts.add("--no-commit"); if (force) { opts.add("--force"); } try { HgPatchClient.importPatch(hgRoot, shelveFile, opts); monitor.worked(1); monitor.subTask(Messages.getString("UnShelveOperation.emptyingShelf")); //$NON-NLS-1$ if (!shelveFile.delete()) { throw new HgException(shelveFile.getName() + " could not be deleted."); } monitor.worked(1); monitor.subTask(Messages.getString("UnShelveOperation.refreshingProject")); //$NON-NLS-1$ } catch (HgException e) { if (HgPatchClient.isPatchImportConflict(e)) { conflict = true; result = e.getLocalizedMessage(); } else { throw e; } } finally { Job job = new RefreshWorkspaceStatusJob(hgRoot); job.schedule(); if (conflict) { job.join(); } } } else { throw new HgException(Messages .getString("UnShelveOperation.error.ShelfEmpty")); //$NON-NLS-1$ } } } } catch (Exception e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } finally { monitor.done(); } } /** * @return Whether a conflict occurred while unshelving */ public boolean isConflict() { return conflict; } } UpdateOperation.java000066400000000000000000000062151173713500500344460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operations/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.operations; import java.lang.reflect.InvocationTargetException; import java.util.Timer; import java.util.TimerTask; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.swt.widgets.Display; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgUpdateClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.wizards.Messages; /** * Update after cloning a repository. Warning: Always does clean updates. */ public class UpdateOperation extends HgOperation { private final String rev; private final boolean forest; private final boolean svn; private final HgRoot hgRoot; /** * @param context * @param rev the LAST revision which will be at the cloned repo, all subsequent revisions will be present * @param forest true to use forest extension * @param svn to use svn extension */ public UpdateOperation(IRunnableContext context, HgRoot hgRoot, String rev, boolean forest, boolean svn) { super(context); this.hgRoot = hgRoot; this.rev = rev; this.forest = forest; this.svn = svn; } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(final IProgressMonitor m) throws InvocationTargetException, InterruptedException { m.beginTask(Messages.getString("CloneRepoWizard.updateOperation.name"), IProgressMonitor.UNKNOWN); //$NON-NLS-1$ // Timer which is used to monitor the monitor cancellation Timer t = new Timer("Update watcher", false); // only start timer if the operation is NOT running in the UI thread if(Display.getCurrent() == null){ final Thread threadToCancel = Thread.currentThread(); t.scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (m.isCanceled() && !threadToCancel.isInterrupted()) { threadToCancel.interrupt(); } } }, 1000, 50); } try { if (svn) { throw new IllegalArgumentException("SVN update not supported yet!"); } else if (forest) { throw new IllegalArgumentException("Forest update not supported yet!"); } else { HgUpdateClient.cleanUpdate(hgRoot, rev); } m.worked(1); } catch (HgException e) { if(e.getCause() instanceof InterruptedException){ throw (InterruptedException) e.getCause(); } throw new InvocationTargetException(e); } finally { t.cancel(); } } @Override protected String getActionDescription() { return "Updating " + hgRoot.getName() + " to selected revision"; } }messages.properties000066400000000000000000000033001173713500500344150ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/operationsInitOperation.call=Calling Mercurial... InitOperation.creatingRepo=Creating repository InitOperation.mapping.1=Mapping InitOperation.mapping.2=\ to team provider... InitOperation.refresh.1=Refresh project InitOperation.refresh.2=\ after mapping team provider... InitOperation.schedulingRefresh=Scheduling status refresh... InitOperation.share=Share: QImportOperation.call=Calling mercurial... QImportOperation.importingPatch=Importing patch to mercurial queue... QImportOperation.refreshingView=Refreshing Patch Queue View... RebaseOperation.calling=Calling mercurial... RebaseOperation.rebasing=Rebasing changesets... RebaseOperation.refreshing=Refreshing changesets... ResolveOperation.resolving=Resolving ShelveOperation.cleaningDirtyFiles=Cleaning dirty files... ShelveOperation.determiningChanges=Determining changes... ShelveOperation.determiningCurrentChangeset=Determining current changeset... ShelveOperation.error.nothingToShelve=Nothing to shelve. ShelveOperation.error.shelfNotEmpty=Shelf is not empty. You must unshelve before shelving anew. ShelveOperation.error.shelfDirCreateFailed=Failed to create shelf directory. ShelveOperation.refreshingResources=Refreshing resources... ShelveOperation.shelving=Shelving... ShelveOperation.shelvingChanges=Shelving changes... UnShelveOperation.applyingChanges=Applying changes... UnShelveOperation.emptyingShelf=Emptying shelf... UnShelveOperation.error.ShelfEmpty=Shelf is empty. Nothing to unshelve. UnShelveOperation.GettingChanges=Getting changes ... UnShelveOperation.refreshingProject=Refreshing project directory... UnShelveOperation.Unshelving=Unshelving... UnShelveOperation.UnshelvingChanges=Unshelving changes... ImportOperation.importing=Importing changesets...eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/000077500000000000000000000000001173713500500306715ustar00rootroot00000000000000ConsolePreferencesPage.java000066400000000000000000000151611173713500500360420ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.ColorFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; public class ConsolePreferencesPage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { public ConsolePreferencesPage() { super(GRID); setPreferenceStore(MercurialEclipsePlugin.getDefault() .getPreferenceStore()); } private ColorFieldEditor commandColorEditor; private ColorFieldEditor messageColorEditor; private ColorFieldEditor errorColorEditor; private BooleanFieldEditor showOnMessage; private BooleanFieldEditor restrictOutput; private BooleanFieldEditor wrap; private IntegerFieldEditor highWaterMark; private IntegerFieldEditor width; private BooleanFieldEditor debug; private BooleanFieldEditor debugTime; private BooleanFieldEditor showOnStartup; @Override protected void createFieldEditors() { final Composite composite = getFieldEditorParent(); createLabel(composite, Messages.getString("ConsolePreferencesPage.header")); //$NON-NLS-1$ IPreferenceStore store = getPreferenceStore(); // ** WRAP wrap = new BooleanFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_WRAP, Messages.getString("ConsolePreferencesPage.wrapText"), //$NON-NLS-1$ composite); addField(wrap); width = new IntegerFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_WIDTH, Messages.getString("ConsolePreferencesPage.consoleWidth"), composite); //$NON-NLS-1$ addField(width); // ** RESTRICT OUTPUT restrictOutput = new BooleanFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_LIMIT_OUTPUT, Messages.getString("ConsolePreferencesPage.limitOutput"), composite); //$NON-NLS-1$ addField(restrictOutput); highWaterMark = new IntegerFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_HIGH_WATER_MARK, Messages.getString("ConsolePreferencesPage.numberChars"), composite); // ) //$NON-NLS-1$ addField(highWaterMark); // ** SHOW AUTOMATICALLY showOnMessage = new BooleanFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_SHOW_ON_MESSAGE, Messages.getString("ConsolePreferencesPage.showConsoleOnMsg"), composite); //$NON-NLS-1$ addField(showOnMessage); // ** show on startup showOnStartup = new BooleanFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_SHOW_ON_STARTUP, "Show console on start-up", composite); //$NON-NLS-1$ addField(showOnStartup); // ** SHOW DEBUG debug = new BooleanFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_DEBUG, Messages.getString("ConsolePreferencesPage.showAllHgMsg"), composite); //$NON-NLS-1$ addField(debug); // ** SHOW TIME debugTime = new BooleanFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_DEBUG_TIME, Messages.getString("ConsolePreferencesPage.showCommandExecutionTime"), composite); //$NON-NLS-1$ addField(debugTime); createLabel(composite, Messages.getString("ConsolePreferencesPage.colorPrefs")); //$NON-NLS-1$ // ** COLORS AND FONTS commandColorEditor = SWTWidgetHelper.createColorFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_COMMAND_COLOR, Messages.getString("ConsolePreferencesPage.cmdColor"), composite, this, getPreferenceStore()); //$NON-NLS-1$ addField(commandColorEditor); messageColorEditor = SWTWidgetHelper.createColorFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_MESSAGE_COLOR, Messages.getString("ConsolePreferencesPage.msgColor"), composite, this, getPreferenceStore()); //$NON-NLS-1$ addField(messageColorEditor); errorColorEditor = SWTWidgetHelper.createColorFieldEditor( MercurialPreferenceConstants.PREF_CONSOLE_ERROR_COLOR, Messages.getString("ConsolePreferencesPage.errorColor"), composite, this, getPreferenceStore()); //$NON-NLS-1$ addField(errorColorEditor); //initIntegerFields(); width.setEnabled(store .getBoolean(MercurialPreferenceConstants.PREF_CONSOLE_WRAP), composite); highWaterMark .setEnabled( store .getBoolean(MercurialPreferenceConstants.PREF_CONSOLE_LIMIT_OUTPUT), composite); Dialog.applyDialogFont(composite); } @Override public void propertyChange(PropertyChangeEvent event) { super.propertyChange(event); initIntegerFields(); highWaterMark.setEnabled(restrictOutput.getBooleanValue(), getFieldEditorParent()); width.setEnabled(wrap.getBooleanValue(), getFieldEditorParent()); } private void initIntegerFields() { int currWatermark = highWaterMark.getIntValue(); if (currWatermark < 1000) { highWaterMark.setValidRange(1000, Integer.MAX_VALUE - 1); highWaterMark.setStringValue("100000"); //$NON-NLS-1$ } int currWidth = width.getIntValue(); if (currWidth < 80) { width.setStringValue("80"); //$NON-NLS-1$ width.setValidRange(80, Integer.MAX_VALUE - 1); } } /** * Utility method that creates a label instance and sets the default layout * data. * * @param parent * the parent for the new label * @param text * the text for the new label * @return the new label */ private Label createLabel(Composite parent, String text) { Label label = new Label(parent, SWT.LEFT); label.setText(text); GridData data = new GridData(); data.horizontalSpan = 2; data.horizontalAlignment = GridData.FILL; label.setLayoutData(data); return label; } public void init(IWorkbench workbench) { } @Override public boolean performOk() { boolean ok = super.performOk(); MercurialEclipsePlugin.getDefault().savePluginPreferences(); return ok; } } GeneralPreferencePage.java000066400000000000000000000221421173713500500356270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Gunnar Ahlberg - implementation * VecTrace (Zingo Andersen) - updateing it * Jérôme Nègre - adding label decorator section * Stefan C - Code cleanup * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import java.io.File; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.FileFieldEditor; import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.jface.preference.RadioGroupFieldEditor; import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import com.vectrace.MercurialEclipse.HgFeatures; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * This class represents a preference page that is contributed to the * Preferences dialog. By sub classing FieldEditorPreferencePage, * we can use the field support built into JFace that allows us to create a page * that is small and knows how to save, restore and apply itself. *

* This page is used to modify preferences only. They are stored in the * preference store that belongs to the main plug-in class. That way, * preferences can be accessed directly via the preference store. */ public class GeneralPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { private MercurialExecutableFileFieldEditor execField; private static final class LabelDecoratorRadioGroupFieldEditor extends RadioGroupFieldEditor { private LabelDecoratorRadioGroupFieldEditor(String name, String labelText, int numColumns, String[][] labelAndValues, Composite parent, boolean useGroup) { super(name, labelText, numColumns, labelAndValues, parent, useGroup); } @Override protected void doStore() { super.doStore(); MercurialEclipsePlugin.getDefault().checkHgInstallation(); // ResourceDecorator.onConfigurationChanged(); } } private static final class MercurialExecutableFileFieldEditor extends FileFieldEditor { private MercurialExecutableFileFieldEditor(String name, String labelText, Composite parent) { super(name, labelText, false, StringFieldEditor.VALIDATE_ON_KEY_STROKE, parent); } @Override public boolean checkState() { // There are other ways of doing this properly but this is // better than the default behavior String stringValue = getStringValue(); if(MERCURIAL_EXECUTABLE.equals(stringValue)){ clearErrorMessage(); return true; } return super.checkState(); } } private static final class GpgExecutableFileFieldEditor extends FileFieldEditor { private GpgExecutableFileFieldEditor(String name, String labelText, Composite parent) { super(name, labelText, false, StringFieldEditor.VALIDATE_ON_KEY_STROKE, parent); } @Override protected boolean checkState() { // There are other ways of doing this properly but this is // better than the default behaviour if(GPG_EXECUTABLE.equals(getStringValue())){ clearErrorMessage(); return true; } return super.checkState(); } } public GeneralPreferencePage() { super(GRID); setPreferenceStore(MercurialEclipsePlugin.getDefault().getPreferenceStore()); setDescription(Messages.getString("GeneralPreferencePage.description")); //$NON-NLS-1$ } /** * Creates the field editors. Field editors are abstractions of the common * GUI blocks needed to manipulate various types of preferences. Each field * editor knows how to save and restore itself. */ @Override public void createFieldEditors() { File integratedHgExecutable = PreferenceInitializer.getIntegratedHgExecutable(); if(integratedHgExecutable != null){ addField(new BooleanFieldEditor(USE_BUILT_IN_HG_EXECUTABLE, "Use default (built-in) Mercurial executable", getFieldEditorParent()){ @Override protected void fireValueChanged(String property, Object oldValue, Object newValue) { super.fireValueChanged(property, oldValue, newValue); if(newValue instanceof Boolean) { enablePathEditor(!((Boolean) newValue).booleanValue()); } } @Override protected void doLoadDefault() { super.doLoadDefault(); enablePathEditor(!getBooleanValue()); } }); } execField = new MercurialExecutableFileFieldEditor( MERCURIAL_EXECUTABLE, Messages.getString("GeneralPreferencePage.field.hgExecutable"), getFieldEditorParent()); addField(execField); execField.setEmptyStringAllowed(false); if (!MercurialEclipsePlugin.getDefault().isHgUsable()) { execField.setErrorMessage(Messages.getString("GeneralPreferencePage.error.HgNotInstalled")); //$NON-NLS-1$ } if (integratedHgExecutable != null && getPreferenceStore().getBoolean(USE_BUILT_IN_HG_EXECUTABLE)) { execField.setEnabled(false, getFieldEditorParent()); } addField(new GpgExecutableFileFieldEditor( GPG_EXECUTABLE, Messages.getString("GeneralPreferencePage.field.gpgExecutable"), getFieldEditorParent())); //$NON-NLS-1$ addField(new StringFieldEditor( MERCURIAL_USERNAME, Messages.getString("GeneralPreferencePage.field.username"), getFieldEditorParent())); //$NON-NLS-1$ addField(new BooleanFieldEditor( PREF_USE_MERCURIAL_USERNAME, "Prefer 'username' value from .hgrc as default user name", getFieldEditorParent())); //$NON-NLS-1$ addField(new BooleanFieldEditor( PREF_DEFAULT_REBASE_KEEP_BRANCHES, "Default to 'Retain the branch name' for Rebase command", getFieldEditorParent())); //$NON-NLS-1$ addField(new BooleanFieldEditor( PREF_USE_EXTERNAL_MERGE, Messages.getString("GeneralPreferencePage.useExternalMergeTool"), getFieldEditorParent())); //$NON-NLS-1$ BooleanFieldEditor editor = new BooleanFieldEditor( PREF_PUSH_NEW_BRANCH, Messages.getString("GeneralPreferencePage.pushNewBranches"), getFieldEditorParent()); addField(editor); if(!HgFeatures.NEW_BRANCH.isEnabled()) { editor.setEnabled(false, getFieldEditorParent()); editor.setLabelText(editor.getLabelText() + " " + Messages.getString("GeneralPreferencePage.optionDisabled")); } addField(new LabelDecoratorRadioGroupFieldEditor( LABELDECORATOR_LOGIC, Messages.getString("GeneralPreferencePage.field.decorationGroup.description"), //$NON-NLS-1$ 1, new String[][] { { Messages.getString("GeneralPreferencePage.field.decorationGroup.asModified"), //$NON-NLS-1$ LABELDECORATOR_LOGIC_2MM }, { Messages.getString("GeneralPreferencePage.field.decorationGroup.mostImportant"), //$NON-NLS-1$ LABELDECORATOR_LOGIC_HB } }, getFieldEditorParent(), true)); addField(new BooleanFieldEditor( PREF_DECORATE_WITH_COLORS, Messages.getString("GeneralPreferencePage.enableFontAndColorDecorations"), getFieldEditorParent())); //$NON-NLS-1$ addField(new BooleanFieldEditor( PREF_AUTO_SHARE_PROJECTS, Messages.getString("GeneralPreferencePage.autoshare"), //$NON-NLS-1$ getFieldEditorParent())); addField(new BooleanFieldEditor( PREF_PRESELECT_UNTRACKED_IN_COMMIT_DIALOG, Messages.getString("GeneralPreferencePage.preselectUntrackedInCommitDialog"), //$NON-NLS-1$ getFieldEditorParent())); BooleanFieldEditor cert_editor = new BooleanFieldEditor( PREF_VERIFY_SERVER_CERTIFICATE, Messages.getString("GeneralPreferencePage.verifyServerCertificate"), //$NON-NLS-1$ getFieldEditorParent()); addField(cert_editor); if(!HgFeatures.INSECURE.isEnabled()) { cert_editor.setEnabled(false, getFieldEditorParent()); cert_editor.setLabelText(cert_editor.getLabelText() + " " + Messages.getString("GeneralPreferencePage.optionDisabled")); } IntegerFieldEditor commitSizeEditor = new IntegerFieldEditor( COMMIT_MESSAGE_BATCH_SIZE, Messages.getString("GeneralPreferencePage.field.commitMessageBatchSize"), //$NON-NLS-1$ getFieldEditorParent()); commitSizeEditor.setValidRange(1, Integer.MAX_VALUE); addField(commitSizeEditor); } protected void enablePathEditor(boolean on) { if(execField == null){ return; } execField.setEnabled(on, getFieldEditorParent()); if(!on){ execField.setStringValue(PreferenceInitializer.getIntegratedHgExecutable().getPath()); } } @Override public void setVisible(boolean visible) { super.setVisible(visible); if(!execField.checkState()){ execField.showErrorMessage(); } } @Override public boolean isValid() { return execField.checkState() && super.isValid(); } public void init(IWorkbench workbench) { } }HgDecoratorConstants.java000066400000000000000000000067551173713500500355700ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; /** * @author bastian * */ public final class HgDecoratorConstants { private HgDecoratorConstants() { // hide constructor of utility class. } public static final String CHANGE_BACKGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.changedBackgroundColor"; //$NON-NLS-1$ public static final String CHANGE_FONT = "com.vectrace.mercurialeclipse.ui.colorsandfonts.changedFont"; //$NON-NLS-1$ public static final String CHANGE_FOREGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.changedForegroundColor"; //$NON-NLS-1$ public static final String IGNORED_BACKGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.ignoredBackgroundColor"; //$NON-NLS-1$ public static final String IGNORED_FONT = "com.vectrace.mercurialeclipse.ui.colorsandfonts.ignoredFont"; //$NON-NLS-1$ public static final String IGNORED_FOREGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.ignoredForegroundColor"; //$NON-NLS-1$ public static final String ADDED_BACKGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.addedBackgroundColor"; //$NON-NLS-1$ public static final String ADDED_FONT = "com.vectrace.mercurialeclipse.ui.colorsandfonts.addedFont"; //$NON-NLS-1$ public static final String ADDED_FOREGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.addedForegroundColor"; //$NON-NLS-1$ public static final String REMOVED_BACKGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.removedBackgroundColor"; //$NON-NLS-1$ public static final String REMOVED_FONT = "com.vectrace.mercurialeclipse.ui.colorsandfonts.removedFont"; //$NON-NLS-1$ public static final String REMOVED_FOREGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.removedForegroundColor"; //$NON-NLS-1$ public static final String CONFLICT_BACKGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.conflictBackgroundColor"; //$NON-NLS-1$ public static final String CONFLICT_FONT = "com.vectrace.mercurialeclipse.ui.colorsandfonts.conflictFont"; //$NON-NLS-1$ public static final String CONFLICT_FOREGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.conflictForegroundColor"; //$NON-NLS-1$ public static final String UNKNOWN_BACKGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.unknownBackgroundColor"; //$NON-NLS-1$ public static final String UNKNOWN_FOREGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.unknownForegroundColor"; //$NON-NLS-1$ public static final String UNKNOWN_FONT = "com.vectrace.mercurialeclipse.ui.colorsandfonts.unknownFont"; //$NON-NLS-1$ public static final String DELETED_BACKGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.deletedBackgroundColor"; //$NON-NLS-1$ public static final String DELETED_FOREGROUND_COLOR = "com.vectrace.mercurialeclipse.ui.colorsandfonts.deletedForegroundColor"; //$NON-NLS-1$ public static final String DELETED_FONT = "com.vectrace.mercurialeclipse.ui.colorsandfonts.deletedFont"; //$NON-NLS-1$ } HistoryPreferencePage.java000066400000000000000000000062031173713500500357130ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Gunnar Ahlberg - implementation * VecTrace (Zingo Andersen) - updateing it * Jérôme Nègre - adding label decorator section * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * This class represents a preference page that is contributed to the Preferences dialog. By sub * classing FieldEditorPreferencePage, we can use the field support built into JFace * that allows us to create a page that is small and knows how to save, restore and apply itself. *

* This page is used to modify preferences only. They are stored in the preference store that * belongs to the main plug-in class. That way, preferences can be accessed directly via the * preference store. */ public class HistoryPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { public HistoryPreferencePage() { super(GRID); setPreferenceStore(MercurialEclipsePlugin.getDefault().getPreferenceStore()); setDescription("Preferences for the Mercurial History View"); //$NON-NLS-1$ } /** * Creates the field editors. Field editors are abstractions of the common GUI blocks needed to * manipulate various types of preferences. Each field editor knows how to save and restore * itself. */ @Override public void createFieldEditors() { addField(new BooleanFieldEditor( MercurialPreferenceConstants.PREF_SIGCHECK_IN_HISTORY, Messages.getString("GeneralPreferencePage.verifyGpgSignaturesInHistoryView"), getFieldEditorParent())); //$NON-NLS-1$ // TODO Temporarily disabled as the font change caused strange UI freezes // addField(SWTWidgetHelper.createFontFieldEditor( // MercurialPreferenceConstants.PREF_HISTORY_MERGE_CHANGESET_FONT, "Merge Changeset Font", getFieldEditorParent(), this, // getPreferenceStore())); addField(SWTWidgetHelper.createColorFieldEditor( MercurialPreferenceConstants.PREF_HISTORY_MERGE_CHANGESET_BACKGROUND, "Merge Changeset Background color", getFieldEditorParent(), this, getPreferenceStore())); addField(SWTWidgetHelper.createColorFieldEditor( MercurialPreferenceConstants.PREF_HISTORY_MERGE_CHANGESET_FOREGROUND, "Merge Changeset Foreground color", getFieldEditorParent(), this, getPreferenceStore())); } public void init(IWorkbench workbench) { } }MercurialPreferenceConstants.java000066400000000000000000000173641173713500500373070ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Gunnar Ahlberg - implementation * Jérôme Nègre - constants are now, well, constant * Bastian Doetsch * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; /** * Constant definitions for plug-in preferences */ public final class MercurialPreferenceConstants { private MercurialPreferenceConstants() { // hide constructor of utility class. } // executables public static final String MERCURIAL_EXECUTABLE = "hg"; //$NON-NLS-1$ public static final String USE_BUILT_IN_HG_EXECUTABLE = "hg.useBuiltInHgExecutable"; //$NON-NLS-1$ public static final String GPG_EXECUTABLE = "hg.gpg.executable"; //$NON-NLS-1$ // user name should be per project in the future, different repositories // could have different names (sub optimal I know but it really could) public static final String MERCURIAL_USERNAME = "user.name"; //$NON-NLS-1$ // label decorator public static final String LABELDECORATOR_LOGIC = "hg.labeldecorator.logic"; //$NON-NLS-1$ public static final String LABELDECORATOR_LOGIC_2MM = "2-means-modified"; //$NON-NLS-1$ public static final String LABELDECORATOR_LOGIC_HB = "high-bit"; //$NON-NLS-1$ public static final String RESOURCE_DECORATOR_SHOW_CHANGESET = "hg.performance.fileShowsChangeset"; //$NON-NLS-1$ public static final String RESOURCE_DECORATOR_SHOW_INCOMING_CHANGESET = "hg.performance.fileShowsChangesetIncoming"; //$NON-NLS-1$ public static final String PREF_DECORATE_WITH_COLORS = "hg.labeldecorator.colors"; //$NON-NLS-1$ public static final String PREF_AUTO_SHARE_PROJECTS = "hg.autoshare"; //$NON-NLS-1$ /** true to automatically include all projects from the repository in the synchronize view */ public static final String PREF_SYNC_ALL_PROJECTS_IN_REPO = "hg.syncAllProjectsInRepository"; //$NON-NLS-1$ public static final String PREF_SYNC_ONLY_CURRENT_BRANCH = "hg.syncOnlyCurrentBranch"; //$NON-NLS-1$ public static final String PREF_SYNC_PRESENTATION_MODE = "hg.syncPresentationMode"; //$NON-NLS-1$ public static final String PREF_SYNC_ENABLE_LOCAL_CHANGESETS = "hg.syncEnableLocalChangesets"; //$NON-NLS-1$ public static final String PREF_ENABLE_SUBREPO_SUPPORT = "enableSubrepoSupport"; //$NON-NLS-1$ /** do not limit graphical log data to show pretty revision graphs in the history view */ public static final String ENABLE_FULL_GLOG = "hg.performance.enableFullGlog"; //$NON-NLS-1$ public static final String PREF_SIGCHECK_IN_HISTORY = Messages.getString("MercurialPreferenceConstants.sigcheck.in.history"); //$NON-NLS-1$ // Timeouts public static final String DEFAULT_TIMEOUT = "hg.timeout.default"; //$NON-NLS-1$ public static final String CLONE_TIMEOUT = "hg.timeout.clone"; //$NON-NLS-1$ public static final String PUSH_TIMEOUT = "hg.timeout.push"; //$NON-NLS-1$ public static final String PULL_TIMEOUT = "hg.timeout.pull"; //$NON-NLS-1$ public static final String UPDATE_TIMEOUT = "hg.timeout.update"; //$NON-NLS-1$ public static final String COMMIT_TIMEOUT = "hg.timeout.commit"; //$NON-NLS-1$ public static final String IMERGE_TIMEOUT = "hg.timeout.imerge"; //$NON-NLS-1$ public static final String LOG_TIMEOUT = "hg.timeout.log"; //$NON-NLS-1$ public static final String STATUS_TIMEOUT = "hg.timeout.status"; //$NON-NLS-1$ public static final String ADD_TIMEOUT = "hg.timeout.add"; //$NON-NLS-1$ public static final String REMOVE_TIMEOUT = "hg.timeout.remove"; //$NON-NLS-1$ // batch sizes public static final String LOG_BATCH_SIZE = "hg.batchsize.log"; //$NON-NLS-1$ public static final String STATUS_BATCH_SIZE = "hg.batchsize.status"; //$NON-NLS-1$ public static final String COMMIT_MESSAGE_BATCH_SIZE = "hg.batchsize.commitmessage"; //$NON-NLS-1$ // remote performance: for incoming/outgoing, compute add/remove/modified status on changeset files public static final String SYNC_COMPUTE_FULL_REMOTE_FILE_STATUS = "hg.computeFullRemoteFileStatus"; //$NON-NLS-1$ // console public static final String PREF_CONSOLE_SHOW_ON_MESSAGE = "hg.console.showOnMessage"; //$NON-NLS-1$ public static final String PREF_CONSOLE_WRAP = "hg.console.wrap"; //$NON-NLS-1$ public static final String PREF_CONSOLE_WIDTH = "hg.console.width"; //$NON-NLS-1$ public static final String PREF_CONSOLE_LIMIT_OUTPUT = "hg.console.limitOutput"; //$NON-NLS-1$ public static final String PREF_CONSOLE_HIGH_WATER_MARK = "hg.console.highWaterMark"; //$NON-NLS-1$ public static final String PREF_CONSOLE_COMMAND_COLOR = "hg.console.command_color"; //$NON-NLS-1$ public static final String PREF_CONSOLE_MESSAGE_COLOR = "hg.console.message_color"; //$NON-NLS-1$ public static final String PREF_CONSOLE_ERROR_COLOR = "hg.console.error_color"; //$NON-NLS-1$ public static final String PREF_CONSOLE_FONT = "hg.console.font"; //$NON-NLS-1$ public static final String PREF_CONSOLE_DEBUG = "hg.console.debug"; //$NON-NLS-1$ public static final String PREF_CONSOLE_DEBUG_TIME = "hg.console.debug.time"; //$NON-NLS-1$ public static final String PREF_CONSOLE_SHOW_ON_STARTUP = "hg.console.showOnStartup"; //$NON-NLS-1$ // merge public static final String PREF_USE_EXTERNAL_MERGE = "hg.merge.useExternal"; //$NON-NLS-1$ // history view public static final String PREF_SHOW_COMMENTS = "pref_show_comments"; //$NON-NLS-1$ public static final String PREF_SHOW_DIFFS = "pref_show_diffs"; //$NON-NLS-1$ /** shows all tags also for file history, even if the file changeset's was not tagged as such */ public static final String PREF_SHOW_ALL_TAGS = "pref_show_alltags"; //$NON-NLS-1$ public static final String PREF_WRAP_COMMENTS = "pref_wrap_comments"; //$NON-NLS-1$ public static final String PREF_SHOW_PATHS = "pref_show_paths"; //$NON-NLS-1$ public static final String PREF_SHOW_GOTO_TEXT = "pref_show_goto_text"; //$NON-NLS-1$ public static final String PREF_AFFECTED_PATHS_LAYOUT = "pref_affected_paths_layout2"; //$NON-NLS-1$ public static final int LAYOUT_HORIZONTAL = 1; public static final int LAYOUT_VERTICAL = 2; public static final String PREF_HISTORY_MERGE_CHANGESET_BACKGROUND = "hg.history.mergeChangesetsBackground"; public static final String PREF_HISTORY_MERGE_CHANGESET_FOREGROUND = "hg.history.mergeChangesetsForeground"; public static final String PREF_USE_MERCURIAL_USERNAME = "hg.useMercurialUsernameForCommit"; public static final String PREF_DEFAULT_REBASE_KEEP_BRANCHES = "hg.defaulRebaseKeepBranches"; public static final String PREF_DEFAULT_TRANSPLANT_FROM_LOCAL_BRANCHES = "hg.defaulTransplantFromLocal"; // clone public static final String PREF_CLONE_UNCOMPRESSED = "hg.cloneUncompressed"; //$NON-NLS-1$ // push public static final String PREF_PUSH_NEW_BRANCH = "hg.pushNewBranch"; //$NON-NLS-1$ // dialogs public static final String PREF_SHOW_MULTIPLE_PROJECTS_DIALOG = "hg.showMultipleProjectsDialog"; public static final String PREF_SHOW_PULL_WARNING_DIALOG = "hg.showPullWarningDialog"; public static final String PREF_PRESELECT_UNTRACKED_IN_COMMIT_DIALOG = "hg.dialog.commit.preSelectUntracked"; public static final String PREF_SHOW_MERGE_CONFICT_NOTIFICATION_DIALOG = "hg.showMergeConflictNotificationDialog"; public static final String PREF_SHOW_REBASE_CONFICT_NOTIFICATION_DIALOG = "hg.showRebaseConflictNotificationDialog"; public static final String PREF_SHOW_QFINISH_WARNING_DIALOG = "hg.showQFinishWarning"; // security public static final String PREF_VERIFY_SERVER_CERTIFICATE = "hg.verifyServerCertificate"; //$NON-NLS-1$ } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/Messages.java000066400000000000000000000021371173713500500333060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.preferences.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } PerformancePreferencePage.java000066400000000000000000000106521173713500500365160ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Gunnar Ahlberg - implementation * VecTrace (Zingo Andersen) - updateing it * Jérôme Nègre - adding label decorator section * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * This class represents a preference page that is contributed to the * Preferences dialog. By sub classing FieldEditorPreferencePage, * we can use the field support built into JFace that allows us to create a page * that is small and knows how to save, restore and apply itself. *

* This page is used to modify preferences only. They are stored in the * preference store that belongs to the main plug-in class. That way, * preferences can be accessed directly via the preference store. */ public class PerformancePreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { private BooleanFieldEditor showIncomingInfo; public PerformancePreferencePage() { super(GRID); setPreferenceStore(MercurialEclipsePlugin.getDefault() .getPreferenceStore()); setDescription(Messages.getString("PerformancePreferencePage.description")); //$NON-NLS-1$ } /** * Creates the field editors. Field editors are abstractions of the common * GUI blocks needed to manipulate various types of preferences. Each field * editor knows how to save and restore itself. */ @Override public void createFieldEditors() { // batch size preferences IntegerFieldEditor batchLogRevisionEditor = new IntegerFieldEditor( LOG_BATCH_SIZE, Messages.getString("PerformancePreferencePage.field.revisionLimit"), getFieldEditorParent()); //$NON-NLS-1$ addField(batchLogRevisionEditor); batchLogRevisionEditor.setValidRange(1, Integer.MAX_VALUE); IntegerFieldEditor batchStatusSeditor = new IntegerFieldEditor( STATUS_BATCH_SIZE, Messages.getString("PerformancePreferencePage.field.statusBatchSize"), //$NON-NLS-1$ getFieldEditorParent()); addField(batchStatusSeditor); batchStatusSeditor.setValidRange(1, Integer.MAX_VALUE); addField(new BooleanFieldEditor( ENABLE_FULL_GLOG, Messages.getString("PerformancePreferencePage.field.enableFullGlog"), //$NON-NLS-1$ getFieldEditorParent())); addField(new BooleanFieldEditor( PREF_ENABLE_SUBREPO_SUPPORT, Messages.getString("PerformancePreferencePage.field.enableSubrepo"), //$NON-NLS-1$ getFieldEditorParent())); // for incoming/outgoing, compute add/remove/modified status on changeset files addField(new BooleanFieldEditor( SYNC_COMPUTE_FULL_REMOTE_FILE_STATUS, Messages.getString("PerformancePreferencePage.field.computeFullStatus"), //$NON-NLS-1$ getFieldEditorParent())); final BooleanFieldEditor showChangesetsInfo = new BooleanFieldEditor( RESOURCE_DECORATOR_SHOW_CHANGESET, Messages.getString("PerformancePreferencePage.field.showChangesetOnFiles"), //$NON-NLS-1$ getFieldEditorParent()){ @Override protected void fireStateChanged(String property, boolean oldValue, boolean newValue) { super.fireStateChanged(property, oldValue, newValue); if(oldValue != newValue){ showIncomingInfo.setEnabled(getBooleanValue(), getFieldEditorParent()); } } }; addField(showChangesetsInfo); showIncomingInfo = new BooleanFieldEditor( RESOURCE_DECORATOR_SHOW_INCOMING_CHANGESET, Messages.getString("PerformancePreferencePage.field.showIncomingChangesetOnFiles"), //$NON-NLS-1$ getFieldEditorParent()); addField(showIncomingInfo); } public void init(IWorkbench workbench) { } }PreferenceInitializer.java000066400000000000000000000222471173713500500357460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Jérôme Nègre - adding label decorator section * Stefan C - Code cleanup * Andrei Loskutov - bug fixes * Zsolt Koppany (intland) - bug fixes * Philip Graf - use default timeout from preferences *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import java.io.File; import java.io.IOException; import java.net.URL; import java.util.StringTokenizer; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.preference.IPreferenceStore; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.synchronize.PresentationMode; import com.vectrace.MercurialEclipse.team.MercurialUtilities; /** * Class used to initialize default preference values. */ public class PreferenceInitializer extends AbstractPreferenceInitializer { private static final boolean IS_WINDOWS = MercurialUtilities.isWindows(); @Override public void initializeDefaultPreferences() { final IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); // per default, we use exact the executable we have (if any) on board store.setDefault(USE_BUILT_IN_HG_EXECUTABLE, true); // try to find out, IF we have the built-in hg executable detectAndSetHgExecutable(store); store.setDefault(PREF_AUTO_SHARE_PROJECTS, true); store.setDefault(PREF_SYNC_ALL_PROJECTS_IN_REPO, true); store.setDefault(PREF_SYNC_ONLY_CURRENT_BRANCH, true); store.setDefault(PREF_SYNC_PRESENTATION_MODE, PresentationMode.COMPRESSED_TREE.name()); store.setDefault(PREF_SYNC_ENABLE_LOCAL_CHANGESETS, false); // currently this reduces performance 2x => so disable per default store.setDefault(PREF_ENABLE_SUBREPO_SUPPORT, false); // "Highest" importance should be default, like "merge conflict" // when having 2 different statuses in a folder it should have the more important one store.setDefault(LABELDECORATOR_LOGIC, LABELDECORATOR_LOGIC_HB); store.setDefault(RESOURCE_DECORATOR_SHOW_CHANGESET, false); store.setDefault(RESOURCE_DECORATOR_SHOW_INCOMING_CHANGESET, false); store.setDefault(SYNC_COMPUTE_FULL_REMOTE_FILE_STATUS, true); store.setDefault(LOG_BATCH_SIZE, 500); store.setDefault(STATUS_BATCH_SIZE, 10); store.setDefault(COMMIT_MESSAGE_BATCH_SIZE, 10); store.setDefault(ENABLE_FULL_GLOG, true); // blue store.setDefault(PREF_CONSOLE_COMMAND_COLOR, "0,0,255"); // black store.setDefault(PREF_CONSOLE_MESSAGE_COLOR, "0,0,0"); // red store.setDefault(PREF_CONSOLE_ERROR_COLOR, "255,0,0"); store.setDefault(PREF_CONSOLE_SHOW_ON_STARTUP, false); store.setDefault(PREF_CONSOLE_LIMIT_OUTPUT, true); store.setDefault(PREF_CONSOLE_HIGH_WATER_MARK, 100000); store.setDefault(PREF_DECORATE_WITH_COLORS, true); store.setDefault(PREF_SHOW_COMMENTS, true); store.setDefault(PREF_SHOW_PATHS, true); // See issue #13662: do not show diffs per default: they may cause OOM on huge changesets store.setDefault(PREF_SHOW_DIFFS, false); store.setDefault(PREF_SHOW_ALL_TAGS, false); store.setDefault(PREF_SHOW_GOTO_TEXT, true); store.setDefault(PREF_AFFECTED_PATHS_LAYOUT, LAYOUT_HORIZONTAL); store.setDefault(PREF_SIGCHECK_IN_HISTORY, false); store.setDefault(PREF_HISTORY_MERGE_CHANGESET_BACKGROUND, "255,210,210"); store.setDefault(PREF_HISTORY_MERGE_CHANGESET_FOREGROUND, "0,0,0"); int defaultTimeout = TimeoutPreferencePage.DEFAULT_TIMEOUT; store.setDefault(DEFAULT_TIMEOUT, defaultTimeout); // remote operations are always longer than local store.setDefault(CLONE_TIMEOUT, defaultTimeout * 10); store.setDefault(PUSH_TIMEOUT, defaultTimeout * 10); store.setDefault(PULL_TIMEOUT, defaultTimeout * 10); store.setDefault(UPDATE_TIMEOUT, defaultTimeout); store.setDefault(COMMIT_TIMEOUT, defaultTimeout); store.setDefault(IMERGE_TIMEOUT, defaultTimeout); store.setDefault(LOG_TIMEOUT, defaultTimeout); store.setDefault(STATUS_TIMEOUT, defaultTimeout); store.setDefault(ADD_TIMEOUT, defaultTimeout); store.setDefault(REMOVE_TIMEOUT, defaultTimeout); String defaultUsername = store.getDefaultString(MERCURIAL_USERNAME); if(defaultUsername == null || defaultUsername.length() == 0) { // the task below may block UI thread and cause entire system to wait forever // therefore start job execution. // The preference key is only used as a cache by MercurialUtilities.getDefaultUserName() and // it is useful to show on the preference page. // Possibly relevant: http://www.javaforge.com/issue/20425 Job job = new Job("Detecting hg user name") { @Override protected IStatus run(IProgressMonitor monitor) { store.setDefault(MERCURIAL_USERNAME, MercurialUtilities.getDefaultUserName()); return Status.OK_STATUS; } }; job.setPriority(Job.LONG); job.setSystem(true); job.schedule(200); } store.setDefault(PREF_USE_MERCURIAL_USERNAME, false); store.setDefault(PREF_DEFAULT_REBASE_KEEP_BRANCHES, false); store.setDefault(PREF_USE_EXTERNAL_MERGE, false); store.setDefault(PREF_DEFAULT_TRANSPLANT_FROM_LOCAL_BRANCHES, false); store.setDefault(PREF_CLONE_UNCOMPRESSED, false); store.setDefault(PREF_PRESELECT_UNTRACKED_IN_COMMIT_DIALOG, false); store.setDefault(PREF_VERIFY_SERVER_CERTIFICATE, true); store.setDefault(PREF_SHOW_PULL_WARNING_DIALOG, MessageDialogWithToggle.PROMPT); store.setDefault(PREF_SHOW_MULTIPLE_PROJECTS_DIALOG, MessageDialogWithToggle.PROMPT); store.setDefault(PREF_SHOW_MERGE_CONFICT_NOTIFICATION_DIALOG, MessageDialogWithToggle.PROMPT); store.setDefault(PREF_SHOW_REBASE_CONFICT_NOTIFICATION_DIALOG, MessageDialogWithToggle.PROMPT); store.setDefault(PREF_SHOW_QFINISH_WARNING_DIALOG, MessageDialogWithToggle.PROMPT); } private static File checkForPossibleHgExecutables() { File hgExecutable = null; String envPath = System.getenv("PATH"); if (envPath != null) { String pathSeparator = String.valueOf(File.pathSeparatorChar); String execSuffix = IS_WINDOWS ? ".exe" : ""; for (StringTokenizer st = new StringTokenizer(envPath, pathSeparator, false); st.hasMoreElements(); ) { String execPath = st.nextToken() + "/hg" + execSuffix; File file = new File(execPath); if (file.isFile()) { hgExecutable = file; break; } } } if (hgExecutable == null && !IS_WINDOWS) { String extraPath[] = { "/usr/bin/hg", "/usr/local/bin/hg", // default on MacOS "/opt/local/bin/hg", // if installed via MacPorts }; for (String fileName : extraPath) { File file = new File(fileName); if (file.isFile()) { hgExecutable = file; break; } } } return hgExecutable; } private static void detectAndSetHgExecutable(IPreferenceStore store) { // Currently only tested on Windows. The binary is expected to be found // at "os\win32\x86\hg.exe" (relative to the plugin/fragment directory) File hgExecutable = getIntegratedHgExecutable(); String defaultExecPath; String existingValue = store.getString(MERCURIAL_EXECUTABLE); if (hgExecutable == null) { hgExecutable = checkForPossibleHgExecutables(); } if (hgExecutable == null) { defaultExecPath = "hg"; if(existingValue != null && !new File(existingValue).isFile()){ store.setValue(MERCURIAL_EXECUTABLE, defaultExecPath); } } else { defaultExecPath = hgExecutable.getPath(); if (store.getBoolean(USE_BUILT_IN_HG_EXECUTABLE) || (existingValue == null || !new File(existingValue).isFile())) { store.setValue(MERCURIAL_EXECUTABLE, defaultExecPath); } } store.setDefault(MERCURIAL_EXECUTABLE, defaultExecPath); } /** * @return an full absolute path to the embedded hg executable from the (fragment) * plugin. This path is guaranteed to point to an existing file. Returns null * if the file cannot be found, does not exists or is not a file at all. */ public static File getIntegratedHgExecutable(){ IPath path = IS_WINDOWS ? new Path("$os$/hg.exe") : new Path("$os$/hg"); URL url = FileLocator.find(MercurialEclipsePlugin.getDefault().getBundle(), path, null); if(url == null) { return null; } try { url = FileLocator.toFileURL(url); File execFile = new File(url.getPath()); if (execFile.isFile()) { return execFile.getAbsoluteFile(); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } return null; } } SynchronizePreferencePage.java000066400000000000000000000036461173713500500365750ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; public class SynchronizePreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { public SynchronizePreferencePage() { super(GRID); setPreferenceStore(MercurialEclipsePlugin.getDefault().getPreferenceStore()); setDescription(Messages.getString("SynchronizePreferencePage.description")); //$NON-NLS-1$ } public void init(IWorkbench workbench) { // noop } @Override public void createFieldEditors() { addField(new BooleanFieldEditor( PREF_SYNC_ONLY_CURRENT_BRANCH, Messages.getString("SynchronizePreferencePage.syncOnlyCurrentBranch"), //$NON-NLS-1$ getFieldEditorParent())); addField(new BooleanFieldEditor( PREF_SYNC_ENABLE_LOCAL_CHANGESETS, Messages.getString("SynchronizePreferencePage.syncEnableLocalChangeSets"), //$NON-NLS-1$ getFieldEditorParent())); addField(new BooleanFieldEditor( PREF_SYNC_ALL_PROJECTS_IN_REPO, Messages.getString("SynchronizePreferencePage.syncAllProjectsInRepo"), //$NON-NLS-1$ getFieldEditorParent())); } }TimeoutPreferencePage.java000066400000000000000000000115111173713500500356760ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferences/******************************************************************************* * Copyright (c) 2006-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Gunnar Ahlberg - implementation * VecTrace (Zingo Andersen) - updateing it * Jérôme Nègre - adding label decorator section * Stefan C - Code cleanup * Andrei Loskutov - bug fixes * Philip Graf - added default timeout text field *******************************************************************************/ package com.vectrace.MercurialEclipse.preferences; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * This class represents a preference page that is contributed to the * Preferences dialog. By sub classing FieldEditorPreferencePage, * we can use the field support built into JFace that allows us to create a page * that is small and knows how to save, restore and apply itself. *

* This page is used to modify preferences only. They are stored in the * preference store that belongs to the main plug-in class. That way, * preferences can be accessed directly via the preference store. */ public class TimeoutPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage { // Default is 6 minutes. Don't ask why 6... because it is 7 times smaller than 42? public static final int DEFAULT_TIMEOUT = 6 * 60 * 1000; private static final class TimeoutFieldEditor extends IntegerFieldEditor { private TimeoutFieldEditor(String name, String labelText, Composite parent) { super(name, labelText, parent); } @Override public void load() { super.load(); if (getIntValue() <= 0) { super.setPresentsDefaultValue(true); super.setStringValue(String.valueOf(DEFAULT_TIMEOUT)); } } } public TimeoutPreferencePage() { super(GRID); setPreferenceStore(MercurialEclipsePlugin.getDefault() .getPreferenceStore()); setDescription(Messages.getString("TimeoutPreferencePage.description")); //$NON-NLS-1$ } /** * Creates the field editors. Field editors are abstractions of the common * GUI blocks needed to manipulate various types of preferences. Each field * editor knows how to save and restore itself. */ @Override public void createFieldEditors() { // timeout preferences addField(new TimeoutFieldEditor( MercurialPreferenceConstants.DEFAULT_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.default"), getFieldEditorParent())); //$NON-NLS-1$ addField(new TimeoutFieldEditor( MercurialPreferenceConstants.CLONE_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.clone"), getFieldEditorParent())); //$NON-NLS-1$ addField(new TimeoutFieldEditor( MercurialPreferenceConstants.PUSH_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.push"), //$NON-NLS-1$ getFieldEditorParent())); addField(new TimeoutFieldEditor( MercurialPreferenceConstants.PULL_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.pull"), getFieldEditorParent())); //$NON-NLS-1$ addField(new TimeoutFieldEditor( MercurialPreferenceConstants.UPDATE_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.update"), getFieldEditorParent())); //$NON-NLS-1$ addField(new TimeoutFieldEditor( MercurialPreferenceConstants.COMMIT_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.commit"), getFieldEditorParent())); //$NON-NLS-1$ addField(new TimeoutFieldEditor( MercurialPreferenceConstants.IMERGE_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.imerge"), getFieldEditorParent())); //$NON-NLS-1$ addField(new TimeoutFieldEditor( MercurialPreferenceConstants.LOG_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.log"), getFieldEditorParent())); //$NON-NLS-1$ addField(new TimeoutFieldEditor( MercurialPreferenceConstants.STATUS_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.status"), getFieldEditorParent())); //$NON-NLS-1$ addField(new TimeoutFieldEditor( MercurialPreferenceConstants.ADD_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.add"), //$NON-NLS-1$ getFieldEditorParent())); addField(new TimeoutFieldEditor( MercurialPreferenceConstants.REMOVE_TIMEOUT, Messages.getString("TimeoutPreferencePage.field.remove"), getFieldEditorParent())); //$NON-NLS-1$ } public void init(IWorkbench workbench) { } }messages.properties000066400000000000000000000077651173713500500345560ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/preferencesConsolePreferencesPage.cmdColor=Command color GeneralPreferencePage.preselectUntrackedInCommitDialog=Preselect untracked files in commit dialog ConsolePreferencesPage.colorPrefs=Console color preferences ConsolePreferencesPage.consoleWidth=Console width ConsolePreferencesPage.errorColor=Error color ConsolePreferencesPage.header=Console preferences ConsolePreferencesPage.limitOutput=Limit output ConsolePreferencesPage.msgColor=Message color ConsolePreferencesPage.numberChars=Number of characters ConsolePreferencesPage.showAllHgMsg=Show all Mercurial messages (debug mode) ConsolePreferencesPage.showCommandExecutionTime=Show command execution time ConsolePreferencesPage.showConsoleOnMsg=Show console on message ConsolePreferencesPage.wrapText=Wrap text PerformancePreferencePage.description=Performance settings PerformancePreferencePage.field.revisionLimit=Number of revisions to get with one hg log call PerformancePreferencePage.field.statusBatchSize=Maximal number of files to query hg status with PerformancePreferencePage.field.enableSubrepo=Enable experimental subrepositories support (moderate) PerformancePreferencePage.field.computeFullStatus=Compute full file status for outgoing/incoming files (slow) PerformancePreferencePage.field.enableFullGlog=Fetch all required data for the history view graph (moderate) PerformancePreferencePage.field.showChangesetOnFiles=Show changeset information for files (slow) PerformancePreferencePage.field.showIncomingChangesetOnFiles=Show incoming changeset information for files (very slow) GeneralPreferencePage.autoshare=Automatically associate MercurialEclipse with new projects containing a Mercurial repository GeneralPreferencePage.description=MercurialEclipse plugin for the Mercurial (Hg) version control system GeneralPreferencePage.field.hgExecutable=Mercurial &Executable: GeneralPreferencePage.enableFontAndColorDecorations=Enable font and color decorations GeneralPreferencePage.error.HgNotInstalled=Mercurial is not correctly installed. GeneralPreferencePage.field.gpgExecutable=&GnuPG Executable: GeneralPreferencePage.field.username=Default &User Name: GeneralPreferencePage.field.decorationGroup.description=When a folder contains files with different statuses, flag the folder: GeneralPreferencePage.field.decorationGroup.asModified=as modified GeneralPreferencePage.field.decorationGroup.mostImportant=with the most important status GeneralPreferencePage.useExternalMergeTool=Use external merge tool for resolving conflicts GeneralPreferencePage.pushNewBranches=Allow pushing new branches (always uses --new-branch flag) GeneralPreferencePage.field.commitMessageBatchSize=Commit messages to save: GeneralPreferencePage.verifyGpgSignaturesInHistoryView=Verify GPG signatures in History view GeneralPreferencePage.verifyServerCertificate=Verify HTTPS server certificate GeneralPreferencePage.optionDisabled=(Option disabled due the unsupported hg version) SynchronizePreferencePage.description=Preferences for the Mercurial Synchronize View SynchronizePreferencePage.syncOnlyCurrentBranch=Synchronize only the current branch SynchronizePreferencePage.syncAllProjectsInRepo=Always synchronize all projects contained in the repository SynchronizePreferencePage.syncEnableLocalChangeSets=Enable local changesets (grouping of uncommitted changes) MercurialPreferenceConstants.sigcheck.in.history=hg.gpg.sigcheck.history TimeoutPreferencePage.description=Configuration page for Mercurial timeouts TimeoutPreferencePage.field.clone=Clone timeout (ms): TimeoutPreferencePage.field.push=Push timeout (ms): TimeoutPreferencePage.field.pull=Pull/Incoming/Outgoing timeout (ms): TimeoutPreferencePage.field.update=Update timeout (ms): TimeoutPreferencePage.field.commit=Commit timeout (ms): TimeoutPreferencePage.field.imerge=Imerge timeout (ms): TimeoutPreferencePage.field.log=Log/GraphLog timeout (ms): TimeoutPreferencePage.field.status=Status timeout (ms): TimeoutPreferencePage.field.add=Add timeout (ms): TimeoutPreferencePage.field.remove=Remove timeout (ms): TimeoutPreferencePage.field.default=Default timeout (ms): eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/properties/000077500000000000000000000000001173713500500305645ustar00rootroot00000000000000DoNotDisplayMe.java000066400000000000000000000016531173713500500342100ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/properties/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.properties; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Put this annotation to the method which shouldn't be shown in the Properties view * (per default, all public "is/get/has" methods with zero arguments are shown). * * @author andrei */ @Retention(RetentionPolicy.RUNTIME) public @interface DoNotDisplayMe { } GenericPropertySource.java000066400000000000000000000122011173713500500356460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/properties/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.properties; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.Platform; import org.eclipse.ui.views.properties.IPropertyDescriptor; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.PropertyDescriptor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * Allows to show ANY object inside Properties view by introspecting it's public getters. * * @author andrei */ public class GenericPropertySource implements IPropertySource { private static final PropPageTitleProvider LABEL_PROVIDER = new PropPageTitleProvider(); private final Object object; private final IPropertyDescriptor[] propertyDescriptors; public GenericPropertySource(Object object) { this.object = object; List props = new ArrayList(); if (object.getClass().isArray()) { Object[] arr = (Object[]) object; for (Object aobject : arr) { if (aobject != null) { props.add(new PropertyDescriptor(aobject, aobject.getClass().getSimpleName())); } } } else if (Collection.class.isAssignableFrom(object.getClass())) { Collection arr = (Collection) object; for (Object aobject : arr) { if (aobject != null) { props.add(new PropertyDescriptor(aobject, aobject.getClass().getSimpleName())); } } } else { List getters = getGetters(object); for (Method method : getters) { Object descriptorId = method; // for collections and arrays we want to start another level in the tree Class returnType = method.getReturnType(); if (isArrayOrCollection(returnType)) { Object value = getDescriptorFromReturnValue(object, method); if(value != null) { descriptorId = value; } } props.add(new PropertyDescriptor(descriptorId, getReadableName(method))); } } propertyDescriptors = props.toArray(new PropertyDescriptor[0]); } public IPropertyDescriptor[] getPropertyDescriptors() { return propertyDescriptors; } public Object getPropertyValue(Object obj) { if (obj instanceof Method) { try { obj = ((Method) obj).invoke(object, (Object[]) null); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } if (obj == null) { return null; } } if (isArrayOrCollection(obj.getClass())) { return new GenericPropertySource(obj); } if (obj instanceof IPropertySource) { return obj; } Object adapter = Platform.getAdapterManager().getAdapter(obj, IPropertySource.class); if (adapter != null) { return adapter; } return "" + obj; } /** * Overridden to get "value" column filled also for complex types with children * {@inheritDoc} */ public Object getEditableValue() { String text = LABEL_PROVIDER.getText(object); return text == null ? "" : text; } public boolean isPropertySet(Object id) { return false; } public void resetPropertyValue(Object id) { // } public void setPropertyValue(Object id, Object value) { // } private static boolean isArrayOrCollection(Class type) { return type.isArray() || Collection.class.isAssignableFrom(type); } private static String getReadableName(Method method) { String name = method.getName(); return (name.startsWith("get") || name.startsWith("has")) ? name.substring(3) : name .startsWith("is") ? name.substring(2) : name; } private static List getGetters(Object obj) { List methodList = new ArrayList(); Set methodNames = new HashSet(); Method[] methods = obj.getClass().getMethods(); for (Method method : methods) { if (method.getParameterTypes().length == 0) { String name = method.getName(); if (methodNames.contains(name)) { // to prevent overridden methods appear multiple times continue; } if ((name.startsWith("get") || name.startsWith("is") || name.startsWith("has")) && (!name.equals("getClass") && !name.equals("hashCode"))) { methodNames.add(name); DoNotDisplayMe annotation = method.getAnnotation(DoNotDisplayMe.class); if (annotation == null) { methodList.add(method); } } } } return methodList; } private static Object getDescriptorFromReturnValue(Object instance, Method method) { try { Object result = method.invoke(instance, (Object[]) null); if(result != null) { return new GenericPropertySource(result); } } catch (Exception e) { MercurialEclipsePlugin.logError( "GenericPropertySource: method invication failed", e); } return null; } }OpenPropertiesAction.java000066400000000000000000000034451173713500500354720ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/properties/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.properties; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * Show details on a selected mercurial model object. */ public class OpenPropertiesAction implements IObjectActionDelegate { private IWorkbenchPart targetPart; public OpenPropertiesAction() { super(); } public OpenPropertiesAction(IWorkbenchPart targetPart) { super(); this.targetPart = targetPart; } public final void setActivePart(final IAction action, final IWorkbenchPart targetPart) { this.targetPart = targetPart; } public final void selectionChanged(final IAction action, final ISelection newSelection) { // noop } public final void run(final IAction action) { try { if (targetPart == null) { MercurialEclipsePlugin.getActivePage().showView(IPageLayout.ID_PROP_SHEET); } else { targetPart.getSite().getPage().showView(IPageLayout.ID_PROP_SHEET); } } catch (PartInitException e) { MercurialEclipsePlugin.logError("Failed to show properties view", e); } finally { targetPart = null; } } } PropPageTitleProvider.java000066400000000000000000000056251173713500500356120ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/properties/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.properties; import java.util.Collection; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.graphics.Image; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.Tag; /** * Label provider used to represent some mercurial objects in the properties view * @author andrei */ public class PropPageTitleProvider implements ILabelProvider { public void addListener(ILabelProviderListener listener) { // noop } public void dispose() { // noop } public boolean isLabelProperty(Object element, String property) { return true; } public void removeListener(ILabelProviderListener listener) { // noop } public Image getImage(Object element) { return null; } public String getText(Object element) { if(element instanceof IStructuredSelection) { IStructuredSelection selection = (IStructuredSelection) element; element = selection.getFirstElement(); } if(element instanceof MercurialRevision) { MercurialRevision revision = (MercurialRevision) element; return "Revision " + revision.getRevision() + " of " + revision.getName(); } if(element instanceof FileStatus) { FileStatus status = (FileStatus) element; return status.getRootRelativePath().lastSegment(); } if(element instanceof Tag) { Tag tag = (Tag) element; return tag.getName(); } if(element instanceof ChangeSet) { ChangeSet cs = (ChangeSet) element; return cs.getName(); } if(element instanceof FileFromChangeSet) { FileFromChangeSet fcs = (FileFromChangeSet) element; IPath path = fcs.getPath(); if(path != null) { return path.toOSString(); } return fcs.toString(); } if(element == null) { return null; } if(element.getClass().isArray()) { int length = ((Object[])element).length; return length > 0? "" + length : ""; } if(Collection.class.isAssignableFrom(element.getClass())) { int length = ((Collection)element).size(); return length > 0? "" + length : ""; } return element.getClass().getSimpleName(); } } PropertyPageAdapterFactory.java000066400000000000000000000051561173713500500366310ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/properties/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.properties; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.team.ui.history.IHistoryView; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.IPropertySource; import org.eclipse.ui.views.properties.PropertySheetPage; import com.vectrace.MercurialEclipse.history.MercurialHistoryPage; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.Tag; import com.vectrace.MercurialEclipse.synchronize.cs.ChangesetGroup; /** * Factory adapting our model for Property page * * @author andrei */ public class PropertyPageAdapterFactory implements IAdapterFactory { /* Disabled tabbed property view support - right now this is overkill. * see also plugin.xml private static class MercurialPropertySheetPage extends TabbedPropertySheetPage { static ITabbedPropertySheetPageContributor contributor = new ITabbedPropertySheetPageContributor() { public String getContributorId() { return MercurialHistoryPage.class.getName(); } }; public MercurialPropertySheetPage() { super(contributor); } } */ public Object getAdapter(Object adaptable, Class adapterType) { if (adapterType == IPropertySource.class) { if (adaptable instanceof MercurialRevision || adaptable instanceof FileStatus || adaptable instanceof FileFromChangeSet || adaptable instanceof ChangeSet || adaptable instanceof ChangesetGroup || adaptable instanceof Tag) { return new GenericPropertySource(adaptable); } } if (adapterType == IPropertySheetPage.class) { if (adaptable instanceof IHistoryView && ((IHistoryView) adaptable).getHistoryPage() instanceof MercurialHistoryPage) { return new /*Mercurial*/PropertySheetPage(); } } return null; } public Class[] getAdapterList() { return new Class[] { IPropertySource.class, IPropertySheetPage.class }; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/000077500000000000000000000000001173713500500306075ustar00rootroot00000000000000IRepositoryListener.java000066400000000000000000000020621173713500500353710ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptation ******************************************************************************/ package com.vectrace.MercurialEclipse.repository; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; /** * Listener for repositories. events fired when repository added, removed or changed */ public interface IRepositoryListener { void repositoryAdded(IHgRepositoryLocation root); void repositoryModified(IHgRepositoryLocation root); void repositoryRemoved(IHgRepositoryLocation root); void repositoriesChanged(IHgRepositoryLocation[] roots); } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/Messages.java000066400000000000000000000021351173713500500332220ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.repository; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.repository.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } RepoPropertiesPage.java000066400000000000000000000113651173713500500351600ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.repository; import java.io.IOException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceStore; import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IWorkbenchPropertyPage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocation; /** * Properties page for hg repository, which allows to change some basic properties like login * name/password etc */ public class RepoPropertiesPage extends FieldEditorPreferencePage implements IWorkbenchPropertyPage { private static final String KEY_LNAME = "lname"; private static final String KEY_LOCATION = "location"; private static final String KEY_LOGIN_NAME = "name"; private static final String KEY_LOGIN_PWD = "pwd"; private IAdaptable adaptable; public RepoPropertiesPage() { super(GRID); PreferenceStore store = new PreferenceStore() { @Override public void save() throws IOException { internalSave(); } }; setPreferenceStore(store); } protected void internalSave() { if (adaptable == null) { return; } IHgRepositoryLocation adapter = (IHgRepositoryLocation) adaptable .getAdapter(IHgRepositoryLocation.class); if (!(adapter instanceof HgRepositoryLocation)) { return; } HgRepositoryLocation repo = (HgRepositoryLocation) adapter; IPreferenceStore store = getPreferenceStore(); String user = store.getString(KEY_LOGIN_NAME); String pwd = store.getString(KEY_LOGIN_PWD); String lname = store.getString(KEY_LNAME); try { adaptable = MercurialEclipsePlugin.getRepoManager().updateRepoLocation(null, repo.getLocation(), lname, user, pwd); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } // as selection is not updated in the view, simply copy new data to the old one repo.setUser(user); repo.setPassword(pwd); repo.setLogicalName(lname); } @Override protected Control createContents(Composite parent) { return super.createContents(parent); } @Override protected void createFieldEditors() { IHgRepositoryLocation location = getLocation(); boolean editable = location != null && !location.isLocal(); StringFieldEditor locationEditor = new StringFieldEditor(KEY_LOCATION, "Location", getFieldEditorParent()); addField(locationEditor); locationEditor.getTextControl(getFieldEditorParent()).setEditable(false); StringFieldEditor logicalNameEditor = new StringFieldEditor(KEY_LNAME, "Logical Name", getFieldEditorParent()); addField(logicalNameEditor); logicalNameEditor.getTextControl(getFieldEditorParent()).setEditable(editable); StringFieldEditor nameEditor = new StringFieldEditor(KEY_LOGIN_NAME, "Login", getFieldEditorParent()); addField(nameEditor); nameEditor.getTextControl(getFieldEditorParent()).setEditable(editable); StringFieldEditor pwdEditor = new StringFieldEditor(KEY_LOGIN_PWD, "Password", getFieldEditorParent()); pwdEditor.getTextControl(getFieldEditorParent()).setEchoChar('*'); pwdEditor.getTextControl(getFieldEditorParent()).setEditable(editable); addField(pwdEditor); } public IAdaptable getElement() { return adaptable; } private IHgRepositoryLocation getLocation() { if (adaptable == null) { return null; } return (IHgRepositoryLocation) adaptable.getAdapter(IHgRepositoryLocation.class); } public void setElement(IAdaptable element) { this.adaptable = element; IHgRepositoryLocation repo = getLocation(); if (repo == null) { return; } IPreferenceStore store = getPreferenceStore(); if (repo.getUser() != null) { store.setDefault(KEY_LOGIN_NAME, repo.getUser()); } if (repo.getPassword() != null) { store.setDefault(KEY_LOGIN_PWD, repo.getPassword()); } if (repo.getLocation() != null) { store.setDefault(KEY_LOCATION, repo.getLocation()); } if (repo.getLogicalName() != null) { store.setDefault(KEY_LNAME, repo.getLogicalName()); } } } RepositoriesView.java000066400000000000000000000446651173713500500347340ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.repository; import java.util.Iterator; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.IActionBars; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.actions.SelectionProviderAction; import org.eclipse.ui.internal.dialogs.PropertyDialog; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.ui.part.DrillDownAdapter; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgInitClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgPath; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.repository.actions.RemoveRootAction; import com.vectrace.MercurialEclipse.repository.model.AllRootsElement; import com.vectrace.MercurialEclipse.repository.model.RemoteContentProvider; import com.vectrace.MercurialEclipse.ui.HgProjectPropertyPage; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.wizards.CloneRepoWizard; import com.vectrace.MercurialEclipse.wizards.ImportProjectsFromRepoWizard; import com.vectrace.MercurialEclipse.wizards.NewLocationWizard; /** * RepositoriesView is a view on a set of known Hg repositories */ public class RepositoriesView extends ViewPart implements ISelectionListener { private final class InitAction extends Action { private final Shell shell; private InitAction(String text, ImageDescriptor image, Shell shell) { super(text, image); this.shell = shell; } @Override public void run() { IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); if(selection.size() != 1 || !(selection.getFirstElement() instanceof IHgRepositoryLocation)){ return; } final IHgRepositoryLocation repo = (IHgRepositoryLocation) selection.getFirstElement(); final String [] initResult = new String[]{""}; Job job = new Job("Init for " + repo.toString()) { @Override protected IStatus run(IProgressMonitor monitor) { try { initResult[0] = HgInitClient.init(repo); } catch (HgException e) { initResult[0] = e.getMessage(); MercurialEclipsePlugin.logError(e); return e.getStatus(); } return Status.OK_STATUS; } }; job.addJobChangeListener(new JobChangeAdapter() { @Override public void done(final IJobChangeEvent event) { Display.getDefault().asyncExec(new Runnable() { public void run() { String message; if (event.getResult().isOK()) { message = "Hg init for repository '" + repo.toString() + "' was successful!"; } else { message = "Hg init for repository '" + repo.toString() + "' failed!"; } if (initResult[0] != null && initResult[0].length() > 0) { message += "\nHg said: " + initResult[0]; } MessageDialog.openInformation(shell, "Hg init result", message); } }); } }); IWorkbenchSiteProgressService service = (IWorkbenchSiteProgressService) getSite() .getService(IWorkbenchSiteProgressService.class); service.schedule(job); } } public static final String VIEW_ID = "com.vectrace.MercurialEclipse.repository.RepositoriesView"; //$NON-NLS-1$ // The root private AllRootsElement root; // Actions private Action newAction; private RemoveRootAction removeRootAction; // The tree viewer protected TreeViewer treeViewer; // Drill down adapter private DrillDownAdapter drillPart; // Home, back, and "drill into" private Action refreshAction; private Action refreshPopupAction; private Action collapseAllAction; private Action propertiesAction; private Action cloneAction; private RemoteContentProvider contentProvider; /** this listener is used when a repository is added, removed or changed */ private final IRepositoryListener repositoryListener = new IRepositoryListener() { public void repositoryAdded(final IHgRepositoryLocation loc) { refresh(loc); } public void repositoryRemoved(IHgRepositoryLocation loc) { refresh(null); } public void repositoriesChanged(IHgRepositoryLocation[] roots) { refresh(null); } private void refresh(final Object object) { Display display = getViewer().getControl().getDisplay(); display.asyncExec(new Runnable() { public void run() { refreshViewer(object, false); } }); } public void repositoryModified(IHgRepositoryLocation loc) { refresh(null); } }; private Action importAction; private Action initAction; public RepositoriesView() { super(); } /** * Contribute actions to the view */ protected void contributeActions() { final Shell shell = getShell(); // Create actions // New Repository (popup) newAction = new Action(Messages.getString("RepositoriesView.createRepo"), MercurialEclipsePlugin //$NON-NLS-1$ .getImageDescriptor("wizards/newlocation_wiz.gif")) { //$NON-NLS-1$ @Override public void run() { NewLocationWizard wizard = new NewLocationWizard(); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.open(); } }; // Clone Repository (popup) cloneAction = new Action(Messages.getString("RepositoriesView.cloneRepo"), MercurialEclipsePlugin //$NON-NLS-1$ .getImageDescriptor("clone_repo.gif")) { //$NON-NLS-1$ @Override public void run() { IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); CloneRepoWizard wizard = new CloneRepoWizard(); wizard.init(PlatformUI.getWorkbench(), selection); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.open(); } }; // Init Repository (popup) initAction = new InitAction(Messages.getString("RepositoriesView.initRepo"), MercurialEclipsePlugin //$NON-NLS-1$ .getImageDescriptor("release_rls.gif"), shell); // Import project (popup) importAction = new Action(Messages.getString("RepositoriesView.importProject"), MercurialEclipsePlugin.getImageDescriptor("import_project.gif")) { //$NON-NLS-1$ @Override public void run() { IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); ImportProjectsFromRepoWizard wizard = new ImportProjectsFromRepoWizard(); wizard.init(PlatformUI.getWorkbench(), selection); WizardDialog dialog = new WizardDialog(shell, wizard); dialog.open(); } }; // Properties propertiesAction = new SelectionProviderAction(treeViewer, "Properties") { @Override public void run() { IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); if(selection.isEmpty()){ return; } Object firstElement = selection.getFirstElement(); PreferenceDialog dialog = createDialog(firstElement); if (dialog != null) { dialog.open(); } if(!selection.isEmpty()) { treeViewer.refresh(firstElement); } } public PreferenceDialog createDialog(Object element) { String initialPageId = null; if(element instanceof IProject){ initialPageId = HgProjectPropertyPage.ID; } return PropertyDialog.createDialogOn(shell, initialPageId, element); } }; IActionBars bars = getViewSite().getActionBars(); bars.setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), propertiesAction); IStructuredSelection selection = (IStructuredSelection) getViewer().getSelection(); if (selection.size() == 1) { propertiesAction.setEnabled(true); } else { propertiesAction.setEnabled(false); } getViewer().addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection ss = (IStructuredSelection) event.getSelection(); propertiesAction.setEnabled(ss.size() == 1); } }); // Remove Root removeRootAction = new RemoveRootAction(treeViewer.getControl().getShell()); removeRootAction.selectionChanged((IStructuredSelection) null); bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), removeRootAction); // Refresh action (toolbar) refreshAction = new Action(Messages.getString("RepositoriesView.refreshRepos"), //$NON-NLS-1$ MercurialEclipsePlugin.getImageDescriptor("elcl16/refresh.gif")) { //$NON-NLS-1$ @Override public void run() { refreshViewer(null, true); } }; refreshAction.setToolTipText(Messages.getString("RepositoriesView.refresh")); //$NON-NLS-1$ refreshAction.setDisabledImageDescriptor(MercurialEclipsePlugin .getImageDescriptor("dlcl16/refresh.gif")); //$NON-NLS-1$ refreshAction.setHoverImageDescriptor(MercurialEclipsePlugin .getImageDescriptor("clcl16/refresh.gif")); //$NON-NLS-1$ getViewSite().getActionBars().setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction); refreshPopupAction = new Action( Messages.getString("RepositoriesView.refresh"), MercurialEclipsePlugin //$NON-NLS-1$ .getImageDescriptor("clcl16/refresh.gif")) { //$NON-NLS-1$ @Override public void run() { refreshViewerNode(); } }; // Collapse action collapseAllAction = new Action(Messages.getString("RepositoriesView.collapseAll"), //$NON-NLS-1$ MercurialEclipsePlugin.getImageDescriptor("elcl16/collapseall.gif")) { //$NON-NLS-1$ @Override public void run() { collapseAll(); } }; collapseAllAction.setToolTipText(Messages.getString("RepositoriesView.collapseAll")); //$NON-NLS-1$ collapseAllAction.setHoverImageDescriptor(MercurialEclipsePlugin .getImageDescriptor("clcl16/collapseall.gif")); //$NON-NLS-1$ // Create the popup menu MenuManager menuMgr = new MenuManager(); Tree tree = treeViewer.getTree(); Menu menu = menuMgr.createContextMenu(tree); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { addWorkbenchActions(manager); } }); menuMgr.setRemoveAllWhenShown(true); tree.setMenu(menu); getSite().registerContextMenu(menuMgr, treeViewer); // Create the local tool bar IToolBarManager tbm = bars.getToolBarManager(); IMenuManager mm = bars.getMenuManager(); drillPart.addNavigationActions(tbm); drillPart.addNavigationActions(mm); tbm.add(new Separator()); mm.add(new Separator()); tbm.add(newAction); mm.add(newAction); tbm.add(refreshAction); mm.add(refreshAction); tbm.add(new Separator()); mm.add(new Separator()); tbm.add(collapseAllAction); mm.add(collapseAllAction); tbm.update(false); mm.update(false); bars.updateActionBars(); } protected void addWorkbenchActions(IMenuManager manager) { IStructuredSelection selection = (IStructuredSelection) getViewer().getSelection(); // File actions go first (view file) manager.add(new Separator(IWorkbenchActionConstants.GROUP_FILE)); // Misc additions manager.add(new Separator("historyGroup")); //$NON-NLS-1$ manager.add(new Separator("checkoutGroup")); //$NON-NLS-1$ manager.add(new Separator("exportImportGroup")); //$NON-NLS-1$ boolean singleFile = selection.size() == 1 && selection.getFirstElement() instanceof HgPath; if(singleFile) { HgPath path = (HgPath) selection.getFirstElement(); if(path.isDirectory()) { manager.add(importAction); } } manager.add(new Separator("miscGroup")); //$NON-NLS-1$ boolean singleRepoSelected = selection.size() == 1 && selection.getFirstElement() instanceof IHgRepositoryLocation; if(singleRepoSelected){ manager.add(cloneAction); IHgRepositoryLocation repo = (IHgRepositoryLocation) selection.getFirstElement(); if(!repo.isLocal() && repo.getLocation().startsWith("ssh:")) { manager.add(initAction); } manager.add(refreshPopupAction); } removeRootAction.selectionChanged(selection); if (removeRootAction.isEnabled()) { manager.add(removeRootAction); } manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); if (selection.size() == 1) { manager.add(propertiesAction); } } @Override public void createPartControl(Composite parent) { treeViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); contentProvider = new RemoteContentProvider(); treeViewer.setContentProvider(contentProvider); treeViewer.setLabelProvider(WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider()); root = new AllRootsElement(); treeViewer.setInput(root); treeViewer.setSorter(new RepositorySorter()); drillPart = new DrillDownAdapter(treeViewer); contributeActions(); initializeListeners(); MercurialEclipsePlugin.getRepoManager().addRepositoryListener(repositoryListener); getSite().setSelectionProvider(treeViewer); } protected void initializeListeners() { getSite().getWorkbenchWindow().getSelectionService() .addPostSelectionListener(this); treeViewer.addSelectionChangedListener(removeRootAction); // when F5 is pressed, refresh this view treeViewer.getControl().addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent event) { if (event.keyCode == SWT.F5) { refreshAction.run(); } } }); treeViewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent e) { handleDoubleClick(e); } }); } public void selectionChanged(IWorkbenchPart part, ISelection selection) { String msg = getStatusLineMessage(selection); getViewSite().getActionBars().getStatusLineManager().setMessage(msg); } /** * When selection is changed we update the status line */ private String getStatusLineMessage(ISelection selection) { if (!(selection instanceof IStructuredSelection) || selection.isEmpty()) { return ""; //$NON-NLS-1$ } IStructuredSelection s = (IStructuredSelection) selection; if (s.size() > 1) { return String.valueOf(s.size()) + Messages.getString("RepositoriesView.multiSelected"); //$NON-NLS-1$ } return Messages.getString("RepositoriesView.oneSelected"); //$NON-NLS-1$ } @Override public void setFocus() { treeViewer.getControl().setFocus(); } protected Shell getShell() { return treeViewer.getTree().getShell(); } public TreeViewer getViewer() { return treeViewer; } /** * this is called whenever a new repository location is added for example or * when user wants to refresh */ public void refreshViewer(Object object, boolean refreshRepositoriesFolders) { if (treeViewer == null || treeViewer.getControl() == null || treeViewer.getControl().isDisposed()) { return; } if (refreshRepositoriesFolders) { try { MercurialEclipsePlugin.getRepoManager().refreshRepositories(null); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } treeViewer.refresh(); if(object != null) { treeViewer.setSelection(new StructuredSelection(object), true); } } @SuppressWarnings("rawtypes") protected void refreshViewerNode() { IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection(); Iterator iter = selection.iterator(); while (iter.hasNext()) { Object object = iter.next(); if (object instanceof IHgRepositoryLocation) { refreshAction.run(); break; } treeViewer.refresh(object); } } public void collapseAll() { if (treeViewer == null) { return; } treeViewer.getControl().setRedraw(false); treeViewer.collapseToLevel(treeViewer.getInput(), AbstractTreeViewer.ALL_LEVELS); treeViewer.getControl().setRedraw(true); } /** * The mouse has been double-clicked in the tree, perform appropriate * behaviour. */ private void handleDoubleClick(DoubleClickEvent e) { // Only act on single selection ISelection selection = e.getSelection(); if (!(selection instanceof IStructuredSelection)) { return; } IStructuredSelection structured = (IStructuredSelection) selection; if (structured.size() != 1) { return; } Object firstElement = structured.getFirstElement(); IResource resource = ResourceUtils.getResource(firstElement); if (resource != null && resource.exists() && resource.getType() == IResource.FILE) { ResourceUtils.openEditor(null, (IFile) resource); return; } propertiesAction.run(); } @Override public void dispose() { MercurialEclipsePlugin.getRepoManager().removeRepositoryListener(repositoryListener); super.dispose(); treeViewer = null; } } RepositoryComparator.java000066400000000000000000000021501173713500500356000ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/******************************************************************************* * Copyright (c) 2005, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptation ******************************************************************************/ package com.vectrace.MercurialEclipse.repository; import java.util.Comparator; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; /** * This class allows to sort IHgRepositoryLoction's alphabetically using the URL * or the label (if set). The case of the strings is ignored. */ public class RepositoryComparator implements Comparator { public int compare(IHgRepositoryLocation o1, IHgRepositoryLocation o2) { return o1.getLocation().compareToIgnoreCase(o2.getLocation()); } }RepositorySorter.java000066400000000000000000000021441173713500500347520ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/******************************************************************************* * Copyright (c) 2005, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptation ******************************************************************************/ package com.vectrace.MercurialEclipse.repository; import org.eclipse.jface.viewers.ViewerSorter; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; public class RepositorySorter extends ViewerSorter { private static final int REPO_ROOT_CATEGORY = 1; /* (non-Javadoc) * @see org.eclipse.jface.viewers.ViewerSorter#category(java.lang.Object) */ @Override public int category(Object element) { if (element instanceof IHgRepositoryLocation) { return REPO_ROOT_CATEGORY; } return 0; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/actions/000077500000000000000000000000001173713500500322475ustar00rootroot00000000000000RemoveRootAction.java000066400000000000000000000053501173713500500362750ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/actions/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.repository.actions; import java.util.ArrayList; import java.util.Iterator; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.actions.SelectionListenerAction; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; /** * RemoveRootAction removes a repository */ public class RemoveRootAction extends SelectionListenerAction { private IStructuredSelection selection; public RemoveRootAction(Shell shell) { super("Remove"); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("rem_co.gif")); } /** * Returns the selected remote files */ @SuppressWarnings("unchecked") protected IHgRepositoryLocation[] getSelectedRemoteRoots() { ArrayList resources = new ArrayList(); if (selection != null && !selection.isEmpty()) { Iterator elements = selection.iterator(); while (elements.hasNext()) { Object next = MercurialEclipsePlugin.getAdapter(elements.next(), IHgRepositoryLocation.class); if (next instanceof IHgRepositoryLocation) { resources.add((IHgRepositoryLocation) next); } } } return resources.toArray(new IHgRepositoryLocation[resources.size()]); } @Override public void run() { IHgRepositoryLocation[] roots = getSelectedRemoteRoots(); if (roots.length == 0) { return; } boolean confirm = MessageDialog.openConfirm(null, "Mercurial Repositories", "Remove repository (all authentication data will be lost)?"); if(!confirm){ return; } for (IHgRepositoryLocation repo : roots) { MercurialEclipsePlugin.getRepoManager().disposeRepository(repo); } } /** * updates the selection. this selection will be used during run returns * true if action can be enabled */ @Override protected boolean updateSelection(IStructuredSelection sel) { this.selection = sel; IHgRepositoryLocation[] roots = getSelectedRemoteRoots(); return roots.length > 0; } } messages.properties000066400000000000000000000006511173713500500344570ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repositoryRepositoriesView.collapseAll=Collapse All RepositoriesView.createRepo=Create Repository... RepositoriesView.cloneRepo=Clone Repository... RepositoriesView.initRepo=Init Repository RepositoriesView.importProject=Import as Project... RepositoriesView.multiSelected=\ selected. RepositoriesView.new=New RepositoriesView.oneSelected=1 selected. RepositoriesView.refresh=Refresh RepositoriesView.refreshRepos=Refresh Repositories eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/model/000077500000000000000000000000001173713500500317075ustar00rootroot00000000000000AllRootsElement.java000066400000000000000000000063021173713500500355450ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/model/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.repository.model; import java.util.Collection; import java.util.Iterator; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.model.IWorkbenchAdapter; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; /** * AllRootsElement is the model element for the repositories view. * Its children are the array of all known repository roots. * * Because we extend IAdaptable, we don't need to register this adapter */ public class AllRootsElement implements IWorkbenchAdapter, IAdaptable { public AllRootsElement() { super(); } public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { if (adapter == IWorkbenchAdapter.class) { return this; } return null; } /** * Return non null array with all known local and remote repositories * @param o ignored */ public IHgRepositoryLocation[] getChildren(Object o) { HgRepositoryLocationManager repoManager = MercurialEclipsePlugin.getRepoManager(); Collection repoLocations = repoManager.getAllRepoLocations(); Collection hgRoots = MercurialRootCache.getInstance().getKnownHgRoots(); // remove local repos which are known as hg roots for (IHgRepositoryLocation hgRoot : hgRoots) { Iterator iterator = repoLocations.iterator(); while (iterator.hasNext()) { IHgRepositoryLocation repoLoc = iterator.next(); if(repoLoc.equals(hgRoot)){ iterator.remove(); } } } // remove roots which have default repos set for (IHgRepositoryLocation repo : repoLocations) { Iterator iterator = hgRoots.iterator(); while (iterator.hasNext()) { HgRoot hgRoot = iterator.next(); if(repo.equals(repoManager.getDefaultRepoLocation(hgRoot))){ iterator.remove(); } } } IHgRepositoryLocation [] result = new IHgRepositoryLocation[repoLocations.size() + hgRoots.size()]; System.arraycopy(repoLocations.toArray(), 0, result, 0, repoLocations.size()); System.arraycopy(hgRoots.toArray(), 0, result, repoLocations.size(), hgRoots.size()); return result; } public ImageDescriptor getImageDescriptor(Object object) { return null; } public String getLabel(Object o) { return null; } public Object getParent(Object o) { return null; } } RemoteContentProvider.java000066400000000000000000000056611173713500500370040ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/repository/model/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.repository.model; import java.util.ArrayList; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.progress.DeferredTreeContentManager; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; /** * Extension to the generic workbench content provider mechanism to lazily * determine whether an element has children. That is, children for an element * aren't fetched until the user clicks on the tree expansion box. */ public class RemoteContentProvider extends WorkbenchContentProvider { private DeferredTreeContentManager manager; @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (viewer instanceof AbstractTreeViewer) { manager = new DeferredTreeContentManager(this, (AbstractTreeViewer) viewer); } super.inputChanged(viewer, oldInput, newInput); } @Override public boolean hasChildren(Object element) { if (element == null) { return false; } if (manager != null) { if (manager.isDeferredAdapter(element)) { return manager.mayHaveChildren(element); } } return super.hasChildren(element); } @SuppressWarnings("unchecked") @Override public Object[] getChildren(Object parentElement) { if (manager != null) { Object[] children = manager.getChildren(parentElement); if (children != null) { if (parentElement instanceof IHgRepositoryLocation) { ArrayList childrenArray = new ArrayList(); for (int i = 0; i < children.length; i++) { childrenArray.add(children[i]); } children = new Object[childrenArray.size()]; childrenArray.toArray(children); } // This will be a placeholder to indicate // that the real children are being fetched return children; } } return super.getChildren(parentElement); } public void cancelJobs(IHgRepositoryLocation[] roots) { if (manager != null) { for (int i = 0; i < roots.length; i++) { IHgRepositoryLocation root = roots[i]; cancelJobs(root); } } } /** * Cancel any jobs that are fetching content from the given location. * * @param location */ public void cancelJobs(IHgRepositoryLocation location) { if (manager != null) { manager.cancel(location); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/000077500000000000000000000000001173713500500276355ustar00rootroot00000000000000DecoratingMercurialTextSearchLabelProvider.java000066400000000000000000000074071173713500500410220ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Bastian Doetsch - adaptation for MercurialEclipses *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import org.eclipse.jface.preference.JFacePreferences; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.ViewerColumn; import org.eclipse.jface.viewers.StyledString.Styler; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbenchPreferenceConstants; import org.eclipse.ui.PlatformUI; public class DecoratingMercurialTextSearchLabelProvider extends DecoratingStyledCellLabelProvider implements IPropertyChangeListener, ILabelProvider { private static final String HIGHLIGHT_BG_COLOR_NAME= "org.eclipse.jdt.ui.ColoredLabels.match_highlight"; //$NON-NLS-1$ public static final Styler HIGHLIGHT_STYLE= StyledString.createColorRegistryStyler(null, HIGHLIGHT_BG_COLOR_NAME); public DecoratingMercurialTextSearchLabelProvider( MercurialTextSearchTreeLabelProvider provider) { super(provider, PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator(), null); } @Override public void initialize(ColumnViewer viewer, ViewerColumn column) { PlatformUI.getPreferenceStore().addPropertyChangeListener(this); JFaceResources.getColorRegistry().addListener(this); setOwnerDrawEnabled(showColoredLabels()); super.initialize(viewer, column); } @Override public void dispose() { super.dispose(); PlatformUI.getPreferenceStore().removePropertyChangeListener(this); JFaceResources.getColorRegistry().removeListener(this); } private void refresh() { ColumnViewer viewer= getViewer(); if (viewer == null) { return; } boolean showColoredLabels= showColoredLabels(); if (showColoredLabels != isOwnerDrawEnabled()) { setOwnerDrawEnabled(showColoredLabels); viewer.refresh(); } else if (showColoredLabels) { viewer.refresh(); } } @Override protected StyleRange prepareStyleRange(StyleRange styleRange, boolean applyColors) { if (!applyColors && styleRange.background != null) { styleRange= super.prepareStyleRange(styleRange, applyColors); styleRange.borderStyle= SWT.BORDER_DOT; return styleRange; } return super.prepareStyleRange(styleRange, applyColors); } public static boolean showColoredLabels() { return PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.USE_COLORED_LABELS); } public void propertyChange(PropertyChangeEvent event) { String property= event.getProperty(); if (property.equals(JFacePreferences.QUALIFIER_COLOR) || property.equals(JFacePreferences.COUNTER_COLOR) || property.equals(JFacePreferences.DECORATIONS_COLOR) || property.equals(HIGHLIGHT_BG_COLOR_NAME) || property.equals(IWorkbenchPreferenceConstants.USE_COLORED_LABELS)) { Display.getDefault().asyncExec(new Runnable() { public void run() { refresh(); } }); } } public String getText(Object element) { return getStyledText(element).getString(); } } IMercurialTextSearchContentProvider.java000066400000000000000000000003671173713500500375240ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/searchpackage com.vectrace.MercurialEclipse.search; import org.eclipse.jface.viewers.IContentProvider; public interface IMercurialTextSearchContentProvider extends IContentProvider { void elementsChanged(Object[] updatedElements); void clear(); }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/MercurialMatch.java000066400000000000000000000057751173713500500334160ustar00rootroot00000000000000package com.vectrace.MercurialEclipse.search; import org.eclipse.core.resources.IFile; import org.eclipse.jface.text.Region; import org.eclipse.search.ui.text.Match; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; public class MercurialMatch extends Match { private int rev = -1; private int lineNumber; private String extract; private MercurialRevisionStorage mercurialRevisionStorage; private Region originalLocation; private IFile file; private boolean becomesMatch; /** * @param matchRequestor */ public MercurialMatch(MercurialTextSearchMatchAccess ma) { super(ma.getMercurialRevisionStorage(), -1, -1); this.rev = ma.getRev(); this.lineNumber = ma.getLineNumber(); this.extract = ma.getExtract(); this.mercurialRevisionStorage = ma.getMercurialRevisionStorage(); this.becomesMatch = ma.isBecomesMatch(); this.file = ma.getFile(); } /** * @param file */ public MercurialMatch(IFile file) { super(file, -1, -1); this.file = file; } @Override public void setOffset(int offset) { if (originalLocation == null) { // remember the original location before changing it originalLocation = new Region(getOffset(), getLength()); } super.setOffset(offset); } @Override public void setLength(int length) { if (originalLocation == null) { // remember the original location before changing it originalLocation = new Region(getOffset(), getLength()); } super.setLength(length); } public int getOriginalOffset() { if (originalLocation != null) { return originalLocation.getOffset(); } return getOffset(); } public int getOriginalLength() { if (originalLocation != null) { return originalLocation.getLength(); } return getLength(); } public IFile getFile() { return file; } public boolean isFileSearch() { return lineNumber == 0; } public Region getOriginalLocation() { return originalLocation; } public void setOriginalLocation(Region originalLocation) { this.originalLocation = originalLocation; } public int getRev() { return rev; } public int getLineNumber() { return lineNumber; } public String getExtract() { return extract; } public MercurialRevisionStorage getMercurialRevisionStorage() { return mercurialRevisionStorage; } public void setFile(IFile file) { this.file = file; } public void setRev(int rev) { this.rev = rev; } public void setLineNumber(int lineNumber) { this.lineNumber = lineNumber; } public void setExtract(String extract) { this.extract = extract; } public void setMercurialRevisionStorage( MercurialRevisionStorage mercurialRevisionStorage) { this.mercurialRevisionStorage = mercurialRevisionStorage; } @Override public int getOffset() { // TODO Auto-generated method stub return super.getOffset(); } /** * @return the becomesMatch */ public boolean isBecomesMatch() { return becomesMatch; } /** * @param becomesMatch the becomesMatch to set */ public void setBecomesMatch(boolean becomesMatch) { this.becomesMatch = becomesMatch; } } MercurialTextSearchEngine.java000066400000000000000000000031121173713500500354620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.search.core.text.TextSearchEngine; import org.eclipse.search.core.text.TextSearchRequestor; import org.eclipse.search.core.text.TextSearchScope; /** * @author Bastian * */ public class MercurialTextSearchEngine extends TextSearchEngine { public MercurialTextSearchEngine() { } @Override public IStatus search(TextSearchScope scope, TextSearchRequestor requestor, Pattern searchPattern, IProgressMonitor monitor) { // do all the work in the visitor return new MercurialTextSearchVisitor(requestor, searchPattern).search( (MercurialTextSearchScope) scope, monitor); } @Override public IStatus search(IFile[] scope, TextSearchRequestor requestor, Pattern searchPattern, IProgressMonitor monitor) { // do all the work in the visitor return new MercurialTextSearchVisitor(requestor, searchPattern).search( scope, monitor); } } MercurialTextSearchMatchAccess.java000066400000000000000000000147241173713500500364460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian - implementation * Philip Graf - Fixed bugs which FindBugs found *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Path; import org.eclipse.search.core.text.TextSearchMatchAccess; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Bastian * */ public class MercurialTextSearchMatchAccess extends TextSearchMatchAccess { private final HgRoot root; private int rev; private int lineNumber; private String user; private String date; private IFile file; private boolean becomesMatch = true; private final String extract; private String fileContent; private MercurialRevisionStorage mercurialRevisionStorage; /** * Expects a line like filename:rev:linenumber:-|+:username:date * * @param line * @throws HgException */ public MercurialTextSearchMatchAccess(HgRoot root, String line, boolean all) throws HgException { this.root = root; try { String[] split = line.trim().split(":"); int i=0; Path path = new Path(root.getAbsolutePath() + File.separator + split[i++]); this.file = ResourceUtils.getFileHandle(path); this.rev = Integer.parseInt(split[i++]); this.lineNumber = Integer.parseInt(split[i++]); if (all) { this.becomesMatch = !"-".equals(split[i++]); } this.user = split[i++]; this.extract = split[i++]; } catch (Exception e) { // result is not correctly formed or the line is not a search result entry throw new HgException("Failed to parse search result", e); } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (becomesMatch ? 1231 : 1237); result = prime * result + ((date == null) ? 0 : date.hashCode()); result = prime * result + ((file == null) ? 0 : file.hashCode()); result = prime * result + lineNumber; result = prime * result + rev; result = prime * result + ((user == null) ? 0 : user.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } MercurialTextSearchMatchAccess other = (MercurialTextSearchMatchAccess) obj; if (becomesMatch != other.becomesMatch) { return false; } if (date == null) { if (other.date != null) { return false; } } else if (!date.equals(other.date)) { return false; } if (file == null) { if (other.file != null) { return false; } } else if (!file.getFullPath().equals(other.file.getFullPath())) { return false; } if (lineNumber != other.lineNumber) { return false; } if (rev != other.rev) { return false; } if (user == null) { if (other.user != null) { return false; } } else if (!user.equals(other.user)) { return false; } return true; } public int getRev() { return rev; } public void setRev(int rev) { this.rev = rev; } public int getLineNumber() { return lineNumber; } public void setLineNumber(int lineNumber) { this.lineNumber = lineNumber; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } @Override public IFile getFile() { return file; } public void setFile(IFile file) { this.file = file; } public boolean isBecomesMatch() { return becomesMatch; } public void setBecomesMatch(boolean becomesMatch) { this.becomesMatch = becomesMatch; } @Override public String getFileContent(int offset, int length) { String sub = getFileContent(); if (sub.length() > 0) { return sub.substring(offset, offset + length); } return ""; } /** * @return * */ private String getFileContent() { if (fileContent == null) { getMercurialRevisionStorage(); BufferedReader reader = null; try { InputStream is = mercurialRevisionStorage.getContents(); if (is != null) { StringBuilder sb = new StringBuilder(); String line; reader = new BufferedReader( new InputStreamReader(is, root.getEncoding())); while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } this.fileContent = sb.toString(); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { } } } if (fileContent == null) { fileContent = ""; } return fileContent; } @Override public char getFileContentChar(int offset) { String sub = getFileContent(offset, 1); if (sub != null && sub.length() > 0) { return sub.charAt(0); } return ' '; } @Override public int getFileContentLength() { return getFileContent().length(); } @Override public int getMatchLength() { return extract.length(); } @Override public int getMatchOffset() { return getFileContent().indexOf(extract); } public HgRoot getRoot() { return root; } public String getExtract() { return extract; } public void setFileContent(String fileContent) { this.fileContent = fileContent; } public MercurialRevisionStorage getMercurialRevisionStorage() { if (mercurialRevisionStorage == null) { mercurialRevisionStorage = new MercurialRevisionStorage(file, rev); } return mercurialRevisionStorage; } public void setMercurialRevisionStorage( MercurialRevisionStorage mercurialRevisionStorage) { this.mercurialRevisionStorage = mercurialRevisionStorage; } } MercurialTextSearchPage.java000066400000000000000000000604031173713500500351370ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Juerg Billeter, juergbi@ethz.ch - 47136 Search view should show match objects * Ulrich Etter, etteru@ethz.ch - 47136 Search view should show match objects * Roman Fuchs, fuchsro@ethz.ch - 47136 Search view should show match objects * Bastian Doetsch - adaptation for MercurialEclipse * Andrei Loskutov - bug fixes * Philip Graf - Fixed bugs which FindBugs found *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.regex.PatternSyntaxException; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.fieldassist.ComboContentAdapter; import org.eclipse.jface.resource.JFaceColors; import org.eclipse.jface.text.FindReplaceDocumentAdapterContentProposalProvider; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.search.internal.core.text.PatternConstructor; import org.eclipse.search.internal.ui.SearchMessages; import org.eclipse.search.internal.ui.SearchPlugin; import org.eclipse.search.internal.ui.util.FileTypeEditor; import org.eclipse.search.internal.ui.util.SWTUtil; import org.eclipse.search.ui.ISearchPage; import org.eclipse.search.ui.ISearchPageContainer; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.NewSearchUI; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.StringUtils; @SuppressWarnings("restriction") public class MercurialTextSearchPage extends DialogPage implements ISearchPage { private static final int HISTORY_SIZE = 12; public static final String EXTENSION_POINT_ID = "org.eclipse.search.internal.ui.text.TextSearchPage"; //$NON-NLS-1$ private static final boolean IS_REGEX_SEARCH = true; // Dialog store id constants private static final String PAGE_NAME = "TextSearchPage"; //$NON-NLS-1$ private static final String STORE_HISTORY = "HISTORY"; //$NON-NLS-1$ private static final String STORE_HISTORY_SIZE = "HISTORY_SIZE"; //$NON-NLS-1$ private final List fPreviousSearchPatterns = new ArrayList( 20); private boolean fFirstTime = true; private Combo fPattern; private Combo fExtensions; private CLabel fStatusLabel; private ISearchPageContainer fContainer; private FileTypeEditor fFileTypeEditor; private ContentAssistCommandAdapter fPatterFieldContentAssist; private Button firstRevisionCheckbox; private static class SearchPatternData { public final boolean isCaseSensitive; public final boolean isRegExSearch; public final String textPattern; public final String[] fileNamePatterns; public final int scope; public final IWorkingSet[] workingSets; public SearchPatternData(String textPattern, boolean isCaseSensitive, boolean isRegExSearch, String[] fileNamePatterns, int scope, IWorkingSet[] workingSets) { Assert.isNotNull(fileNamePatterns); this.isCaseSensitive = isCaseSensitive; this.isRegExSearch = isRegExSearch; this.textPattern = textPattern; this.fileNamePatterns = fileNamePatterns; this.scope = scope; this.workingSets = workingSets; // can be null } public void store(IDialogSettings settings) { settings.put("ignoreCase", !isCaseSensitive); //$NON-NLS-1$ settings.put("isRegExSearch", isRegExSearch); //$NON-NLS-1$ settings.put("textPattern", textPattern); //$NON-NLS-1$ settings.put("fileNamePatterns", fileNamePatterns); //$NON-NLS-1$ settings.put("scope", scope); //$NON-NLS-1$ if (workingSets != null) { String[] wsIds = new String[workingSets.length]; for (int i = 0; i < workingSets.length; i++) { wsIds[i] = workingSets[i].getLabel(); } settings.put("workingSets", wsIds); //$NON-NLS-1$ } else { settings.put("workingSets", new String[0]); //$NON-NLS-1$ } } public static SearchPatternData create(IDialogSettings settings) { String textPattern = settings.get("textPattern"); //$NON-NLS-1$ String[] wsIds = settings.getArray("workingSets"); //$NON-NLS-1$ IWorkingSet[] workingSets = null; if (wsIds != null && wsIds.length > 0) { IWorkingSetManager workingSetManager = PlatformUI.getWorkbench() .getWorkingSetManager(); workingSets = new IWorkingSet[wsIds.length]; for (int i = 0; workingSets != null && i < wsIds.length; i++) { workingSets[i] = workingSetManager.getWorkingSet(wsIds[i]); if (workingSets[i] == null) { workingSets = null; } } } String[] fileNamePatterns = settings.getArray("fileNamePatterns"); //$NON-NLS-1$ if (fileNamePatterns == null) { fileNamePatterns = new String[0]; } try { int scope = settings.getInt("scope"); //$NON-NLS-1$ boolean isRegExSearch = settings.getBoolean("isRegExSearch"); //$NON-NLS-1$ boolean ignoreCase = settings.getBoolean("ignoreCase"); //$NON-NLS-1$ return new SearchPatternData(textPattern, !ignoreCase, isRegExSearch, fileNamePatterns, scope, workingSets); } catch (NumberFormatException e) { return null; } } } static class TextSearchPageInput { private final String fSearchText; private final MercurialTextSearchScope fScope; public TextSearchPageInput(String searchText, MercurialTextSearchScope scope) { fSearchText = searchText; fScope = scope; } public String getSearchText() { return fSearchText; } public MercurialTextSearchScope getScope() { return fScope; } } // ---- Action Handling ------------------------------------------------ private ISearchQuery newQuery() { SearchPatternData data = getPatternData(); TextSearchPageInput input = new TextSearchPageInput(data.textPattern, createTextSearchScope()); return new MercurialTextSearchQueryProvider(firstRevisionCheckbox.getSelection()) .createQuery(input); } public boolean performAction() { NewSearchUI.runQueryInBackground(newQuery()); return true; } private String getPattern() { return fPattern.getText(); } public MercurialTextSearchScope createTextSearchScope() { // Setup search scope switch (getContainer().getSelectedScope()) { case ISearchPageContainer.WORKSPACE_SCOPE: return MercurialTextSearchScope.newWorkspaceScope(getExtensions(), firstRevisionCheckbox.getSelection()); case ISearchPageContainer.SELECTION_SCOPE: return getSelectedResourcesScope(); case ISearchPageContainer.SELECTED_PROJECTS_SCOPE: return getEnclosingProjectScope(); case ISearchPageContainer.WORKING_SET_SCOPE: IWorkingSet[] workingSets = getContainer().getSelectedWorkingSets(); return MercurialTextSearchScope.newSearchScope(workingSets, getExtensions(), firstRevisionCheckbox.getSelection()); default: // unknown scope return MercurialTextSearchScope.newWorkspaceScope(getExtensions(), firstRevisionCheckbox.getSelection()); } } private MercurialTextSearchScope getSelectedResourcesScope() { HashSet resources = new HashSet(); ISelection sel = getContainer().getSelection(); if (sel instanceof IStructuredSelection && !sel.isEmpty()) { Iterator iter = ((IStructuredSelection) sel).iterator(); while (iter.hasNext()) { Object curr = iter.next(); if (curr instanceof IWorkingSet) { IWorkingSet workingSet = (IWorkingSet) curr; if (workingSet.isAggregateWorkingSet() && workingSet.isEmpty()) { return MercurialTextSearchScope.newWorkspaceScope(getExtensions(), firstRevisionCheckbox.getSelection()); } IAdaptable[] elements = workingSet.getElements(); for (int i = 0; i < elements.length; i++) { IResource resource = (IResource) elements[i].getAdapter(IResource.class); if (resource != null && resource.isAccessible()) { resources.add(resource); } } } else if (curr instanceof IAdaptable) { IResource resource = (IResource) ((IAdaptable) curr) .getAdapter(IResource.class); if (resource != null && resource.isAccessible()) { resources.add(resource); } } } } IResource[] arr = resources.toArray(new IResource[resources.size()]); return MercurialTextSearchScope.newSearchScope(arr, getExtensions(), firstRevisionCheckbox .getSelection()); } private MercurialTextSearchScope getEnclosingProjectScope() { String[] enclosingProjectName = getContainer().getSelectedProjectNames(); if (enclosingProjectName == null) { return MercurialTextSearchScope.newWorkspaceScope(getExtensions(), firstRevisionCheckbox.getSelection()); } IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IResource[] res = new IResource[enclosingProjectName.length]; for (int i = 0; i < res.length; i++) { res[i] = root.getProject(enclosingProjectName[i]); } return MercurialTextSearchScope.newSearchScope(res, getExtensions(), firstRevisionCheckbox .getSelection()); } private SearchPatternData findInPrevious(String pattern) { for (Iterator iter = fPreviousSearchPatterns.iterator(); iter.hasNext();) { SearchPatternData element = iter.next(); if (pattern.equals(element.textPattern)) { return element; } } return null; } /** * Return search pattern data and update previous searches. An existing entry will be updated. * * @return the search pattern data */ private SearchPatternData getPatternData() { SearchPatternData match = findInPrevious(fPattern.getText()); if (match != null) { fPreviousSearchPatterns.remove(match); } match = new SearchPatternData(getPattern(), false, IS_REGEX_SEARCH, getExtensions(), getContainer().getSelectedScope(), getContainer().getSelectedWorkingSets()); fPreviousSearchPatterns.add(0, match); return match; } private String[] getPreviousExtensions() { List extensions = new ArrayList(fPreviousSearchPatterns.size()); int size = fPreviousSearchPatterns.size(); for (int i = 0; i < size; i++) { SearchPatternData data = fPreviousSearchPatterns.get(i); String text = FileTypeEditor.typesToString(data.fileNamePatterns); if (!extensions.contains(text)) { extensions.add(text); } } return extensions.toArray(new String[extensions.size()]); } private String[] getPreviousSearchPatterns() { int size = fPreviousSearchPatterns.size(); String[] patterns = new String[size]; for (int i = 0; i < size; i++) { patterns[i] = (fPreviousSearchPatterns.get(i)).textPattern; } return patterns; } private String[] getExtensions() { return fFileTypeEditor.getFileTypes(); } @Override public void setVisible(boolean visible) { if (visible && fPattern != null) { if (fFirstTime) { fFirstTime = false; // Set item and text here to prevent page from resizing fPattern.setItems(getPreviousSearchPatterns()); fExtensions.setItems(getPreviousExtensions()); // if (fExtensions.getItemCount() == 0) { // loadFilePatternDefaults(); // } if (!initializePatternControl()) { fPattern.select(0); fExtensions.setText("*"); //$NON-NLS-1$ handleWidgetSelected(); } } fPattern.setFocus(); } updateOKStatus(); super.setVisible(visible); } final void updateOKStatus() { boolean regexStatus = validateRegex(); boolean hasFilePattern = fExtensions.getText().length() > 0; boolean hasTextPattern = fPattern.getText().length() > 0; getContainer().setPerformActionEnabled(regexStatus && hasFilePattern && hasTextPattern); } // ---- Widget creation ------------------------------------------------ public void createControl(Composite parent) { initializeDialogUnits(parent); readConfiguration(); Composite result = new Composite(parent, SWT.NONE); result.setFont(parent.getFont()); GridLayout layout = new GridLayout(2, false); result.setLayout(layout); addTextPatternControls(result); Label separator = new Label(result, SWT.NONE); separator.setVisible(false); GridData data = new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1); data.heightHint = convertHeightInCharsToPixels(1) / 3; separator.setLayoutData(data); addFileNameControls(result); separator = new Label(result, SWT.NONE); separator.setVisible(false); data = new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1); data.heightHint = convertHeightInCharsToPixels(1) / 3; separator.setLayoutData(data); addSearchInControls(result); setControl(result); Dialog.applyDialogFont(result); } private void addSearchInControls(Composite result) { Group g = SWTWidgetHelper.createGroup(result, "Search in"); this.firstRevisionCheckbox = SWTWidgetHelper.createCheckBox(g, "Search in all changesets"); this.firstRevisionCheckbox.setEnabled(true); this.firstRevisionCheckbox.setSelection(false); } private boolean validateRegex() { if (IS_REGEX_SEARCH) { try { PatternConstructor.createPattern(fPattern.getText(), false, true); } catch (PatternSyntaxException e) { String locMessage = e.getLocalizedMessage(); int i = 0; while (i < locMessage.length() && "\n\r".indexOf(locMessage.charAt(i)) == -1) { //$NON-NLS-1$ i++; } statusMessage(true, locMessage.substring(0, i)); // only take first line return false; } statusMessage(false, ""); //$NON-NLS-1$ } else { statusMessage(false, SearchMessages.SearchPage_containingText_hint); } return true; } private void addTextPatternControls(Composite group) { // grid layout with 2 columns // Info text Label label = new Label(group, SWT.LEAD); label.setText(SearchMessages.SearchPage_containingText_text); label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); label.setFont(group.getFont()); // Pattern combo fPattern = new Combo(group, SWT.SINGLE | SWT.BORDER); // Not done here to prevent page from resizing // fPattern.setItems(getPreviousSearchPatterns()); fPattern.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleWidgetSelected(); updateOKStatus(); } }); // add some listeners for regex syntax checking fPattern.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { updateOKStatus(); } }); fPattern.setFont(group.getFont()); GridData data = new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1); data.widthHint = convertWidthInCharsToPixels(50); fPattern.setLayoutData(data); // Text line which explains the special characters fStatusLabel = new CLabel(group, SWT.LEAD); fStatusLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); fStatusLabel.setFont(group.getFont()); fStatusLabel.setAlignment(SWT.LEFT); fStatusLabel.setText(SearchMessages.SearchPage_containingText_hint); ComboContentAdapter contentAdapter = new ComboContentAdapter(); FindReplaceDocumentAdapterContentProposalProvider findProposer = new FindReplaceDocumentAdapterContentProposalProvider( true); fPatterFieldContentAssist = new ContentAssistCommandAdapter(fPattern, contentAdapter, findProposer, ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, new char[] { '\\', '[', '(' }, true); fPatterFieldContentAssist.setEnabled(IS_REGEX_SEARCH); } private void handleWidgetSelected() { int selectionIndex = fPattern.getSelectionIndex(); if (selectionIndex < 0 || selectionIndex >= fPreviousSearchPatterns.size()) { return; } SearchPatternData patternData = fPreviousSearchPatterns.get(selectionIndex); if (!fPattern.getText().equals(patternData.textPattern)) { return; } fPattern.setText(patternData.textPattern); fFileTypeEditor.setFileTypes(patternData.fileNamePatterns); if (patternData.workingSets != null) { getContainer().setSelectedWorkingSets(patternData.workingSets); } else { getContainer().setSelectedScope(patternData.scope); } } private boolean initializePatternControl() { ISelection selection = getSelection(); if (selection instanceof ITextSelection && !selection.isEmpty()) { String text = ((ITextSelection) selection).getText(); if (text != null) { if (IS_REGEX_SEARCH) { fPattern.setText(escapeForRegExPattern(text)); } else { fPattern.setText(insertEscapeChars(text)); } if (getPreviousExtensions().length > 0) { fExtensions.setText(getPreviousExtensions()[0]); } else { String extension = getExtensionFromEditor(); if (extension != null) { fExtensions.setText(extension); } else { fExtensions.setText("*"); //$NON-NLS-1$ } } return true; } } return false; } /** * TODO this is a temporary copy from FindReplaceDocumentAdapter (Eclipse 3.5) we have to keep * it as long as we want to be Eclipse 3.4 compatible * * Escapes special characters in the string, such that the resulting pattern matches the given * string. * * @param string * the string to escape * @return a regex pattern that matches the given string * @since 3.5 */ private static String escapeForRegExPattern(String string) { // implements https://bugs.eclipse.org/bugs/show_bug.cgi?id=44422 StringBuffer pattern = new StringBuffer(string.length() + 16); int length = string.length(); if (length > 0 && string.charAt(0) == '^') { pattern.append('\\'); } for (int i = 0; i < length; i++) { char ch = string.charAt(i); switch (ch) { case '\\': case '(': case ')': case '[': case ']': case '{': case '}': case '.': case '?': case '*': case '+': case '|': pattern.append('\\').append(ch); break; case '\r': if (i + 1 < length && string.charAt(i + 1) == '\n') { i++; } pattern.append("\\R"); //$NON-NLS-1$ break; case '\n': pattern.append("\\R"); //$NON-NLS-1$ break; case '\t': pattern.append("\\t"); //$NON-NLS-1$ break; case '\f': pattern.append("\\f"); //$NON-NLS-1$ break; case 0x07: pattern.append("\\a"); //$NON-NLS-1$ break; case 0x1B: pattern.append("\\e"); //$NON-NLS-1$ break; default: if (0 <= ch && ch < 0x20) { pattern.append("\\x"); //$NON-NLS-1$ pattern.append(Integer.toHexString(ch).toUpperCase()); } else { pattern.append(ch); } } } if (length > 0 && string.charAt(length - 1) == '$') { pattern.insert(pattern.length() - 1, '\\'); } return pattern.toString(); } private String insertEscapeChars(String text) { if (StringUtils.isEmpty(text)) { return ""; //$NON-NLS-1$ } StringBuffer sbIn = new StringBuffer(text); BufferedReader reader = new BufferedReader(new StringReader(text)); int lengthOfFirstLine = 0; try { lengthOfFirstLine = reader.readLine().length(); } catch (IOException ex) { return ""; //$NON-NLS-1$ } StringBuffer sbOut = new StringBuffer(lengthOfFirstLine + 5); int i = 0; while (i < lengthOfFirstLine) { char ch = sbIn.charAt(i); if (ch == '*' || ch == '?' || ch == '\\') { sbOut.append("\\"); //$NON-NLS-1$ } sbOut.append(ch); i++; } return sbOut.toString(); } private String getExtensionFromEditor() { IEditorPart ep = SearchPlugin.getActivePage().getActiveEditor(); if (ep != null) { Object elem = ep.getEditorInput(); if (elem instanceof IFileEditorInput) { String extension = ((IFileEditorInput) elem).getFile().getFileExtension(); if (extension == null) { return ((IFileEditorInput) elem).getFile().getName(); } return "*." + extension; //$NON-NLS-1$ } } return null; } private void addFileNameControls(Composite group) { // grid layout with 2 columns // Line with label, combo and button Label label = new Label(group, SWT.LEAD); label.setText(SearchMessages.SearchPage_fileNamePatterns_text); label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); label.setFont(group.getFont()); fExtensions = new Combo(group, SWT.SINGLE | SWT.BORDER); fExtensions.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { updateOKStatus(); } }); GridData data = new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1); data.widthHint = convertWidthInCharsToPixels(50); fExtensions.setLayoutData(data); fExtensions.setFont(group.getFont()); Button button = new Button(group, SWT.PUSH); button.setText(SearchMessages.SearchPage_browse); GridData gridData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 1, 1); gridData.widthHint = SWTUtil.getButtonWidthHint(button); button.setLayoutData(gridData); button.setFont(group.getFont()); fFileTypeEditor = new FileTypeEditor(fExtensions, button); // Text line which explains the special characters Label description = new Label(group, SWT.LEAD); description.setText(SearchMessages.SearchPage_fileNamePatterns_hint); description.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); description.setFont(group.getFont()); } /** * Sets the search page's container. * * @param container * the container to set */ public void setContainer(ISearchPageContainer container) { fContainer = container; } private ISearchPageContainer getContainer() { return fContainer; } private ISelection getSelection() { return fContainer.getSelection(); } // --------------- Configuration handling -------------- @Override public void dispose() { writeConfiguration(); super.dispose(); } /** * Returns the page settings for this Text search page. * * @return the page settings to be used */ private IDialogSettings getDialogSettings() { return SearchPlugin.getDefault().getDialogSettingsSection(PAGE_NAME); } /** * Initializes itself from the stored page settings. */ private void readConfiguration() { IDialogSettings s = getDialogSettings(); try { int historySize = s.getInt(STORE_HISTORY_SIZE); for (int i = 0; i < historySize; i++) { IDialogSettings histSettings = s.getSection(STORE_HISTORY + i); if (histSettings != null) { SearchPatternData data = SearchPatternData.create(histSettings); if (data != null) { fPreviousSearchPatterns.add(data); } } } } catch (NumberFormatException e) { // ignore } } /** * Stores it current configuration in the dialog store. */ private void writeConfiguration() { IDialogSettings s = getDialogSettings(); int historySize = Math.min(fPreviousSearchPatterns.size(), HISTORY_SIZE); s.put(STORE_HISTORY_SIZE, historySize); for (int i = 0; i < historySize; i++) { IDialogSettings histSettings = s.addNewSection(STORE_HISTORY + i); SearchPatternData data = fPreviousSearchPatterns.get(i); data.store(histSettings); } } private void statusMessage(boolean error, String message) { fStatusLabel.setText(message); if (error) { fStatusLabel.setForeground(JFaceColors.getErrorText(fStatusLabel.getDisplay())); } else { fStatusLabel.setForeground(null); } } } MercurialTextSearchQuery.java000066400000000000000000000171651173713500500353770ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Juerg Billeter, juergbi@ethz.ch - 47136 Search view should show match objects * Ulrich Etter, etteru@ethz.ch - 47136 Search view should show match objects * Roman Fuchs, fuchsro@ethz.ch - 47136 Search view should show match objects * Bastian Doetsch - MercurialEclipse adaptation * Philip Graf - Fixed bugs which FindBugs found *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import java.util.ArrayList; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.search.core.text.TextSearchEngine; import org.eclipse.search.core.text.TextSearchMatchAccess; import org.eclipse.search.core.text.TextSearchRequestor; import org.eclipse.search.internal.core.text.PatternConstructor; import org.eclipse.search.internal.ui.Messages; import org.eclipse.search.internal.ui.SearchMessages; import org.eclipse.search.internal.ui.text.SearchResultUpdater; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.ISearchResult; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.FileTextSearchScope; import org.eclipse.search.ui.text.Match; @SuppressWarnings("restriction") public class MercurialTextSearchQuery implements ISearchQuery { private static final class TextSearchResultCollector extends TextSearchRequestor { private final AbstractTextSearchResult fResult; private final boolean fIsFileSearchOnly; private final boolean fSearchInBinaries; private ArrayList fCachedMatches; private TextSearchResultCollector(AbstractTextSearchResult result, boolean isFileSearchOnly, boolean searchInBinaries) { fResult = result; fIsFileSearchOnly = isFileSearchOnly; fSearchInBinaries = searchInBinaries; } @Override public boolean acceptFile(IFile file) throws CoreException { if (fIsFileSearchOnly) { fResult.addMatch(new MercurialMatch(file)); } flushMatches(); return true; } /* * (non-Javadoc) * * @see * org.eclipse.search.core.text.TextSearchRequestor#reportBinaryFile * (org.eclipse.core.resources.IFile) */ @Override public boolean reportBinaryFile(IFile file) { return fSearchInBinaries; } @Override public boolean acceptPatternMatch(TextSearchMatchAccess matchRequestor) throws CoreException { if (matchRequestor instanceof MercurialTextSearchMatchAccess) { MercurialMatch match = new MercurialMatch( (MercurialTextSearchMatchAccess) matchRequestor); fCachedMatches.add(match); return true; } return false; } @Override public void beginReporting() { fCachedMatches = new ArrayList(); } @Override public void endReporting() { flushMatches(); fCachedMatches = null; } private void flushMatches() { if (!fCachedMatches.isEmpty()) { fResult.addMatches(fCachedMatches .toArray(new Match[fCachedMatches.size()])); fCachedMatches.clear(); } } } private final MercurialTextSearchScope fScope; private final String fSearchText; private MercurialTextSearchResult fResult; public MercurialTextSearchQuery(String searchText, MercurialTextSearchScope scope) { fSearchText = searchText; fScope = scope; } public MercurialTextSearchScope getSearchScope() { return fScope; } public boolean canRunInBackground() { return true; } public IStatus run(final IProgressMonitor monitor) { AbstractTextSearchResult textResult = (AbstractTextSearchResult) getSearchResult(); textResult.removeAll(); Pattern searchPattern = getSearchPattern(); boolean searchInBinaries = !isScopeAllFileTypes(); TextSearchResultCollector collector = new TextSearchResultCollector( textResult, isFileNameSearch(), searchInBinaries); TextSearchEngine engine = new MercurialTextSearchEngine(); return engine.search(fScope, collector, searchPattern, monitor); } private boolean isScopeAllFileTypes() { String[] fileNamePatterns = fScope.getFileNamePatterns(); if (fileNamePatterns == null) { return true; } for (int i = 0; i < fileNamePatterns.length; i++) { if ("*".equals(fileNamePatterns[i])) { //$NON-NLS-1$ return true; } } return false; } public String getLabel() { return "Mercurial Text Search for " + fSearchText; } public String getSearchString() { return fSearchText; } public String getResultLabel(int nMatches) { String searchString = getSearchString(); if (searchString.length() > 0) { // text search if (isScopeAllFileTypes()) { // search all file extensions if (nMatches == 1) { Object[] args = { searchString, fScope.getDescription() }; return Messages.format( SearchMessages.FileSearchQuery_singularLabel, args); } Object[] args = { searchString, Integer.valueOf(nMatches), fScope.getDescription() }; return Messages.format( SearchMessages.FileSearchQuery_pluralPattern, args); } // search selected file extensions if (nMatches == 1) { Object[] args = { searchString, fScope.getDescription(), fScope.getFilterDescription() }; return Messages .format( SearchMessages.FileSearchQuery_singularPatternWithFileExt, args); } Object[] args = { searchString, Integer.valueOf(nMatches), fScope.getDescription(), fScope.getFilterDescription() }; return Messages.format( SearchMessages.FileSearchQuery_pluralPatternWithFileExt, args); } // file search if (nMatches == 1) { Object[] args = { fScope.getFilterDescription(), fScope.getDescription() }; return Messages .format( SearchMessages.FileSearchQuery_singularLabel_fileNameSearch, args); } Object[] args = { fScope.getFilterDescription(), Integer.valueOf(nMatches), fScope.getDescription() }; return Messages.format( SearchMessages.FileSearchQuery_pluralPattern_fileNameSearch, args); } /** * @param result * all result are added to this search result * @param monitor * the progress monitor to use * @param file * the file to search in * @return returns the status of the operation */ public IStatus searchInFile(final AbstractTextSearchResult result, final IProgressMonitor monitor, IFile file) { FileTextSearchScope scope = FileTextSearchScope.newSearchScope( new IResource[] { file }, new String[] { "*" }, true); //$NON-NLS-1$ Pattern searchPattern = getSearchPattern(); TextSearchResultCollector collector = new TextSearchResultCollector( result, isFileNameSearch(), true); return new MercurialTextSearchEngine().search(scope, collector, searchPattern, monitor); } protected Pattern getSearchPattern() { return PatternConstructor.createPattern(fSearchText, true, true); } public boolean isFileNameSearch() { return fSearchText.length() == 0; } public boolean canRerun() { return true; } public ISearchResult getSearchResult() { if (fResult == null) { fResult = new MercurialTextSearchResult(this); new SearchResultUpdater(fResult); } return fResult; } } MercurialTextSearchQueryProvider.java000066400000000000000000000050671173713500500371100ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import org.eclipse.core.resources.IResource; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.ui.IWorkingSet; import com.vectrace.MercurialEclipse.search.MercurialTextSearchPage.TextSearchPageInput; /** * @author Bastian * */ public class MercurialTextSearchQueryProvider { private final boolean all; public MercurialTextSearchQueryProvider(boolean all) { this.all = all; } /* * (non-Javadoc) * * @seeorg.eclipse.search.ui.text.TextSearchQueryProvider#createQuery( TextSearchInput) */ public ISearchQuery createQuery(TextSearchPageInput input) { MercurialTextSearchScope scope = input.getScope(); String text = input.getSearchText(); return new MercurialTextSearchQuery(text, scope); } /* * (non-Javadoc) * * @see org.eclipse.search.ui.text.TextSearchQueryProvider#createQuery(java.lang .String) */ public ISearchQuery createQuery(String searchForString) { MercurialTextSearchScope scope = MercurialTextSearchScope.newWorkspaceScope( getPreviousFileNamePatterns(), all); return new MercurialTextSearchQuery(searchForString, scope); } /* * (non-Javadoc) * * @see org.eclipse.search.ui.text.TextSearchQueryProvider#createQuery(java.lang .String, * org.eclipse.core.resources.IResource[]) */ public ISearchQuery createQuery(String selectedText, IResource[] resources) { MercurialTextSearchScope scope = MercurialTextSearchScope.newSearchScope(resources, getPreviousFileNamePatterns(), all); return new MercurialTextSearchQuery(selectedText, scope); } /* * (non-Javadoc) * * @see org.eclipse.search.ui.text.TextSearchQueryProvider#createQuery(java.lang .String, * org.eclipse.ui.IWorkingSet[]) */ public ISearchQuery createQuery(String selectedText, IWorkingSet[] ws) { MercurialTextSearchScope scope = MercurialTextSearchScope.newSearchScope(ws, getPreviousFileNamePatterns(), all); return new MercurialTextSearchQuery(selectedText, scope); } private String[] getPreviousFileNamePatterns() { return new String[] { "*" }; //$NON-NLS-1$ } } MercurialTextSearchResult.java000066400000000000000000000044351173713500500355440ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import org.eclipse.core.resources.IFile; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.search.internal.ui.SearchPluginImages; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.IEditorMatchAdapter; import org.eclipse.search.ui.text.IFileMatchAdapter; import org.eclipse.search.ui.text.Match; import org.eclipse.ui.IEditorPart; /** * @author Bastian * */ public class MercurialTextSearchResult extends AbstractTextSearchResult implements IEditorMatchAdapter, IFileMatchAdapter { private MercurialTextSearchQuery query; public MercurialTextSearchResult() { super(); } public MercurialTextSearchResult(MercurialTextSearchQuery query) { this.query = query; } @Override public IEditorMatchAdapter getEditorMatchAdapter() { return this; } @Override public IFileMatchAdapter getFileMatchAdapter() { return this; } @SuppressWarnings("restriction") public ImageDescriptor getImageDescriptor() { return SearchPluginImages.DESC_OBJ_TSEARCH_DPDN; } public String getLabel() { return query.getResultLabel(super.getMatchCount()); } public ISearchQuery getQuery() { return this.query; } public String getTooltip() { return getLabel(); } public Match[] computeContainedMatches(AbstractTextSearchResult result, IFile file) { return new Match[0]; } public Match[] computeContainedMatches(AbstractTextSearchResult result, IEditorPart editor) { return new Match[0]; } public IFile getFile(Object element) { if (element instanceof IFile) { return (IFile)element; } return null; } public boolean isShownInEditor(Match match, IEditorPart editor) { return false; } } MercurialTextSearchResultPage.java000066400000000000000000000223411173713500500363350ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Juerg Billeter, juergbi@ethz.ch - 47136 Search view should show match objects * Ulrich Etter, etteru@ethz.ch - 47136 Search view should show match objects * Roman Fuchs, fuchsro@ethz.ch - 47136 Search view should show match objects * Bastian Doetsch - adaptation for MercurialEclipse * Philip Graf - Fixed bugs which FindBugs found *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.OpenEvent; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.search.internal.ui.Messages; import org.eclipse.search.internal.ui.SearchMessages; import org.eclipse.search.internal.ui.text.NewTextSearchActionGroup; import org.eclipse.search.ui.IContextMenuConstants; import org.eclipse.search.ui.ISearchResultViewPart; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.AbstractTextSearchViewPage; import org.eclipse.search.ui.text.Match; import org.eclipse.search2.internal.ui.OpenSearchPreferencesAction; import org.eclipse.team.internal.ui.Utils; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IMemento; import org.eclipse.ui.PartInitException; import org.eclipse.ui.actions.ActionGroup; import org.eclipse.ui.part.IPageSite; import org.eclipse.ui.texteditor.ITextEditor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.history.MercurialRevision; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; @SuppressWarnings("restriction") public class MercurialTextSearchResultPage extends AbstractTextSearchViewPage implements IAdaptable { private static final String KEY_LIMIT = "org.eclipse.search.resultpage.limit"; //$NON-NLS-1$ private static final int DEFAULT_ELEMENT_LIMIT = 1000; private ActionGroup fActionGroup; private IMercurialTextSearchContentProvider contentProvider; public MercurialTextSearchResultPage() { setElementLimit(new Integer(DEFAULT_ELEMENT_LIMIT)); } @Override public void setElementLimit(Integer elementLimit) { super.setElementLimit(elementLimit); int limit = elementLimit.intValue(); getSettings().put(KEY_LIMIT, limit); } @Override public StructuredViewer getViewer() { return super.getViewer(); } @Override protected void configureTableViewer(TableViewer viewer) { viewer.setUseHashlookup(true); contentProvider = new MercurialTextSearchTableContentProvider(this); viewer.setContentProvider(contentProvider); MercurialTextSearchTableLabelProvider innerLabelProvider = new MercurialTextSearchTableLabelProvider( this, MercurialTextSearchTreeLabelProvider.SHOW_LABEL); viewer.setLabelProvider(new DecoratingMercurialTextSearchLabelProvider(innerLabelProvider)); } @Override protected void configureTreeViewer(TreeViewer viewer) { viewer.setUseHashlookup(true); contentProvider = new MercurialTextSearchTreeContentProvider(this, viewer); viewer.setContentProvider(contentProvider); MercurialTextSearchTreeLabelProvider innerLabelProvider = new MercurialTextSearchTreeLabelProvider( this, MercurialTextSearchTreeLabelProvider.SHOW_LABEL); viewer.setLabelProvider(new DecoratingMercurialTextSearchLabelProvider(innerLabelProvider)); viewer.setComparator(new ViewerComparator() { @Override public int compare(Viewer v, Object e1, Object e2) { if (e1 instanceof MercurialRevisionStorage && e2 instanceof MercurialRevisionStorage) { MercurialRevisionStorage mrs1 = (MercurialRevisionStorage) e1; MercurialRevisionStorage mrs2 = (MercurialRevisionStorage) e2; if (mrs1.getResource().equals(mrs2.getResource())) { return mrs2.getRevision() - mrs1.getRevision(); } } else if (e1 instanceof MercurialMatch && e2 instanceof MercurialMatch) { MercurialMatch m1 = (MercurialMatch) e1; MercurialMatch m2 = (MercurialMatch) e2; return m1.getLineNumber() - m2.getLineNumber(); } return super.compare(v, e1, e2); } }); } @Override protected void showMatch(Match match, int offset, int length, boolean activate) throws PartInitException { // TODO } @Override protected void handleOpen(OpenEvent event) { Object firstElement = ((IStructuredSelection) event.getSelection()).getFirstElement(); if (firstElement instanceof MercurialMatch) { if (getDisplayedMatchCount(firstElement) == 0) { try { MercurialMatch m = (MercurialMatch) firstElement; // open an editor with the content of the changeset this matc MercurialRevision revision = new MercurialRevision(m .getMercurialRevisionStorage().getChangeSet(), null, m.getFile(), null, null); IEditorPart editor = Utils.openEditor(getSite().getPage(), revision, new NullProgressMonitor()); if (editor instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) editor; IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput()); if (document != null) { String content = document.get(); int offset = content.indexOf(m.getExtract()); int length = m.getExtract().length(); m.setOffset(offset); m.setLength(length); textEditor.selectAndReveal(offset, length); } } } catch (Exception e) { ErrorDialog.openError(getSite().getShell(), SearchMessages.FileSearchPage_open_file_dialog_title, SearchMessages.FileSearchPage_open_file_failed, new Status( IStatus.ERROR, MercurialEclipsePlugin.ID, e .getLocalizedMessage(), e)); } return; } } } @Override protected void fillContextMenu(IMenuManager mgr) { // TODO } @Override public void setViewPart(ISearchResultViewPart part) { super.setViewPart(part); fActionGroup = new NewTextSearchActionGroup(part); } @Override public void init(IPageSite site) { super.init(site); IMenuManager menuManager = site.getActionBars().getMenuManager(); menuManager.appendToGroup(IContextMenuConstants.GROUP_PROPERTIES, new OpenSearchPreferencesAction()); } @Override public void dispose() { fActionGroup.dispose(); super.dispose(); } @Override protected void elementsChanged(Object[] objects) { if (contentProvider != null) { contentProvider.elementsChanged(objects); } } @Override protected void clear() { if (contentProvider != null) { contentProvider.clear(); } } @Override public void restoreState(IMemento memento) { super.restoreState(memento); int elementLimit = DEFAULT_ELEMENT_LIMIT; try { elementLimit = getSettings().getInt(KEY_LIMIT); } catch (NumberFormatException e) { } if (memento != null) { Integer value = memento.getInteger(KEY_LIMIT); if (value != null) { elementLimit = value.intValue(); } } setElementLimit(Integer.valueOf(elementLimit)); } @Override public void saveState(IMemento memento) { super.saveState(memento); memento.putInteger(KEY_LIMIT, getElementLimit().intValue()); } @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { return null; } @Override public String getLabel() { String label = super.getLabel(); StructuredViewer viewer = getViewer(); if (viewer instanceof TableViewer) { TableViewer tv = (TableViewer) viewer; AbstractTextSearchResult result = getInput(); if (result != null) { int itemCount = ((IStructuredContentProvider) tv.getContentProvider()) .getElements(getInput()).length; if (showLineMatches()) { int matchCount = getInput().getMatchCount(); if (itemCount < matchCount) { return Messages.format( SearchMessages.FileSearchPage_limited_format_matches, new Object[] {label, Integer.valueOf(itemCount), Integer.valueOf(matchCount)}); } } else { int fileCount = getInput().getElements().length; if (itemCount < fileCount) { return Messages.format( SearchMessages.FileSearchPage_limited_format_files, new Object[] {label, Integer.valueOf(itemCount), Integer.valueOf(fileCount)}); } } } } return label; } private boolean showLineMatches() { AbstractTextSearchResult input = getInput(); return getLayout() == FLAG_LAYOUT_TREE && input != null && !((MercurialTextSearchQuery) input.getQuery()).isFileNameSearch(); } } MercurialTextSearchScope.java000066400000000000000000000257111173713500500353370ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2000, 2008, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Bastian Doetsch - adaptation for MercurialEclipse *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import java.util.ArrayList; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.search.core.text.TextSearchScope; import org.eclipse.search.internal.core.text.PatternConstructor; import org.eclipse.search.internal.ui.Messages; import org.eclipse.search.internal.ui.SearchMessages; import org.eclipse.search.internal.ui.WorkingSetComparator; import org.eclipse.search.internal.ui.text.BasicElementLabels; import org.eclipse.search.internal.ui.util.FileTypeEditor; import org.eclipse.ui.IWorkingSet; /** * @author bastian * */ @SuppressWarnings("restriction") public final class MercurialTextSearchScope extends TextSearchScope { private final Matcher fNegativeFileNameMatcher; private final Matcher fPositiveFileNameMatcher; private final String fDescription; private final IResource[] fRootElements; private final IWorkingSet[] fWorkingSets; private final String[] fFileNamePatterns; private final boolean all; private MercurialTextSearchScope(String description, IResource[] resources, IWorkingSet[] workingSets, String[] fileNamePatterns, boolean all) { fDescription = description; fRootElements = resources; fFileNamePatterns = fileNamePatterns; fWorkingSets = workingSets; this.all = all; fPositiveFileNameMatcher = createMatcher(fileNamePatterns, false); fNegativeFileNameMatcher = createMatcher(fileNamePatterns, true); } @Override public boolean contains(IResourceProxy proxy) { if (proxy.isDerived()) { return false; // all resources in a derived folder are considered to be derived, see bug // 103576 } if (proxy.getType() == IResource.FILE) { return matchesFileName(proxy.getName()); } return true; } private boolean matchesFileName(String fileName) { if (fPositiveFileNameMatcher != null && !fPositiveFileNameMatcher.reset(fileName).matches()) { return false; } if (fNegativeFileNameMatcher != null && fNegativeFileNameMatcher.reset(fileName).matches()) { return false; } return true; } private Matcher createMatcher(String[] fileNamePatterns, boolean negativeMatcher) { if (fileNamePatterns == null || fileNamePatterns.length == 0) { return null; } ArrayList patterns = new ArrayList(); for (int i = 0; i < fileNamePatterns.length; i++) { String pattern = fFileNamePatterns[i]; if (negativeMatcher == pattern.startsWith(FileTypeEditor.FILE_PATTERN_NEGATOR)) { if (negativeMatcher) { pattern = pattern.substring(FileTypeEditor.FILE_PATTERN_NEGATOR.length()) .trim(); } if (pattern.length() > 0) { patterns.add(pattern); } } } if (!patterns.isEmpty()) { String[] patternArray = patterns.toArray(new String[patterns.size()]); Pattern pattern = PatternConstructor.createPattern(patternArray, true); return pattern.matcher(""); //$NON-NLS-1$ } return null; } /** * @return the all */ public boolean isAll() { return all; } /** * Returns a scope for the workspace. The created scope contains all resources in the workspace * that match the given file name patterns. Depending on includeDerived, derived * resources or resources inside a derived container are part of the scope or not. * * @param fileNamePatterns * file name pattern that all files have to match null to include all * file names. * @param all * defines if all changesets are included in the scope. * @return a scope containing all files in the workspace that match the given file name * patterns. */ public static MercurialTextSearchScope newWorkspaceScope(String[] fileNamePatterns, boolean all) { return new MercurialTextSearchScope(SearchMessages.WorkspaceScope, new IResource[] { ResourcesPlugin.getWorkspace().getRoot() }, null, fileNamePatterns, all); } private static IResource[] removeRedundantEntries(IResource[] elements) { ArrayList res = new ArrayList(); for (int i = 0; i < elements.length; i++) { IResource curr = elements[i]; addToList(res, curr); } return res.toArray(new IResource[res.size()]); } private static void addToList(ArrayList res, IResource curr) { IPath currPath = curr.getFullPath(); for (int k = res.size() - 1; k >= 0; k--) { IResource other = res.get(k); IPath otherPath = other.getFullPath(); if (otherPath.isPrefixOf(currPath)) { return; } if (currPath.isPrefixOf(otherPath)) { res.remove(k); } } res.add(curr); } /** * Returns a scope for the given root resources. The created scope contains all root resources * and their children that match the given file name patterns. Depending on * includeDerived, derived resources or resources inside a derived container are * part of the scope or not. * * @param roots * the roots resources defining the scope. * @param fileNamePatterns * file name pattern that all files have to match null to include all * file names. * @param all * defines if all changesets are included in the scope. * @return a scope containing the resources and its children if they match the given file name * patterns. */ public static MercurialTextSearchScope newSearchScope(IResource[] roots, String[] fileNamePatterns, boolean all) { roots = removeRedundantEntries(roots); String description; if (roots.length == 0) { description = SearchMessages.FileTextSearchScope_scope_empty; } else if (roots.length == 1) { String label = SearchMessages.FileTextSearchScope_scope_single; description = Messages.format(label, roots[0].getName()); } else if (roots.length == 2) { String label = SearchMessages.FileTextSearchScope_scope_double; description = Messages.format(label, new String[] { roots[0].getName(), roots[1].getName() }); } else { String label = SearchMessages.FileTextSearchScope_scope_multiple; description = Messages.format(label, new String[] { roots[0].getName(), roots[1].getName() }); } return new MercurialTextSearchScope(description, roots, null, fileNamePatterns, all); } /** * Returns a scope for the given working sets. The created scope contains all resources in the * working sets that match the given file name patterns. Depending on * includeDerived, derived resources or resources inside a derived container are * part of the scope or not. * * @param workingSets * the working sets defining the scope. * @param fileNamePatterns * file name pattern that all files have to match null to include all * file names. * @param all * defines if all changesets are included in the scope. * @return a scope containing the resources in the working set if they match the given file name * patterns. */ @SuppressWarnings("unchecked") public static MercurialTextSearchScope newSearchScope(IWorkingSet[] workingSets, String[] fileNamePatterns, boolean all) { String description; Arrays.sort(workingSets, new WorkingSetComparator()); if (workingSets.length == 0) { description = SearchMessages.FileTextSearchScope_ws_scope_empty; } else if (workingSets.length == 1) { String label = SearchMessages.FileTextSearchScope_ws_scope_single; description = Messages.format(label, workingSets[0].getLabel()); } else if (workingSets.length == 2) { String label = SearchMessages.FileTextSearchScope_ws_scope_double; description = Messages.format(label, new String[] { workingSets[0].getLabel(), workingSets[1].getLabel() }); } else { String label = SearchMessages.FileTextSearchScope_ws_scope_multiple; description = Messages.format(label, new String[] { workingSets[0].getLabel(), workingSets[1].getLabel() }); } MercurialTextSearchScope scope = new MercurialTextSearchScope(description, convertToResources(workingSets), workingSets, fileNamePatterns, all); return scope; } private static IResource[] convertToResources(IWorkingSet[] workingSets) { ArrayList res = new ArrayList(); for (int i = 0; i < workingSets.length; i++) { IWorkingSet workingSet = workingSets[i]; if (workingSet.isAggregateWorkingSet() && workingSet.isEmpty()) { return new IResource[] { ResourcesPlugin.getWorkspace().getRoot() }; } IAdaptable[] elements = workingSet.getElements(); for (int k = 0; k < elements.length; k++) { IResource curr = (IResource) elements[k].getAdapter(IResource.class); if (curr != null) { addToList(res, curr); } } } return res.toArray(new IResource[res.size()]); } @Override public IResource[] getRoots() { return fRootElements; } /** * Returns the description of the scope * * @return the description of the scope */ public String getDescription() { return fDescription; } /** * Returns the file name pattern configured for this scope or null to match all * file names. * * @return the file name pattern starings */ public String[] getFileNamePatterns() { return fFileNamePatterns; } /** * Returns the working-sets that were used to configure this scope or null if the * scope was not created off working sets. * * @return the working-sets the scope is based on. */ public IWorkingSet[] getWorkingSets() { return fWorkingSets; } /** * Returns the content types configured for this scope or null to match all content * types. * * @return the file name pattern starings */ public IContentType[] getContentTypes() { return null; // to be implemented in the future } /** * Returns a description describing the file name patterns and content types. * * @return the description of the scope */ public String getFilterDescription() { String[] ext = fFileNamePatterns; if (ext == null) { return BasicElementLabels.getFilePattern("*"); //$NON-NLS-1$ } Arrays.sort(ext); StringBuffer buf = new StringBuffer(); for (int i = 0; i < ext.length; i++) { if (i > 0) { buf.append(", "); //$NON-NLS-1$ } buf.append(ext[i]); } return BasicElementLabels.getFilePattern(buf.toString()); } } MercurialTextSearchTableContentProvider.java000066400000000000000000000042441173713500500403610ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/searchpackage com.vectrace.MercurialEclipse.search; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.search.ui.text.AbstractTextSearchResult; public class MercurialTextSearchTableContentProvider implements IStructuredContentProvider, IMercurialTextSearchContentProvider { private static final Object[] EMPTY_ARR = new Object[0]; private final MercurialTextSearchResultPage fPage; private AbstractTextSearchResult fResult; public MercurialTextSearchTableContentProvider(MercurialTextSearchResultPage page) { fPage = page; } public void dispose() { // nothing to do } public Object[] getElements(Object inputElement) { if (inputElement instanceof MercurialTextSearchResult) { int elementLimit = getElementLimit(); Object[] elements = ((MercurialTextSearchResult) inputElement) .getElements(); if (elementLimit != -1 && elements.length > elementLimit) { Object[] shownElements = new Object[elementLimit]; System.arraycopy(elements, 0, shownElements, 0, elementLimit); return shownElements; } return elements; } return EMPTY_ARR; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (newInput instanceof MercurialTextSearchResult) { fResult = (MercurialTextSearchResult) newInput; } } public void elementsChanged(Object[] updatedElements) { TableViewer viewer = getViewer(); int elementLimit = getElementLimit(); boolean tableLimited = elementLimit != -1; for (int i = 0; i < updatedElements.length; i++) { if (fResult.getMatchCount(updatedElements[i]) > 0) { if (viewer.testFindItem(updatedElements[i]) != null) { viewer.update(updatedElements[i], null); } else { if (!tableLimited || viewer.getTable().getItemCount() < elementLimit) { viewer.add(updatedElements[i]); } } } else { viewer.remove(updatedElements[i]); } } } private int getElementLimit() { return fPage.getElementLimit().intValue(); } private TableViewer getViewer() { return (TableViewer) fPage.getViewer(); } public void clear() { getViewer().refresh(); } } MercurialTextSearchTableLabelProvider.java000066400000000000000000000032661173713500500377710ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import org.eclipse.jface.viewers.StyledString; import org.eclipse.search.ui.text.AbstractTextSearchViewPage; import org.eclipse.swt.graphics.Image; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; /** * @author bastian * */ public class MercurialTextSearchTableLabelProvider extends MercurialTextSearchTreeLabelProvider { /** * @param page * @param orderFlag */ public MercurialTextSearchTableLabelProvider(AbstractTextSearchViewPage page, int orderFlag) { super(page, orderFlag); } @Override public StyledString getStyledText(Object element) { if (element instanceof MercurialRevisionStorage) { MercurialRevisionStorage mrs = (MercurialRevisionStorage) element; String csInfo = getCsInfoString(mrs); return new StyledString(csInfo + mrs.getResource().getFullPath().toOSString()); } return super.getStyledText(element); } @Override public Image getImage(Object element) { if (element instanceof MercurialRevisionStorage) { MercurialRevisionStorage mrs = (MercurialRevisionStorage) element; return super.getResourceImage(mrs.getResource()); } return super.getImage(element); } } MercurialTextSearchTreeContentProvider.java000066400000000000000000000152311173713500500402270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2000, 2008, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Juerg Billeter, juergbi@ethz.ch - 47136 Search view should show match objects * Ulrich Etter, etteru@ethz.ch - 47136 Search view should show match objects * Roman Fuchs, fuchsro@ethz.ch - 47136 Search view should show match objects * Bastian Doetsch - Adaptation for MercurialEclipse *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.Match; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; public class MercurialTextSearchTreeContentProvider implements ITreeContentProvider, IMercurialTextSearchContentProvider { private static final Object[] EMPTY_ARR = new Object[0]; private AbstractTextSearchResult fResult; private final MercurialTextSearchResultPage fPage; private final AbstractTreeViewer fTreeViewer; private Map fChildrenMap; MercurialTextSearchTreeContentProvider(MercurialTextSearchResultPage page, AbstractTreeViewer viewer) { fPage = page; fTreeViewer = viewer; } public Object[] getElements(Object inputElement) { Object[] children = getChildren(inputElement); int elementLimit = getElementLimit(); if (elementLimit != -1 && elementLimit < children.length) { Object[] limitedChildren = new Object[elementLimit]; System.arraycopy(children, 0, limitedChildren, 0, elementLimit); return limitedChildren; } return children; } private int getElementLimit() { return fPage.getElementLimit().intValue(); } public void dispose() { // nothing to do } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (newInput instanceof MercurialTextSearchResult) { initialize((MercurialTextSearchResult) newInput); } } private synchronized void initialize(AbstractTextSearchResult result) { fResult = result; fChildrenMap = new HashMap(); addMatches(result); } /** * @param result * @param showLineMatches */ private void addMatches(AbstractTextSearchResult result) { boolean showLineMatches = !((MercurialTextSearchQuery) fResult.getQuery()) .isFileNameSearch(); if (result != null && showLineMatches) { Object[] elements = result.getElements(); for (int i = 0; i < elements.length; i++) { Match[] matches = result.getMatches(elements[i]); for (int j = 0; j < matches.length; j++) { MercurialMatch m = (MercurialMatch) matches[j]; insert(m, false, m.getMercurialRevisionStorage()); } } } } private void insert(Object child, boolean refreshViewer, MercurialRevisionStorage mrs) { Object parent = getParent(child, mrs); while (parent != null) { if (insertChild(parent, child)) { if (refreshViewer) { fTreeViewer.add(parent, child); } } else { if (refreshViewer) { fTreeViewer.refresh(parent); } return; } child = parent; parent = getParent(child, mrs); } if (insertChild(fResult, child)) { if (refreshViewer) { fTreeViewer.add(fResult, child); } } } /** * Adds the child to the parent. * * @param parent * the parent * @param child * the child * @return true if this set did not already contain the specified element */ private boolean insertChild(Object parent, Object child) { Set children = (Set) fChildrenMap.get(parent); if (children == null) { children = new HashSet(); fChildrenMap.put(parent, children); } return children.add(child); } private boolean hasChild(Object parent, Object child) { Set children = (Set) fChildrenMap.get(parent); return children != null && children.contains(child); } private void remove(Object element, boolean refreshViewer) { // precondition here: fResult.getMatchCount(child) <= 0 if (hasChildren(element)) { if (refreshViewer) { fTreeViewer.refresh(element); } } else { if (!hasMatches(element)) { fChildrenMap.remove(element); Object parent = getParent(element); if (parent != null) { removeFromSiblings(element, parent); remove(parent, refreshViewer); } else { removeFromSiblings(element, fResult); if (refreshViewer) { fTreeViewer.refresh(); } } } else { if (refreshViewer) { fTreeViewer.refresh(element); } } } } private boolean hasMatches(Object element) { return fResult.getMatchCount(element) > 0; } private void removeFromSiblings(Object element, Object parent) { Set siblings = (Set) fChildrenMap.get(parent); if (siblings != null) { siblings.remove(element); } } public Object[] getChildren(Object parentElement) { Set children = (Set) fChildrenMap.get(parentElement); if (children == null) { return EMPTY_ARR; } return children.toArray(); } public boolean hasChildren(Object element) { return getChildren(element).length > 0; } /* * (non-Javadoc) * * @seeorg.eclipse.search.internal.ui.text.IFileSearchContentProvider# * elementsChanged(java.lang.Object[]) */ public synchronized void elementsChanged(Object[] updatedElements) { for (int i = 0; i < updatedElements.length; i++) { if (!(updatedElements[i] instanceof MercurialRevisionStorage)) { // do nothing } else { MercurialRevisionStorage mrs = (MercurialRevisionStorage) updatedElements[i]; insert(mrs.getResource(), true, mrs); addMatches(fResult); } } } public void clear() { initialize(fResult); fTreeViewer.refresh(); } public Object getParent(Object element, MercurialRevisionStorage mrs) { if (element instanceof IProject) { return null; } if (element instanceof IResource) { IResource resource = (IResource) element; return resource.getParent(); } if (element instanceof MercurialRevisionStorage) { return mrs.getResource(); } if (element instanceof MercurialMatch) { return mrs; } return null; } public Object getParent(Object element) { return null; } } MercurialTextSearchTreeLabelProvider.java000066400000000000000000000214311173713500500376330ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2000, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Juerg Billeter, juergbi@ethz.ch - 47136 Search view should show match objects * Ulrich Etter, etteru@ethz.ch - 47136 Search view should show match objects * Roman Fuchs, fuchsro@ethz.ch - 47136 Search view should show match objects * Andrei Loskutov - bug fixes * Philip Graf - Fixed bugs which FindBugs found *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import java.util.Comparator; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.StyledString.Styler; import org.eclipse.search.internal.ui.Messages; import org.eclipse.search.internal.ui.SearchMessages; import org.eclipse.search.internal.ui.SearchPluginImages; import org.eclipse.search.internal.ui.text.BasicElementLabels; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.AbstractTextSearchViewPage; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.model.WorkbenchLabelProvider; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; public class MercurialTextSearchTreeLabelProvider extends LabelProvider implements IStyledLabelProvider { public static final int SHOW_LABEL = 1; public static final int SHOW_LABEL_PATH = 2; public static final int SHOW_PATH_LABEL = 3; private static final String FG_SEPARATOR_FORMAT = "{0} - {1}"; //$NON-NLS-1$ private static final String FG_ELLIPSES = " ... "; //$NON-NLS-1$ private final WorkbenchLabelProvider fLabelProvider; private final AbstractTextSearchViewPage fPage; private final Comparator fMatchComparator; private final Image fLineMatchImage; private int fOrder; public MercurialTextSearchTreeLabelProvider(AbstractTextSearchViewPage page, int orderFlag) { fLabelProvider = new WorkbenchLabelProvider(); fOrder = orderFlag; fPage = page; fLineMatchImage = SearchPluginImages.get(SearchPluginImages.IMG_OBJ_TEXT_SEARCH_LINE); fMatchComparator = new Comparator() { public int compare(MercurialMatch o1, MercurialMatch o2) { return o1.getLineNumber() - o2.getLineNumber(); } }; } public void setOrder(int orderFlag) { fOrder = orderFlag; } public int getOrder() { return fOrder; } @Override public String getText(Object object) { return getStyledText(object).getString(); } private StyledString getColoredLabelWithCounts(Object element, StyledString coloredName) { AbstractTextSearchResult result = fPage.getInput(); if (result == null) { return coloredName; } int matchCount = result.getMatchCount(element); if (matchCount <= 1) { return coloredName; } String countInfo = Messages.format(SearchMessages.FileLabelProvider_count_format, Integer.valueOf(matchCount)); coloredName.append(' ').append(countInfo, StyledString.COUNTER_STYLER); return coloredName; } public StyledString getStyledText(Object element) { if (element instanceof MercurialRevisionStorage) { MercurialRevisionStorage mrs = (MercurialRevisionStorage) element; ChangeSet cs = mrs.getChangeSet(); if(cs == null) { return new StyledString(""); } return new StyledString(cs.getChangesetIndex() + " [" + cs.getAuthor() + "] (" + cs.getAgeDate() + ")"); } if (element instanceof MercurialMatch) { MercurialMatch match = (MercurialMatch) element; return getMercurialMatchLabel(match); } if (!(element instanceof IResource)) { return new StyledString(element.toString()); } IResource resource = (IResource) element; if (!resource.exists()) { new StyledString(SearchMessages.FileLabelProvider_removed_resource_label); } String name = BasicElementLabels.getResourceName(resource); if (fOrder == SHOW_LABEL) { return getColoredLabelWithCounts(resource, new StyledString(name)); } String pathString = BasicElementLabels.getPathLabel(resource.getParent().getFullPath(), false); if (fOrder == SHOW_LABEL_PATH) { StyledString str = new StyledString(name); String decorated = Messages.format(FG_SEPARATOR_FORMAT, new String[] { str.getString(), pathString }); styleDecoratedString(decorated, StyledString.QUALIFIER_STYLER, str); return getColoredLabelWithCounts(resource, str); } StyledString str = new StyledString(Messages.format(FG_SEPARATOR_FORMAT, new String[] { pathString, name })); return getColoredLabelWithCounts(resource, str); } /** * TODO this is a temporary copy from StyledCellLabelProvider (Eclipse 3.5) we have to keep it * as long as we want to be Eclipse 3.4 compatible * * Applies decoration styles to the decorated string and adds the styles of the previously * undecorated string. *

* If the decoratedString contains the styledString, then the result * keeps the styles of the styledString and styles the decorations with the * decorationStyler. Otherwise, the decorated string is returned without any * styles. * * @param decoratedString * the decorated string * @param decorationStyler * the styler to use for the decoration or null for no styles * @param styledString * the original styled string * * @return the styled decorated string (can be the given styledString) * @since 3.5 */ private static StyledString styleDecoratedString(String decoratedString, Styler decorationStyler, StyledString styledString) { String label = styledString.getString(); int originalStart = decoratedString.indexOf(label); if (originalStart == -1) { return new StyledString(decoratedString); // the decorator did something wild } if (decoratedString.length() == label.length()) { return styledString; } if (originalStart > 0) { StyledString newString = new StyledString(decoratedString.substring(0, originalStart), decorationStyler); newString.append(styledString); styledString = newString; } if (decoratedString.length() > originalStart + label.length()) { // decorator appended // something return styledString.append(decoratedString.substring(originalStart + label.length()), decorationStyler); } return styledString; // no change } private StyledString getMercurialMatchLabel(MercurialMatch match) { int lineNumber = match.getLineNumber(); String becomesMatch = match.isBecomesMatch() ? "+" : "-"; StyledString str = new StyledString(lineNumber + " (" + becomesMatch + ") ", StyledString.QUALIFIER_STYLER); String content = match.getExtract(); return str.append(content); } private static final int MIN_MATCH_CONTEXT = 10; // minimal number of // characters shown // after and before a // match @Override public Image getImage(Object element) { if (element instanceof MercurialRevisionStorage) { return MercurialEclipsePlugin.getImage("elcl16/changeset_obj.gif"); } if (element instanceof MercurialMatch) { return fLineMatchImage; } if (!(element instanceof IResource)) { return null; } return getResourceImage(element); } /** * @param element * @return */ protected Image getResourceImage(Object element) { IResource resource = (IResource) element; Image image = fLabelProvider.getImage(resource); return image; } @Override public void dispose() { super.dispose(); fLabelProvider.dispose(); } @Override public boolean isLabelProperty(Object element, String property) { return fLabelProvider.isLabelProperty(element, property); } @Override public void removeListener(ILabelProviderListener listener) { super.removeListener(listener); fLabelProvider.removeListener(listener); } @Override public void addListener(ILabelProviderListener listener) { super.addListener(listener); fLabelProvider.addListener(listener); } /** * @param mrs * @return */ protected String getCsInfoString(MercurialRevisionStorage mrs) { ChangeSet cs = mrs.getChangeSet(); String csInfo = cs.getChangesetIndex() + " [" + cs.getAuthor() + "] (" + cs.getAgeDate() + ") "; return csInfo; } } MercurialTextSearchVisitor.java000066400000000000000000000107231173713500500357220ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/search/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian - implementation * Philip Graf - Fixed bugs which FindBugs found *******************************************************************************/ package com.vectrace.MercurialEclipse.search; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.search.core.text.TextSearchRequestor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgGrepClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Bastian * */ public class MercurialTextSearchVisitor { private TextSearchRequestor requestor; private Pattern pattern; /** * */ public MercurialTextSearchVisitor() { } /** * @param requestor * @param searchPattern */ public MercurialTextSearchVisitor(TextSearchRequestor requestor, Pattern searchPattern) { this.requestor = requestor; this.pattern = searchPattern; } /** * @param scope * @param monitor * @return */ public IStatus search(MercurialTextSearchScope scope, IProgressMonitor monitor) { IResource[] scopeRoots = scope.getRoots(); boolean all = scope.isAll(); if (scopeRoots.length == 1 && scopeRoots[0].getParent() == null) { // this is workspace root IWorkspace root = ResourcesPlugin.getWorkspace(); IProject[] projects = root.getRoot().getProjects(); scopeRoots = projects; } Map> resourcesByRoot = ResourceUtils.groupByRoot(Arrays .asList(scopeRoots)); String searchString = pattern.pattern(); monitor.beginTask("Searching for " + searchString + " with Mercurial", scopeRoots.length * 5); for (Entry> entry : resourcesByRoot.entrySet()) { HgRoot root = entry.getKey(); monitor.subTask("Searching in respository " + root.getName()); monitor.worked(1); try { IStatus result = search(root, entry.getValue(), monitor, all); if (!result.isOK()) { return result; } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return new Status(IStatus.ERROR, MercurialEclipsePlugin.ID, e.getLocalizedMessage(), e); } } return new Status(IStatus.OK, MercurialEclipsePlugin.ID, "Mercurial search completed successfully."); } /** * @param root * @param all * @throws CoreException */ private IStatus search(HgRoot root, List resources, IProgressMonitor monitor, boolean all) throws CoreException { try { requestor.beginReporting(); monitor.subTask("Calling Mercurial grep command..."); List result = HgGrepClient.grep(root, pattern.pattern(), resources, all, monitor); monitor.worked(1); monitor.subTask("Processing Mercurial grep results..."); for (MercurialTextSearchMatchAccess sr : result) { if (monitor.isCanceled()){ break; } if (sr.getFile() != null) { monitor.subTask("Found match in: " + sr.getFile().getName()); requestor.acceptFile(sr.getFile()); monitor.worked(1); requestor.acceptPatternMatch(sr); monitor.worked(1); } } } catch (HgException e) { MercurialEclipsePlugin.logError(e); return new Status(IStatus.ERROR, MercurialEclipsePlugin.ID, e.getLocalizedMessage(), e); } requestor.endReporting(); return new Status(IStatus.OK, MercurialEclipsePlugin.ID, "Mercurial search completed successfully."); } /** * @param scope * @param monitor * @return */ public IStatus search(IFile[] scope, IProgressMonitor monitor) { // TODO Auto-generated method stub return null; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/000077500000000000000000000000001173713500500300345ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/DataLoader.java000066400000000000000000000034231173713500500327010ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jérôme Nègre - implementation * Stefan C - Code cleanup * Bastian Doetsch - extracted class since I need it for sync * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.commands.HgBranchClient; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.commands.HgTagClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Tag; public abstract class DataLoader { public abstract HgRoot getHgRoot(); public abstract IResource getResource(); public Tag[] getTags() throws HgException { return HgTagClient.getTags(getHgRoot()); } public Branch[] getBranches() throws HgException { return HgBranchClient.getBranches(getHgRoot()); } public ChangeSet[] getHeads() throws HgException { return HgLogClient.getHeads(getHgRoot()); } public int[] getParents() throws HgException { return HgParentClient.getParents(getHgRoot()); } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/EmptyDataLoader.java000066400000000000000000000026631173713500500337250ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Tag; /** * Simple loader which does nothing * * @author Andrei */ public final class EmptyDataLoader extends DataLoader { @Override public HgRoot getHgRoot() { return null; } @Override public IResource getResource() { return null; } @Override public Branch[] getBranches() throws HgException { return new Branch[0]; } @Override public ChangeSet[] getHeads() throws HgException { return new ChangeSet[0]; } @Override public int[] getParents() throws HgException { return new int[0]; } @Override public Tag[] getTags() throws HgException { return new Tag[0]; } }HgCommitMessageManager.java000066400000000000000000000254561173713500500351430ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zingo Andersen - Save/Load commit messages using a xml file * Adam Berkes (Intland) - Fix encoding * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import org.eclipse.jface.preference.IPreferenceStore; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.helpers.DefaultHandler; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * A manager for all Mercurial commit messages. The commit messages are save to a xml file when * closing down and then re-read when the plugin is started. * */ public class HgCommitMessageManager { /** * commit messages database (keep it simple) */ private static List commitMessages = new ArrayList(); /** * Prefix for the pref store for the hg root default commit name */ public static final String KEY_PREFIX_COMMIT_NAME = "commitName_"; //$NON-NLS-1$ private static final String COMMIT_MESSAGE_FILE = "commit_messages.xml"; //$NON-NLS-1$ private static final String XML_TAG_COMMIT_MESSAGE = "commitmessage"; //$NON-NLS-1$ private static final String XML_TAG_COMMIT_MESSAGES = "commitmessages"; //$NON-NLS-1$ private final XmlHandler xmlHandler; public HgCommitMessageManager() { xmlHandler = new XmlHandler(this); } /** * Save message in in-memory database */ public void saveCommitMessage(String message) { if (commitMessages.contains(message)) { // remove it, and put it in front commitMessages.remove(message); commitMessages.add(0, message); return; } commitMessages.add(0, message); restrictSavedCommitMessages(); } /** * Make sure we don't have more commit messages than are allowed in the plugin prefs. */ private void restrictSavedCommitMessages() { final int prefsCommitMessageSizeMax = Integer.parseInt(MercurialUtilities.getPreference( MercurialPreferenceConstants.COMMIT_MESSAGE_BATCH_SIZE, "10")); //$NON-NLS-1$ while (commitMessages.size() > prefsCommitMessageSizeMax) { commitMessages.remove(commitMessages.size() - 1); } } /** * Save message in in-memory database new data last (used when loading from file) */ private void addCommitMessage(String message) { commitMessages.add(message); restrictSavedCommitMessages(); } /** * Get all messages from in-memory database */ public String[] getCommitMessages() { restrictSavedCommitMessages(); return commitMessages.toArray(new String[0]); } /** * Return a File object representing the location file. The file may or may not * exist and must be checked before use. */ private File getLocationFile() { return MercurialEclipsePlugin.getDefault().getStateLocation().append(COMMIT_MESSAGE_FILE) .toFile(); } /** * Load all saved commit messages from the plug-in's default area. * * @throws HgException */ public void start() throws HgException { File file = getLocationFile(); if (!file.isFile()) { return; } BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), MercurialEclipsePlugin.getDefaultEncoding())); SAXParserFactory parserFactory = SAXParserFactory.newInstance(); parserFactory.setValidating(false); SAXParser parser = parserFactory.newSAXParser(); parser.parse(new InputSource(reader), xmlHandler); } catch (SAXException e) { throw new HgException("Failed to open commit database file: " + file, e); } catch (ParserConfigurationException e) { throw new HgException("Failed to open commit database file: " + file, e); } catch (IOException e) { throw new HgException("Failed to open commit database file: " + file, e); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } } } /** * Save all commit messages from the in-memory database to the plug-in's default area. */ public void stop() throws IOException { File file = getLocationFile(); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file), MercurialEclipsePlugin.getDefaultEncoding())); StreamResult streamResult = new StreamResult(writer); SAXTransformerFactory transformerFactory = (SAXTransformerFactory) TransformerFactory .newInstance(); try { TransformerHandler transformerHandler = transformerFactory.newTransformerHandler(); Transformer transformer = transformerHandler.getTransformer(); transformer.setOutputProperty(OutputKeys.ENCODING, MercurialEclipsePlugin .getDefaultEncoding()); /* * transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,"mercurialeclipse_commitmessage.dtd" * ); //$NON-NLS-1$ */ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ transformerHandler.setResult(streamResult); transformerHandler.startDocument(); AttributesImpl atts = new AttributesImpl(); atts.clear(); transformerHandler.startElement("", "", XML_TAG_COMMIT_MESSAGES, atts); //$NON-NLS-1$ int size = commitMessages.size(); final int prefsCommitMessageSizeMax = Integer.parseInt(MercurialUtilities.getPreference( MercurialPreferenceConstants.COMMIT_MESSAGE_BATCH_SIZE, "10")); //$NON-NLS-1$ /* Do not save more then the prefs size */ if (size > prefsCommitMessageSizeMax) { size = prefsCommitMessageSizeMax; } for (int i = 0; i < size; i++) { String msg = commitMessages.get(i); transformerHandler.startElement("", "", XML_TAG_COMMIT_MESSAGE, atts); //$NON-NLS-1$ transformerHandler.characters(msg.toCharArray(), 0, msg.length()); transformerHandler.endElement("", "", XML_TAG_COMMIT_MESSAGE); //$NON-NLS-1$ } transformerHandler.endElement("", "", XML_TAG_COMMIT_MESSAGES); //$NON-NLS-1$ transformerHandler.endDocument(); } catch (TransformerConfigurationException e) { MercurialEclipsePlugin.logError(e); } catch (IllegalArgumentException e) { MercurialEclipsePlugin.logError(e); } catch (SAXException e) { MercurialEclipsePlugin.logError(e); } writer.close(); } /** * Get the commit name for given root * * @param hgRoot * non null * @return never null, but might be empty */ public static String getDefaultCommitName(HgRoot hgRoot) { // first the stored commit name IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); String commitName = store.getString(getKey(hgRoot)); if (!StringUtils.isEmpty(commitName)) { return commitName; } String defaultUserName = hgRoot.getUser(); if(StringUtils.isEmpty(defaultUserName)){ defaultUserName = MercurialUtilities.getDefaultUserName(); } /* * dependent on the preference, use configured Mercurial name or repository * username (in some corporate environments this seems to be necessary) */ if ("true".equals(MercurialUtilities.getPreference( MercurialPreferenceConstants.PREF_USE_MERCURIAL_USERNAME, "true"))) { return defaultUserName; } IHgRepositoryLocation repoLocation = MercurialEclipsePlugin.getRepoManager() .getDefaultRepoLocation(hgRoot); if (repoLocation != null) { String user = repoLocation.getUser(); if (!StringUtils.isEmpty(user)) { return user; } } return defaultUserName; } public static void setDefaultCommitName(HgRoot hgRoot, String name) { IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); store.setValue(getKey(hgRoot), name); } private static String getKey(HgRoot root) { return HgCommitMessageManager.KEY_PREFIX_COMMIT_NAME + root.getAbsolutePath(); } /** * SAX Handler methods class to handle XML parsing */ private static final class XmlHandler extends DefaultHandler { private final HgCommitMessageManager mgr; private String tmpMessage; private XmlHandler(HgCommitMessageManager mgr) { this.mgr = mgr; } /** * Called when the starting of the Element is reached. For Example if we have Tag called * ... , then this method is called when tag is Encountered while * parsing the Current XML File. The AttributeList Parameter has the list of all Attributes * declared for the Current Element in the XML File. */ @Override public void startElement(String uri, String localName, String qname, Attributes attr) { /* Clear char string */ tmpMessage = ""; //$NON-NLS-1$ } /** * Called when the Ending of the current Element is reached. For example in the above * explanation, this method is called when tag is reached */ @Override public void endElement(String uri, String localName, String qname) { /* If it was a commit message save the char string in the database */ if (qname.equalsIgnoreCase(XML_TAG_COMMIT_MESSAGE)) { mgr.addCommitMessage(tmpMessage); } } /** * While Parsing the XML file, if extra characters like space or enter Character are * encountered then this method is called. If you don't want to do anything special with * these characters, then you can normally leave this method blank. */ @Override public void characters(char[] ch, int start, int length) { /* Collect the char string together this will be called for every special char */ tmpMessage = tmpMessage + new String(ch, start, length); } } } HgRepositoryAuthCrypter.java000066400000000000000000000063141173713500500354550ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2009 Intland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Adam Berkes (Intland) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.utils.Base64Coder; /** * En/Crypt authentication data for a persisted repository * @author adam.berkes */ public class HgRepositoryAuthCrypter { protected static final String DEFAULT_ALGORITHM = "DESede"; private Cipher ecipher; private Cipher dcipher; private String algorithm; HgRepositoryAuthCrypter(SecretKey key) { this(key, DEFAULT_ALGORITHM); } HgRepositoryAuthCrypter(SecretKey key, String algorithm) { try { ecipher = Cipher.getInstance(DEFAULT_ALGORITHM); dcipher = Cipher.getInstance(DEFAULT_ALGORITHM); ecipher.init(Cipher.ENCRYPT_MODE, key); dcipher.init(Cipher.DECRYPT_MODE, key); this.algorithm = algorithm; } catch (javax.crypto.NoSuchPaddingException e) { MercurialEclipsePlugin.logError(e); } catch (java.security.NoSuchAlgorithmException e) { MercurialEclipsePlugin.logError(e); } catch (java.security.InvalidKeyException e) { MercurialEclipsePlugin.logError(e); } } public static SecretKey generateKey() { return generateKey(DEFAULT_ALGORITHM); } public static SecretKey generateKey(String algorithm) { try { return KeyGenerator.getInstance(algorithm).generateKey(); } catch (NoSuchAlgorithmException ex) { MercurialEclipsePlugin.logError(ex); } return null; } public String encrypt(String str) { try { // Encode the string into bytes using utf-8 byte[] utf8 = str.getBytes("UTF8"); // Encrypt byte[] enc = ecipher.doFinal(utf8); return new String(Base64Coder.encode(enc)); } catch (javax.crypto.BadPaddingException e) { MercurialEclipsePlugin.logError(e); } catch (IllegalBlockSizeException e) { MercurialEclipsePlugin.logError(e); } catch (UnsupportedEncodingException e) { MercurialEclipsePlugin.logError(e); } return null; } public String decrypt(String str) { try { // Decode base64 to get bytes byte[] dec = Base64Coder.decode(str); // Decrypt byte[] utf8 = dcipher.doFinal(dec); // Decode using utf-8 return new String(utf8, "UTF8"); } catch (javax.crypto.BadPaddingException e) { MercurialEclipsePlugin.logError(e); } catch (IllegalBlockSizeException e) { MercurialEclipsePlugin.logError(e); } catch (UnsupportedEncodingException e) { MercurialEclipsePlugin.logError(e); } return null; } public String getAlgorithm() { return algorithm; } } HgRepositoryAuthCrypterFactory.java000066400000000000000000000075741173713500500370160ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2009 Intland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Adam Berkes (Intland) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.ArrayList; import java.util.List; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESedeKeySpec; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * Create a new crypter using stored secret key * @author adam.berkes */ public final class HgRepositoryAuthCrypterFactory { public static final String DEFAULT_KEY_FILENAME = ".key"; private HgRepositoryAuthCrypterFactory() { // hide constructor of utility class. } public static HgRepositoryAuthCrypter create(File keyFile) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException { KeySpec keySpec = new DESedeKeySpec(getBytesFromFile(keyFile)); SecretKey key = SecretKeyFactory.getInstance(HgRepositoryAuthCrypter.DEFAULT_ALGORITHM).generateSecret(keySpec); return new HgRepositoryAuthCrypter(key); } public static HgRepositoryAuthCrypter create() { try { File keyFile = MercurialEclipsePlugin.getDefault().getStateLocation().append(DEFAULT_KEY_FILENAME).toFile(); if (keyFile.isFile()) { return create(keyFile); } SecretKey key = HgRepositoryAuthCrypter.generateKey(); writeBytesToFile(key.getEncoded(), keyFile); return new HgRepositoryAuthCrypter(key); } catch (Exception ex) { MercurialEclipsePlugin.logError(ex); } return null; } private static byte[] getBytesFromFile(File file) throws IOException { BufferedInputStream is = new BufferedInputStream(new FileInputStream(file)); try { long length = file.length(); byte[] bytes = new byte[(int) length]; int offset = 0; int numRead = 0; while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { offset += numRead; } if (offset < bytes.length) { throw new IOException("Could not completely read file " + file.getName()); } return bytes; } finally { is.close(); } } protected static void writeBytesToFile(byte[] content, File file) throws IOException { BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file)); try { os.write(content, 0, content.length); } finally { os.close(); secureKeyFile(file); } } private static void secureKeyFile(File file) { // Ensure file availability only for user List chmod = new ArrayList(3); if (File.separatorChar == '\\') { chmod.add("cacls"); chmod.add(file.getAbsolutePath()); chmod.add("/T"); chmod.add("/G"); // TODO: find a better method as it is a possible security hole. // property can be overridden at eclipse startup. chmod.add(System.getProperty("user.name") + ":f"); chmod.add("/R"); chmod.add("Everyone"); } else { chmod.add("chmod"); chmod.add("600"); chmod.add(file.getAbsolutePath()); } try { Runtime.getRuntime().exec(chmod.toArray(new String[] {})); } catch (IOException ex) { MercurialEclipsePlugin.logError("Unable to set permission on file", ex); } } } HgRepositoryLocation.java000066400000000000000000000165401173713500500347550ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Balm Consulting Inc (Peter Hunnisett ) - implementation * Stefan C - Code cleanup * Bastian Doetsch - additions for repository view * Subclipse contributors - fromProperties() initial source * Adam Berkes (Intland) - bug fixes * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.model.IWorkbenchAdapter; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; /** * A class abstracting a Mercurial repository location which may be either local * or remote. */ public class HgRepositoryLocation implements Comparable, IHgRepositoryLocation { private static final String PASSWORD_MASK = "***"; private String logicalName; protected String location; private String user; private String password; private boolean isLocal; /** * hg repository which is represented by a bundle file (on local disk) */ public static class BundleRepository extends HgRepositoryLocation { /** * @param location canonical representation of a bundle file path, never null */ public BundleRepository(File location) { super(null, null, null); this.location = location.getAbsolutePath(); } @Override protected URI getUri(boolean isSafe) throws HgException { return null; } @Override public boolean isLocal() { return true; } } private HgRepositoryLocation(String logicalName, String user, String password){ super(); this.logicalName = logicalName; this.user = user; this.password = password; } HgRepositoryLocation(String logicalName, String location, String user, String password) throws HgException { this(logicalName, user, password); URI uri = HgRepositoryLocationParser.parseLocationToURI(location, user, password); if(uri != null) { isLocal = uri.getScheme() == null || uri.getScheme().equalsIgnoreCase("file"); try { this.location = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), uri.getPath(), null, uri.getFragment()).toASCIIString(); } catch (URISyntaxException ex) { MercurialEclipsePlugin.logError(ex); } } else { this.location = location; isLocal = true; } } HgRepositoryLocation(String logicalName, URI uri) throws HgException { this(logicalName, HgRepositoryLocationParser.getUserNameFromURI(uri), HgRepositoryLocationParser.getPasswordFromURI(uri)); if (uri == null) { throw new HgException("Given URI cannot be null"); } isLocal = uri.getScheme() == null || uri.getScheme().equalsIgnoreCase("file"); try { this.location = new URI(uri.getScheme(), null, uri.getHost(), uri.getPort(), uri.getPath(), null, uri.getFragment()).toASCIIString(); } catch (URISyntaxException ex) { MercurialEclipsePlugin.logError(ex); } } public static boolean validateLocation(String validate) { try { IHgRepositoryLocation location2 = HgRepositoryLocationParser.parseLocation(validate, null, null); if(location2 == null){ return false; } return location2.getUri() != null || (location2.getLocation() != null && new File(location2.getLocation()).exists()); } catch (HgException ex) { MercurialEclipsePlugin.logError(ex); return false; } } public int compareTo(File loc) { if(getLocation() == null) { return -1; } if(loc == null){ return 1; } return getLocation().compareTo(loc.getAbsolutePath()); } public int compareTo(IHgRepositoryLocation loc) { if(getLocation() == null) { return -1; } if(loc.getLocation() == null){ return 1; } return getLocation().compareTo(loc.getLocation()); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((location == null) ? 0 : location.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof IHgRepositoryLocation)) { return false; } final IHgRepositoryLocation other = (IHgRepositoryLocation) obj; if (location == null) { if (other.getLocation() != null) { return false; } } else if (!location.equals(other.getLocation())) { return false; } return true; } public String getUser() { return user; } public String getPassword() { return password; } /** * Return unsafe (with password) URI for repository location if possible * @return a valid URI of the repository or null if repository is local directory * @throws HgException unable to parse to URI or location is invalid. */ public URI getUri() throws HgException { return getUri(false); } /** * Return URI for repository location if possible * @param isSafe add password to userinfo if false or add a mask instead * @return a valid URI of the repository or null if repository is local directory * @throws HgException unable to parse to URI or location is invalid. */ protected URI getUri(boolean isSafe) throws HgException { return HgRepositoryLocationParser.parseLocationToURI(getLocation(), getUser(), isSafe ? PASSWORD_MASK : getPassword()); } @Override public String toString() { return location; } public Object[] getChildren(Object o) { HgRoot hgRoot = toHgRoot(); if(hgRoot != null){ // local repo with one single root return new Object[]{ hgRoot }; } // remote repo with possible multiple roots on local file system return MercurialEclipsePlugin.getRepoManager().getAllRepoLocationRoots(this).toArray( new IHgRepositoryLocation[0]); } public HgRoot toHgRoot() { if(isLocal()){ try { return new HgRoot(getLocation()); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } return null; } public String getLocation() { return location; } public String getLogicalName() { return logicalName; } @SuppressWarnings("rawtypes") public Object getAdapter(Class adapter) { if(adapter == IHgRepositoryLocation.class){ return this; } if (adapter == IWorkbenchAdapter.class) { return this; } return null; } public void setPassword(String password) { this.password = password; } public void setUser(String user) { this.user = user; } public void setLogicalName(String logicalName) { this.logicalName = logicalName; } public String getLabel(Object o) { return o.toString(); } public Object getParent(Object o) { return null; } public ImageDescriptor getImageDescriptor(Object object) { return MercurialEclipsePlugin.getImageDescriptor("cview16/repository_rep.gif"); } public boolean isLocal() { return isLocal; } } HgRepositoryLocationManager.java000066400000000000000000000553061173713500500362530ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Balm Consulting Inc (Peter Hunnisett ) - implementation * Stefan Groschupf - logError * Jerome Negre - storing in plain text instead of serializing Java Objects * Bastian Doetsch - support for project specific repository locations * Adam Berkes (Intland) - bug fixes * Ilya Ivanov (Intland) - bug fixes * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.team.core.RepositoryProvider; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgPathsClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.repository.IRepositoryListener; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * A manager for all Mercurial repository locations. *

* Initially, all the data was stored in the file system and was project based. One file per project * plus one file for all repositories. This lead to unneeded overhead/complexity for the case where * 100 projects under the same root was managed with 100 files with redundant or partly different * information. *

* Right now the data stored in the plugin preferences and is hg root based. The repo data is stored * twice: once the default repo for each hg root (if any) and secondly as a list of all available * repositories. *

* Repositories are considered unique by comparing their URL's (without the login info). Hg roots * are considered unique by their absolut hg root paths. Projects are not tracked here anymore, as * they always inherit hg root account/repo information. *

* Additionally, we store default commit names for each hg root, which may be different to the hg * push/pull user names. The reason is that commit name (like 'Andrei@Loskutov.com') may be same for * different repositories, but the 'push' user name must be different due the different account * names which may exist for different repositories (like 'hgeclipse' or 'iloveeclipse' for * bitbucket or javaforge). See {@link HgCommitMessageManager}. *

* P.S. * All sets which contain IHgRepositoryLocation are implemented NOT as SortedSet's due the * fact that SortedSet/TreeMap are using compareTo(Object) for 'get' operations. * HgRoot extends File which contains synthetic compareTo(Object). Unfortunately, * this method can NOT be overridden and unfortunately it is used instead of compareTo(File). * So to avoid ClassCastExceptions we can't use SortedSet's for IHgRepositoryLocation's. */ public class HgRepositoryLocationManager { private static final String KEY_REPOS_PREFIX = "repo_"; //$NON-NLS-1$ private static final String KEY_DEF_REPO_PREFIX = "def_" + KEY_REPOS_PREFIX; //$NON-NLS-1$ private final Map> rootRepos; private final Set repoHistory; private final HgRepositoryLocationParserDelegator delegator; private final Object entriesLock; private volatile boolean initialized; private final List repositoryListeners; public HgRepositoryLocationManager() { super(); entriesLock = new Object(); repositoryListeners = new ArrayList(); rootRepos = new ConcurrentHashMap>(); repoHistory = new LinkedHashSet(); delegator = new HgRepositoryLocationParserDelegator(); } /** * Load all saved repository locations from the plug-in's default area. * * @throws HgException */ public void start() throws HgException { getProjectRepos(); } /** * Flush all repository locations out to a file in the plug-in's default * area. */ public void stop() { saveProjectRepos(); saveRepositoryHistory(); } /** * Return an ordered list of all repository locations that are presently * known. */ public Set getAllRepoLocations() { Set allRepos = new LinkedHashSet(); rootRepos.keySet(); synchronized (entriesLock){ for (Set locations : rootRepos.values()) { allRepos.addAll(locations); } } synchronized (repoHistory) { allRepos.addAll(repoHistory); } return allRepos; } // TODO ME doesn't update rootRepos map until workbench restart. // Map should be updated after every clone operation public Set getAllRepoRoots() { Set allRoots = new LinkedHashSet(); synchronized (entriesLock) { allRoots.addAll(rootRepos.keySet()); } return allRoots; } public Set getAllRepoLocations(HgRoot hgRoot) { if(hgRoot == null){ return new LinkedHashSet(); } Set loc = rootRepos.get(hgRoot); if(loc != null) { return Collections.unmodifiableSet(loc); } return new LinkedHashSet(); } /** * @param repo non null repo location * @return a set of projects we know managed at given location, never null */ public Set getAllRepoLocationProjects(IHgRepositoryLocation repo) { Set projects = new LinkedHashSet(); try { getProjectRepos(); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } Set>> entrySet = rootRepos.entrySet(); for (Entry> entry : entrySet) { Set set = entry.getValue(); if (set != null && set.contains(repo)) { projects.addAll(ResourceUtils.getProjects(entry.getKey())); } } if(projects.isEmpty() && repo.isLocal()) { HgRoot hgRoot = repo.toHgRoot(); if(hgRoot != null) { projects.addAll(MercurialTeamProvider.getKnownHgProjects(hgRoot)); } } return projects; } /** * @param repo non null repo location * @return a set of projects we know managed at given location, never null */ public Set getAllRepoLocationRoots(IHgRepositoryLocation repo) { Set roots = new LinkedHashSet(); try { getProjectRepos(); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } Set>> entrySet = rootRepos.entrySet(); for (Entry> entry : entrySet) { Set set = entry.getValue(); if(set != null && set.contains(repo)){ roots.add(entry.getKey()); } } return Collections.unmodifiableSet(roots); } /** * Add a repository location to the database. */ private boolean addRepoLocation(IHgRepositoryLocation loc) { return internalAddRepoLocation((HgRoot) null, loc); } /** * Add a repository location to the database without to triggering loadRepos again */ private boolean internalAddRepoLocation(HgRoot hgRoot, IHgRepositoryLocation loc) { if (isEmpty(loc)) { return false; } if (hgRoot != null) { Set repoSet = rootRepos.get(hgRoot); if (repoSet == null) { repoSet = new LinkedHashSet(); } synchronized (entriesLock){ repoSet.remove(loc); repoSet.add(loc); } rootRepos.put(hgRoot, repoSet); } synchronized (repoHistory) { repoHistory.remove(loc); repoHistory.add(loc); } repositoryAdded(loc); return true; } private static boolean isEmpty(IHgRepositoryLocation loc) { return loc == null || (loc.getLocation() == null || loc.getLocation().length() == 0); } /** * Add a repository location to the database. Associate a repository * location to a particular hg root. * * @throws HgException */ public boolean addRepoLocation(HgRoot hgRoot, IHgRepositoryLocation loc) throws HgException { boolean result = internalAddRepoLocation(hgRoot, loc); if(result && hgRoot != null && getDefaultRepoLocation(hgRoot) == null){ setDefaultRepository(hgRoot, loc); } return result; } private void getProjectRepos() throws HgException { if (!initialized) { initialized = true; loadRepos(); loadRepositoryHistory(); } } private static List getAllProjects(){ List projects = new ArrayList(); IProject[] iProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject project : iProjects) { if(RepositoryProvider.isShared(project)){ projects.add(project); } } return projects; } /** * @return set with ALL projects managed by hg, not only projects for which we know remote repo locations * @throws HgException */ private Map> loadRepos() throws HgException { rootRepos.clear(); List projects = getAllProjects(); Map> roots = ResourceUtils.groupByRoot(projects); for (Entry> entry : roots.entrySet()) { HgRoot hgRoot = entry.getKey(); loadRepos(hgRoot); } return roots; } public void loadRepos(HgRoot hgRoot) throws HgException { // Load .hg/hgrc paths first; plugin settings will override these Map hgrcRepos = HgPathsClient.getPaths(hgRoot); for (Map.Entry nameAndUrl : hgrcRepos.entrySet()) { String url = nameAndUrl.getValue(); IHgRepositoryLocation repoLocation = matchRepoLocation(url); if(repoLocation == null) { // if not existent, add to repository browser try { String logicalName = nameAndUrl.getKey(); IHgRepositoryLocation loc = updateRepoLocation(hgRoot, url, logicalName, null, null); internalAddRepoLocation(hgRoot, loc); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } } Set locations = loadRepositories(getRootKey(hgRoot)); for(IHgRepositoryLocation loc : locations) { internalAddRepoLocation(hgRoot, loc); } // IHgRepositoryLocation defRepo = getDefaultRepoLocation(hgRoot); // if(defRepo == null && !locations.isEmpty()){ // setDefaultRepository(hgRoot, locations.first()); // } } private void loadRepositoryHistory() { Set locations = loadRepositories(KEY_REPOS_PREFIX); for (IHgRepositoryLocation loc : locations) { boolean usedByProject = false; Set>> entrySet = rootRepos.entrySet(); for (Entry> entry : entrySet) { Set set = entry.getValue(); if (set != null && set.contains(loc)) { usedByProject = true; break; } } synchronized (repoHistory) { repoHistory.remove(loc); repoHistory.add(loc); } if (!usedByProject) { repositoryAdded(loc); } } } private Set loadRepositories(String key) { Set locations = new LinkedHashSet(); IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); String allReposLine = store.getString(key); if(StringUtils.isEmpty(allReposLine)){ return locations; } String[] repoLine = allReposLine.split("\\|"); for (String line : repoLine) { if(line == null || line.length() == 0){ continue; } try { IHgRepositoryLocation loc = delegator.delegateParse(line); if(loc != null) { locations.add(loc); } } catch (Exception e) { // log exception, but don't bother the user with it. MercurialEclipsePlugin.logError(e); } } return locations; } /** * Set given location as default (topmost in hg repositories) * @param hgRoot a valid hg root (not null) * @param loc a valid repoository location (not null) */ public void setDefaultRepository(HgRoot hgRoot, IHgRepositoryLocation loc) { Assert.isNotNull(hgRoot); Assert.isNotNull(loc); Set locations = rootRepos.get(hgRoot); IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); store.setValue(KEY_DEF_REPO_PREFIX + getRootKey(hgRoot), loc.getLocation()); if (locations != null && !locations.contains(loc)) { synchronized (entriesLock){ locations.add(loc); } } else { internalAddRepoLocation(hgRoot, loc); } } /** * Returns the default repository location for a hg root, if it is set. * @return may return null */ public IHgRepositoryLocation getDefaultRepoLocation(HgRoot hgRoot) { IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); String defLoc = store.getString(KEY_DEF_REPO_PREFIX + getRootKey(hgRoot)); if(StringUtils.isEmpty(defLoc)){ return null; } Set locations = rootRepos.get(hgRoot); if (locations != null && !locations.isEmpty()) { synchronized (entriesLock){ for (IHgRepositoryLocation repo : locations) { if(repo.getLocation().equals(defLoc)){ return repo; } } } } for (IHgRepositoryLocation repo : repoHistory) { if(repo.getLocation().equals(defLoc)){ internalAddRepoLocation(hgRoot, repo); return repo; } } return null; } private String getRootKey(HgRoot root) { return KEY_REPOS_PREFIX + root.getAbsolutePath(); } private void saveProjectRepos() { List projects = getAllProjects(); Map> byRoot = ResourceUtils.groupByRoot(projects); Set roots = byRoot.keySet(); for (HgRoot hgRoot : roots) { String key = getRootKey(hgRoot); Set repoSet = rootRepos.get(hgRoot); if(repoSet == null){ continue; } synchronized (entriesLock){ repoSet = new LinkedHashSet(repoSet); } saveRepositories(key, repoSet); } } private void saveRepositoryHistory() { saveRepositories(KEY_REPOS_PREFIX, repoHistory); } private void saveRepositories(String key, Set locations) { if (locations == null || locations.isEmpty()) { return; } IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); StringBuilder sb = new StringBuilder(); for (IHgRepositoryLocation repo : locations) { String line = delegator.delegateCreate(repo); if(line != null){ sb.append(line); sb.append('|'); } } store.setValue(key, sb.toString()); } /** * Get a repo by its URL. If URL is unknown, returns a new location. * @return never returns null */ public IHgRepositoryLocation getRepoLocation(String url) throws HgException { return getRepoLocation(url, null, null); } /** * Get a repo by its URL. If URL is unknown, returns a new location. * @return never returns null */ public IHgRepositoryLocation getRepoLocation(String url, String user, String pass) throws HgException { getProjectRepos(); IHgRepositoryLocation location = matchRepoLocation(url); if (location != null) { if (user == null || user.length() == 0 || (user.equals(location.getUser()) && (pass == null || pass.equals(location.getPassword())))) { return location; } } // make a new location if no matches exist or it's a different user return HgRepositoryLocationParser.parseLocation(url, user, pass); } /** * Get a repo specified by properties. If repository for given url is unknown, * returns a new location. * @return never returns null */ public IHgRepositoryLocation getRepoLocation(Properties props) throws HgException { String user = props.getProperty("user"); //$NON-NLS-1$ if ((user == null) || (user.length() == 0)) { user = null; } String password = props.getProperty("password"); //$NON-NLS-1$ if (user == null) { password = null; } String url = props.getProperty("url"); //$NON-NLS-1$ if (url == null) { throw new HgException(Messages .getString("HgRepositoryLocation.urlMustNotBeNull")); //$NON-NLS-1$ } IHgRepositoryLocation location = matchRepoLocation(url); if (location != null) { if (user == null || user.length() == 0 || (user.equals(location.getUser()) && (password == null || password.equals(location.getPassword())))) { return location; } } // make a new location if no matches exist or it's a different user return HgRepositoryLocationParser.parseLocation(url, user, password); } /** * Simple search on existing repos. * @return may return null */ private IHgRepositoryLocation matchRepoLocation(String url) { url = HgRepositoryLocationParser.trimLocation(url); if (StringUtils.isEmpty(url)) { return null; } for (IHgRepositoryLocation loc : getAllRepoLocations()) { if (url.equals(loc.getLocation())) { return loc; } } return null; } /** * Gets a repo by its URL. If URL is unknown, returns a new location, * adding it to the global repositories cache. Will update stored * last user and password with the provided values. */ public IHgRepositoryLocation updateRepoLocation(HgRoot hgRoot, String url, String logicalName, String user, String pass) throws HgException { IHgRepositoryLocation loc = matchRepoLocation(url); if (loc == null) { // in some cases url may be a repository database line loc = HgRepositoryLocationParser.parseLocation(logicalName, url, user, pass); addRepoLocation(loc); return loc; } boolean update = false; String myLogicalName = logicalName; String myUser = user; String myPass = pass; if (logicalName != null && logicalName.length() > 0 && !logicalName.equals(loc.getLogicalName())) { update = true; } else { myLogicalName = loc.getLogicalName(); } if (user != null && user.length() > 0 && !user.equals(loc.getUser())) { update = true; } else { myUser = loc.getUser(); } if (pass != null && pass.length() > 0 && !pass.equals(loc.getPassword())) { update = true; } else { myPass = loc.getPassword(); } if (update) { IHgRepositoryLocation updated = HgRepositoryLocationParser.parseLocation(myLogicalName, loc.getLocation(), myUser, myPass); synchronized (entriesLock){ for (Set locs : rootRepos.values()) { if (locs.remove(updated)) { locs.add(updated); } } } synchronized (repoHistory) { if (repoHistory.remove(updated)) { repoHistory.add(updated); } } repositoryModified(updated); return updated; } return loc; } /** * Create a repository location instance from the given properties. The * supported properties are: user The username for the connection (optional) * password The password used for the connection (optional) url The url * where the repository resides */ public IHgRepositoryLocation fromProperties(HgRoot hgRoot, Properties configuration) throws HgException { String user = configuration.getProperty("user"); //$NON-NLS-1$ if ((user == null) || (user.length() == 0)) { user = null; } String password = configuration.getProperty("password"); //$NON-NLS-1$ if (user == null) { password = null; } String url = configuration.getProperty("url"); //$NON-NLS-1$ if (url == null) { throw new HgException(Messages.getString("HgRepositoryLocation.urlMustNotBeNull")); //$NON-NLS-1$ } return updateRepoLocation(hgRoot, url, null, user, password); } public void refreshRepositories(IProgressMonitor monitor) throws HgException { stop(); start(); } /** * Create a repository instance from the given properties. The supported * properties are: * * user The username for the connection (optional) password The password * used for the connection (optional) url The url where the repository * resides */ public IHgRepositoryLocation createRepository(Properties configuration) throws HgException { // Create a new repository location IHgRepositoryLocation location = fromProperties(null, configuration); addRepoLocation(location); return location; } public void disposeRepository(IHgRepositoryLocation hgRepo) { Assert.isNotNull(hgRepo); for (HgRoot hgRoot : rootRepos.keySet()) { Set pRepos = rootRepos.get(hgRoot); if (pRepos != null) { boolean removed = false; synchronized (entriesLock){ for (IHgRepositoryLocation repo : pRepos) { if (repo.equals(hgRepo)) { removed = pRepos.remove(repo); break; } } } if(removed) { repositoryRemoved(hgRepo); } } } IHgRepositoryLocation removed = null; synchronized (repoHistory) { for (IHgRepositoryLocation loc : repoHistory) { if (loc.equals(hgRepo)) { repoHistory.remove(loc); removed = loc; break; } } } if(removed != null) { repositoryRemoved(removed); } } /** * Register to receive notification of repository creation and disposal */ public void addRepositoryListener(IRepositoryListener listener) { repositoryListeners.add(listener); } /** * De-register a listener */ public void removeRepositoryListener(IRepositoryListener listener) { repositoryListeners.remove(listener); } /** * signals all listener that we have removed a repository */ private void repositoryRemoved(IHgRepositoryLocation repository) { Iterator it = repositoryListeners.iterator(); while (it.hasNext()) { IRepositoryListener listener = it.next(); listener.repositoryRemoved(repository); } } /** * signals all listener that we have removed a repository */ private void repositoryAdded(IHgRepositoryLocation repository) { Iterator it = repositoryListeners.iterator(); while (it.hasNext()) { IRepositoryListener listener = it.next(); listener.repositoryAdded(repository); } } /** * signals all listener that we have removed a repository */ private void repositoryModified(IHgRepositoryLocation repository) { Iterator it = repositoryListeners.iterator(); while (it.hasNext()) { IRepositoryListener listener = it.next(); listener.repositoryModified(repository); } } } HgRepositoryLocationParser.java000066400000000000000000000233771173713500500361400ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2009 Intland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Adam Berkes (Intland) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * Repository location line format: * [u|d] uri [e] username [e] password alias/id */ public final class HgRepositoryLocationParser { protected static final String PART_SEPARATOR = " "; protected static final String SPLIT_TOKEN = "@@@"; protected static final String ALIAS_TOKEN = "@alias@"; protected static final String PASSWORD_TOKEN = ":"; protected static final String PUSH_PREFIX = "u"; protected static final String PULL_PREFIX = "d"; protected static final String ENCRYPTED_PREFIX = "e"; private HgRepositoryLocationParser() { // hide constructor of utility class. } public static String trimLocation(String url){ if(url == null){ return null; } url = url.trim(); // this is NOT File.separator: we simply disallow to have different locations // which just ends with slash/backslash while(url.endsWith("/") || url.endsWith("\\") || url.endsWith(" ")){ url = url.substring(0, url.length() - 1); } return url; } protected static IHgRepositoryLocation parseLine(final String line) { if (line == null || line.length() < 1) { return null; } String repositoryLine = line; // get direction indicator: OBSOLETED. It does not make sense to save this attribute on the repo. // unfortunately if was released with 1.5.0, so simply read the first character // String direction = repositoryLine.substring(0,1); repositoryLine = repositoryLine.substring(1); try { List parts = new ArrayList(5); while (repositoryLine != null && repositoryLine.length() > 0) { int len = Integer.valueOf(repositoryLine.substring(0, repositoryLine.indexOf(PART_SEPARATOR))).intValue(); repositoryLine = repositoryLine.substring(repositoryLine.indexOf(PART_SEPARATOR) + 1); String partValue = repositoryLine.substring(0, len); repositoryLine = repositoryLine.substring(repositoryLine.length() > len ? len + 1 : repositoryLine.length()); parts.add(partValue); } HgRepositoryAuthCrypter crypter = HgRepositoryAuthCrypterFactory.create(); String username = parts.get(1); if (username.startsWith(ENCRYPTED_PREFIX + PART_SEPARATOR)) { username = crypter.decrypt(username.substring(2)); } String password = parts.get(2); if (password.startsWith(ENCRYPTED_PREFIX + PART_SEPARATOR)) { password = crypter.decrypt(password.substring(2)); } String locationStr = trimLocation(parts.get(0)); URI uri = parseLocationToURI(locationStr, username, password); IHgRepositoryLocation location; if(uri != null) { location = new HgRepositoryLocation(parts.get(3), uri); } else { location = new HgRepositoryLocation(parts.get(3), locationStr, "", ""); } return location; } catch(Throwable th) { MercurialEclipsePlugin.logError(th); return null; } } protected static String createLine(final IHgRepositoryLocation location) { StringBuilder line = new StringBuilder(PULL_PREFIX); // remove authentication from location line.append(String.valueOf(location.getLocation().length())); line.append(PART_SEPARATOR); line.append(location.getLocation()); line.append(PART_SEPARATOR); HgRepositoryAuthCrypter crypter = HgRepositoryAuthCrypterFactory.create(); String user = location.getUser() != null ? location.getUser() : ""; if (user.length() > 0) { user = ENCRYPTED_PREFIX + PART_SEPARATOR + crypter.encrypt(user); } line.append(String.valueOf(user.length())); line.append(PART_SEPARATOR); line.append(user); line.append(PART_SEPARATOR); String password = location.getPassword() != null ? location.getPassword() : ""; if (password.length() > 0) { password = ENCRYPTED_PREFIX + PART_SEPARATOR + crypter.encrypt(password); } line.append(String.valueOf(password.length())); line.append(PART_SEPARATOR); line.append(password); line.append(PART_SEPARATOR); String logicalName = location.getLogicalName() != null ? location.getLogicalName() : ""; line.append(String.valueOf(logicalName.length())); line.append(PART_SEPARATOR); line.append(logicalName); return line.toString(); } protected static IHgRepositoryLocation parseLocation(String logicalName, String location, String user, String password) throws HgException { return parseLine(logicalName, location, user, password); } protected static IHgRepositoryLocation parseLocation(String location, String user, String password) throws HgException { return parseLocation(null, location, user, password); } protected static IHgRepositoryLocation parseLine(String logicalName, String location, String user, String password) throws HgException { if(StringUtils.isEmpty(location)){ throw new HgException("Empty location for " + logicalName + " (user:" + user +")!"); } String[] repoInfo = location.split(SPLIT_TOKEN); if ((user == null || user.length() == 0) && repoInfo.length > 1) { String userInfo = repoInfo[1]; if (userInfo.contains(ALIAS_TOKEN)) { userInfo = userInfo.substring(0, userInfo.indexOf(ALIAS_TOKEN)); } String[] splitUserInfo = userInfo.split(PASSWORD_TOKEN, 2); user = splitUserInfo[0]; if (splitUserInfo.length > 1) { password = splitUserInfo[1]; } else { password = null; } location = repoInfo[0]; } String[] alias = location.split(ALIAS_TOKEN); if (alias.length == 2 && (logicalName == null || logicalName.length() == 0)) { logicalName = alias[1]; if (location.contains(ALIAS_TOKEN)) { location = location.substring(0, location.indexOf(ALIAS_TOKEN)); } } location = trimLocation(location); URI uri = parseLocationToURI(location, user, password); if (uri != null) { return new HgRepositoryLocation(logicalName, uri); } return new HgRepositoryLocation(logicalName, location, user, password); } protected static URI parseLocationToURI(String location, String user, String password) throws HgException { URI uri = null; try { uri = new URI(location); } catch (URISyntaxException e) { // Bastian: we can't filter for directories only, as bundle-files are valid repositories // as well. So only check if file exists. // Most possibly windows path, return null File localPath = new File(location); if (localPath.exists()) { return null; } throw new HgException("Hg repository location invalid: <" + location + ">"); } if (uri.getScheme() != null && !uri.getScheme().equalsIgnoreCase("file")) { //$NON-NLS-1$ String userInfo = null; if (uri.getUserInfo() != null) { // extract user and password from given URI String[] authorization = uri.getUserInfo().split(":", 2); //$NON-NLS-1$ user = authorization[0]; if (authorization.length > 1) { password = authorization[1]; } } // This is a hack: ssh doesn't allow us to directly enter // in passwords in the URI (even though it says it does) if (uri.getScheme().equalsIgnoreCase("ssh")) { // Do not provide empty strings as user name: see issue #11828 if (!StringUtils.isEmpty(user)) { userInfo = user; } } else { userInfo = createUserinfo(user, password); } try { return new URI(uri.getScheme(), userInfo, uri.getHost(), uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); } catch (URISyntaxException ex) { HgException hgex = new HgException("Failed to parse hg repository: <" + location + ">", ex); hgex.initCause(ex); throw hgex; } } return uri; } protected static String getUserNameFromURI(URI uri) { String userInfo = uri != null ? uri.getUserInfo() : null; if (userInfo != null) { if (userInfo.indexOf(PASSWORD_TOKEN) > 0) { return userInfo.substring(0, userInfo.indexOf(PASSWORD_TOKEN)); } return userInfo; } return null; } protected static String getPasswordFromURI(URI uri) { String userInfo = uri != null ? uri.getUserInfo() : null; if (userInfo != null) { if (userInfo.indexOf(PASSWORD_TOKEN) > 0) { return userInfo.substring(userInfo.indexOf(PASSWORD_TOKEN) + 1); } // NEVER return the username as password return ""; } return null; } private static String createUserinfo(String user1, String password1) { String userInfo = null; if (user1 != null && user1.length() > 0) { // pass gotta be separated by a colon if (password1 != null && password1.length() != 0) { userInfo = user1 + PASSWORD_TOKEN + password1; } else { userInfo = user1; } } return userInfo; } @Deprecated public static String createSaveString(IHgRepositoryLocation location) { StringBuilder line = new StringBuilder(location.getLocation()); if (location.getUser() != null) { line.append(SPLIT_TOKEN); line.append(location.getUser()); if (location.getPassword() != null) { line.append(PASSWORD_TOKEN); line.append(location.getPassword()); } } if (location.getLogicalName() != null && location.getLogicalName().length() > 0) { line.append(ALIAS_TOKEN); line.append(location.getLogicalName()); } return line.toString(); } } HgRepositoryLocationParserDelegator.java000066400000000000000000000030461173713500500377560ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2009 Intland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Adam Berkes (Intland) - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; /** * Delegates work of parsing persisted hg repository location to the * appropriate class/method * * @author adam.berkes */ public class HgRepositoryLocationParserDelegator { public IHgRepositoryLocation delegateParse(String line) { if (line != null) { if(line.startsWith(HgRepositoryLocationParser.PUSH_PREFIX) || line.startsWith(HgRepositoryLocationParser.PULL_PREFIX)) { return HgRepositoryLocationParser.parseLine(line); } try { return HgRepositoryLocationParser.parseLine(null, line, null, null); } catch (HgException ex) { MercurialEclipsePlugin.logError("Unable to parse repository line <" + line + ">", ex); } } return null; } public String delegateCreate(IHgRepositoryLocation location) { return HgRepositoryLocationParser.createLine(location); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/Messages.java000066400000000000000000000021221173713500500324430ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.storage.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } ResourceDataLoader.java000066400000000000000000000023551173713500500343350ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ge.zhong implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * @author Ge Zhong * */ public class ResourceDataLoader extends DataLoader { private final IResource resource; public ResourceDataLoader(IResource resource) { this.resource = resource; } /** * @see com.vectrace.MercurialEclipse.storage.DataLoader#getHgRoot() */ @Override public HgRoot getHgRoot() { return MercurialTeamProvider.getHgRoot(resource); } /** * @see com.vectrace.MercurialEclipse.storage.DataLoader#getResource() */ @Override public IResource getResource() { return resource; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/RootDataLoader.java000066400000000000000000000016411173713500500335450ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.model.HgRoot; public class RootDataLoader extends DataLoader { private final HgRoot hgRoot; public RootDataLoader(HgRoot hgRoot) { this.hgRoot = hgRoot; } @Override public IResource getResource() { return null; } @Override public HgRoot getHgRoot() { return hgRoot; } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/storage/messages.properties000066400000000000000000000002131173713500500337550ustar00rootroot00000000000000HgRepositoryLocation.urlMustNotBeNull=URL must not be null. HgRepositoryLocationManager.couldntCreate=Couldn't create repository location. eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/000077500000000000000000000000001173713500500307435ustar00rootroot00000000000000DelayedSyncInfo.java000066400000000000000000000077611173713500500345620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.team.core.diff.IDiff; import org.eclipse.team.core.diff.ITwoWayDiff; import org.eclipse.team.core.diff.provider.TwoWayDiff; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.core.mapping.IResourceDiff; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.core.variants.IResourceVariant; import org.eclipse.team.core.variants.IResourceVariantComparator; import org.eclipse.team.internal.core.mapping.ResourceVariantFileRevision; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.compare.RevisionNode; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.team.NullRevision; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Andrei */ public class DelayedSyncInfo extends MercurialSyncInfo { private final HgRoot root; private final String currentBranch; private final IHgRepositoryLocation repo; private IResourceVariant delayedBase; private IResourceVariant delayedRemote; private DelayedDiff delayedDiff; public DelayedSyncInfo(IFile local, HgRoot root, String currentBranch, IHgRepositoryLocation repo, IResourceVariantComparator comparator, int description) { super(local, null, null, comparator, description); this.root = root; this.currentBranch = currentBranch; this.repo = repo; try { init(); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } private void initBaseAndRemote(){ IFile file = (IFile) getLocal(); SyncInfo syncInfo = MercurialSynchronizeSubscriber.getSyncInfo(file, root, currentBranch, repo); if(syncInfo != null){ delayedBase = syncInfo.getBase(); delayedRemote = syncInfo.getRemote(); } else { delayedBase = new MercurialResourceVariant(new RevisionNode(ResourceUtils.convertToHgFile(new NullRevision(file, null)))); delayedRemote = new MercurialResourceVariant(new RevisionNode(ResourceUtils.convertToHgFile(new NullRevision(file, null)))); } } @Override public IResourceVariant getBase() { if(delayedBase == null) { initBaseAndRemote(); } return delayedBase; } @Override public IResourceVariant getRemote() { if(delayedRemote == null) { initBaseAndRemote(); } return delayedRemote; } // here to avoid FindBugs warnings @Override public boolean equals(Object other) { return super.equals(other); } @Override public int hashCode() { return super.hashCode(); } public IDiff getDiff(){ if(delayedDiff == null){ delayedDiff = new DelayedDiff(); } return delayedDiff; } // TODO right now incoming/outgoing arrows are not shown as icon overlays // I guess we must use ThreeWayDiff for this... @SuppressWarnings("restriction") public class DelayedDiff extends TwoWayDiff implements IResourceDiff { public DelayedDiff() { super(getLocal().getFullPath(), IDiff.CHANGE, ITwoWayDiff.CONTENT); } public IFileRevision getAfterState() { ResourceVariantFileRevision revision = new ResourceVariantFileRevision(getRemote()); return revision; } public IFileRevision getBeforeState() { ResourceVariantFileRevision revision = new ResourceVariantFileRevision(getBase()); return revision; } public IResource getResource() { return getLocal(); } } } HgDragAdapterAssistant.java000066400000000000000000000054601173713500500360630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.Transfer; import org.eclipse.ui.navigator.CommonDragAdapterAssistant; import org.eclipse.ui.part.ResourceTransfer; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author andrei */ public class HgDragAdapterAssistant extends CommonDragAdapterAssistant { private static final Transfer[] SUPPORTED_TRANSFERS = new Transfer[] { ResourceTransfer .getInstance() }; public HgDragAdapterAssistant() { super(); } @Override public Transfer[] getSupportedTransferTypes() { return SUPPORTED_TRANSFERS; } @Override public boolean setDragData(DragSourceEvent event, IStructuredSelection selection) { if (!ResourceTransfer.getInstance().isSupportedType(event.dataType)) { return false; } IFile[] resources = getSelectedResources(selection); if (resources.length == 0) { return false; } event.data = resources; return true; } private static IFile[] getSelectedResources(IStructuredSelection selection) { List resources = ResourceUtils.getResources(selection); final Set files = new HashSet(); for (IResource resource : resources) { if(resource instanceof IFile) { // TODO how to deal with folders in a sync tree? We have to // add only those files from the folder which are shown in particular changeset files.add((IFile) resource); } else if(resource instanceof IContainer) { IContainer folder = (IContainer) resource; try { folder.accept(new IResourceVisitor() { public boolean visit(IResource child) throws CoreException { if(child instanceof IFile) { files.add((IFile) child); } return true; } }); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } return files.toArray(new IFile[0]); } } HgDropAdapterAssistant.java000066400000000000000000000113001173713500500361000ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.util.LocalSelectionTransfer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.dnd.DropTargetEvent; import org.eclipse.swt.dnd.TransferData; import org.eclipse.ui.navigator.CommonDropAdapter; import org.eclipse.ui.navigator.CommonDropAdapterAssistant; import org.eclipse.ui.part.ResourceTransfer; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.synchronize.cs.UncommittedChangesetGroup; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgDropAdapterAssistant extends CommonDropAdapterAssistant { public HgDropAdapterAssistant() { super(); } @Override public IStatus validateDrop(Object target, int operation, TransferData transferType) { if (!LocalSelectionTransfer.getTransfer().isSupportedType(transferType)) { return Status.CANCEL_STATUS; } if(!(target instanceof WorkingChangeSet) && !(target instanceof UncommittedChangesetGroup)) { return Status.CANCEL_STATUS; } return Status.OK_STATUS; } @Override public IStatus handleDrop(CommonDropAdapter dropAdapter, DropTargetEvent dropTargetEvent, Object target) { TransferData currentTransfer = dropAdapter.getCurrentTransfer(); IFile[] files; if (LocalSelectionTransfer.getTransfer().isSupportedType( currentTransfer)) { files = getSelectedResources().toArray(new IFile[0]); } else if(ResourceTransfer.getInstance().isSupportedType(currentTransfer)) { files = (IFile[]) dropTargetEvent.data; } else { return Status.CANCEL_STATUS; } if (files == null || files.length == 0) { return Status.CANCEL_STATUS; } if(dropAdapter.getCurrentTarget() instanceof UncommittedChangesetGroup) { createNewChangeset((UncommittedChangesetGroup)dropAdapter.getCurrentTarget(), files); } else if(dropAdapter.getCurrentTarget() instanceof GroupedUncommittedChangeSet) { moveToAnotherChangeset((GroupedUncommittedChangeSet)dropAdapter.getCurrentTarget(), files); } else { return Status.CANCEL_STATUS; } return Status.OK_STATUS; } private static void moveToAnotherChangeset(GroupedUncommittedChangeSet changeSet, IFile[] files) { changeSet.getGroup().move(files, changeSet); } private static void createNewChangeset(UncommittedChangesetGroup group, IFile[] files) { group.create(files); } /** * Returns the resource selection from the LocalSelectionTransfer. * * @return the resource selection from the LocalSelectionTransfer */ private static Set getSelectedResources() { ISelection selection = LocalSelectionTransfer.getTransfer().getSelection(); if (!(selection instanceof IStructuredSelection)) { return Collections.emptySet(); } List resources = ResourceUtils.getResources((IStructuredSelection) selection); final MercurialStatusCache cache = MercurialStatusCache.getInstance(); final Set files = new HashSet(); for (IResource resource : resources) { if(resource instanceof IFile && !cache.isClean(resource)) { files.add((IFile) resource); } else if(resource instanceof IContainer && !cache.isClean(resource)) { IContainer folder = (IContainer) resource; try { folder.accept(new IResourceVisitor() { public boolean visit(IResource child) throws CoreException { if(child instanceof IFile && !cache.isClean(child)) { files.add((IFile) child); } return true; } }); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } return files; } } HgSubscriberChangeEvent.java000066400000000000000000000034451173713500500362270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import org.eclipse.core.resources.IResource; import org.eclipse.team.core.subscribers.ISubscriberChangeEvent; import org.eclipse.team.core.subscribers.Subscriber; import org.eclipse.team.core.subscribers.SubscriberChangeEvent; public class HgSubscriberChangeEvent extends SubscriberChangeEvent { public HgSubscriberChangeEvent(Subscriber subscriber, int flags, IResource resource) { super(subscriber, flags, resource); } @Override public boolean equals(Object obj) { if(this == obj){ return true; } if(!(obj instanceof HgSubscriberChangeEvent)){ return false; } HgSubscriberChangeEvent event = (HgSubscriberChangeEvent) obj; return getResource().equals(event.getResource()); } @Override public int hashCode() { return getResource().hashCode(); } @Override public String toString() { StringBuilder sb = new StringBuilder(); switch (getFlags()) { case ISubscriberChangeEvent.ROOT_ADDED: sb.append("+"); break; case ISubscriberChangeEvent.ROOT_REMOVED: sb.append("-"); break; case ISubscriberChangeEvent.NO_CHANGE: sb.append(""); break; case ISubscriberChangeEvent.SYNC_CHANGED: sb.append("~"); break; } sb.append(getResource().getName()); return sb.toString(); } }HgSubscriberMergeContext.java000066400000000000000000000107531173713500500364440ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.resources.mapping.ResourceTraversal; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.diff.IDiff; import org.eclipse.team.core.mapping.ISynchronizationScopeManager; import org.eclipse.team.core.subscribers.Subscriber; import org.eclipse.team.core.subscribers.SubscriberMergeContext; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangesetsCollector; /** * @author bastian * */ public class HgSubscriberMergeContext extends SubscriberMergeContext { private final Set hidden; private final MercurialSynchronizeSubscriber subscriber; public HgSubscriberMergeContext(Subscriber subscriber, ISynchronizationScopeManager manager) { super(subscriber, manager); initialize(); hidden = new HashSet(); this.subscriber = (MercurialSynchronizeSubscriber) subscriber; } /** * Called after "Overwrite" action is executed *

* {@inheritDoc} */ @Override protected void makeInSync(IDiff diff, IProgressMonitor monitor) throws CoreException { } // @Override // public void run(IWorkspaceRunnable runnable, ISchedulingRule rule, int flags, // IProgressMonitor monitor) throws CoreException { // doPullAndMerge(subscriber.getRepo(), subscriber.getProjects(), runnable, rule, flags, monitor); // } // // @Override // protected void runInBackground(IWorkspaceRunnable runnable) { // doPullAndMerge(subscriber.getRepo(), subscriber.getProjects(), runnable); // } public void markAsMerged(IDiff node, boolean inSyncHint, IProgressMonitor monitor) throws CoreException { } public void reject(IDiff diff, IProgressMonitor monitor) throws CoreException { } /** * "Synchronize", part 2 *

* {@inheritDoc} */ @Override public void refresh(ResourceTraversal[] traversals, int flags, IProgressMonitor monitor) throws CoreException { super.refresh(traversals, flags, monitor); monitor.done(); } /** * "Synchronize", part 1 *

* {@inheritDoc} */ @Override public void refresh(ResourceMapping[] mappings, IProgressMonitor monitor) throws CoreException { super.refresh(mappings, monitor); HgChangesetsCollector collector = subscriber.getCollector(); if(collector != null) { collector.refresh(mappings); } } @Override protected SyncInfo getSyncInfo(IResource resource) throws CoreException { return super.getSyncInfo(resource); } @Override public void dispose() { // avoid silly NPE's in the team API code if they try to dispose compare // editors on shutdown, we don't care if(!PlatformUI.getWorkbench().isClosing()) { super.dispose(); } clearHiddenFiles(); } public void hide(IFile file) { hidden.add(file); // HgChangesetsCollector collector = subscriber.getCollector(); // if(collector != null) { // collector.refresh(null); // } } public void clearHiddenFiles(){ hidden.clear(); } public boolean isHidden(IFile file){ return hidden.contains(file); } // private void doPullAndMerge(HgRepositoryLocation location, // IProject[] projects, // IWorkspaceRunnable runnable) { // doPullAndMerge(location, projects, runnable, null, 0, null); // } // // private void doPullAndMerge(HgRepositoryLocation location, // IProject[] projects, // IWorkspaceRunnable runnable, // ISchedulingRule rule, // int flags, // IProgressMonitor monitor) { // //TODO This is a null solution to avoid wrong usage until it is properly implemented! // // I was originally planned to show a dialog here but that seems "impossible" :( // } } HgSubscriberScopeManager.java000066400000000000000000000220211173713500500363730ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import java.util.HashSet; import java.util.Observable; import java.util.Observer; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.mapping.ISynchronizationScope; import org.eclipse.team.core.subscribers.ISubscriberChangeEvent; import org.eclipse.team.core.subscribers.SubscriberScopeManager; import org.eclipse.ui.IPropertyListener; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.IncomingChangesetCache; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.OutgoingChangesetCache; /** * @author Andrei */ public class HgSubscriberScopeManager extends SubscriberScopeManager implements Observer { public static final int INCOMING = -1; public static final int OUTGOING = -2; public static final int LOCAL = -3; private final IPropertyListener branchListener; private boolean disposed; public HgSubscriberScopeManager(ResourceMapping[] inputMappings, MercurialSynchronizeSubscriber subscriber) { super(HgSubscriberScopeManager.class.getSimpleName(), inputMappings, subscriber, false); MercurialStatusCache.getInstance().addObserver(this); IncomingChangesetCache.getInstance().addObserver(this); OutgoingChangesetCache.getInstance().addObserver(this); branchListener = new IPropertyListener() { public void propertyChanged(Object source, int propId) { MercurialSynchronizeSubscriber subscriber1 = (MercurialSynchronizeSubscriber) getSubscriber(); subscriber1.branchChanged((HgRoot) source); } }; MercurialTeamProvider.addBranchListener(branchListener); } @Override public ISynchronizationScope getScope() { // Does NOT return expected (our) scope, but ResourceMappingScope... // super.getScope(); RepositorySynchronizationScope scope2 = ((MercurialSynchronizeSubscriber) getSubscriber()).getScope(); return scope2; } @Override public void initialize(IProgressMonitor monitor) throws CoreException { super.initialize(monitor); // MercurialSynchronizeParticipant participant = ((MercurialSynchronizeSubscriber) getSubscriber()).getParticipant(); // HgSubscriberMergeContext context2 = (HgSubscriberMergeContext) participant.getContext(); // context2.clearHiddenFiles(); } public void update(Observable o, Object arg) { if(!(arg instanceof Set)){ return; } Set changeEvents = new HashSet(); Set resources = (Set) arg; IResource[] roots = getSubscriber().roots(); boolean projectRefresh = false; int flags = ISubscriberChangeEvent.SYNC_CHANGED; for (Object res : resources) { if(!(res instanceof IResource)) { continue; } IResource resource = (IResource) res; for (IResource root : roots) { if(root.contains(resource)) { if(!projectRefresh && resource.contains(root)){ projectRefresh = true; } changeEvents.add(new HgSubscriberChangeEvent(getSubscriber(), flags, resource)); break; } } } if (changeEvents.size() == 0) { return; } // XXX check the usage of the arguments set. Now it may contain more then one project // in the set. Hovewer, we may refresh too much here... if(projectRefresh && (resources.size() == 1 || containsOnlyProjects(resources))){ // we must sync the data for the project if(MercurialEclipsePlugin.getDefault().isDebugging()) { System.out.println("! Update data from: " + o + " : " + resources.size()); } int flag = 0; if (o instanceof IncomingChangesetCache) { flag = INCOMING; } else if (o instanceof OutgoingChangesetCache || o instanceof LocalChangesetCache) { flag = OUTGOING; } else if (o instanceof MercurialStatusCache) { flag = LOCAL; } updateData(roots, flag); } else { // we must update our sync UI with new data we already got if(MercurialEclipsePlugin.getDefault().isDebugging()) { System.out.println("Update UI from: " + o + " : " + resources.size()); } updateUI(changeEvents); } } private boolean containsOnlyProjects(Set resources) { for (Object object : resources) { if(!(object instanceof IProject)) { return false; } } return true; } @Override public void dispose() { if(disposed){ return; } disposed = true; MercurialStatusCache.getInstance().deleteObserver(this); IncomingChangesetCache.getInstance().deleteObserver(this); OutgoingChangesetCache.getInstance().deleteObserver(this); MercurialTeamProvider.removeBranchListener(branchListener); super.dispose(); } private void updateUI(Set events) { UpdateUIJob updateJob = new UpdateUIJob(events, (MercurialSynchronizeSubscriber) getSubscriber()); Job[] jobs = Job.getJobManager().find(UpdateUIJob.class); for (Job job : jobs) { if(updateJob.equals(job)){ job.cancel(); if(MercurialEclipsePlugin.getDefault().isDebugging()) { System.out.println("Cancelled refresh UI: " + ((UpdateUIJob) job).events.size()); } } } updateJob.schedule(500); } private void updateData(IResource[] roots, int flag) { UpdateDataJob updateJob = new UpdateDataJob(flag, roots, (MercurialSynchronizeSubscriber) getSubscriber()); Job[] jobs = Job.getJobManager().find(UpdateDataJob.class); for (Job job : jobs) { if(updateJob.equals(job)){ job.cancel(); if(MercurialEclipsePlugin.getDefault().isDebugging()) { System.out.println("Cancelled refresh data: " + flag); } } } updateJob.schedule(200); } private static class UpdateUIJob extends Job { private final MercurialSynchronizeSubscriber subscriber; private final Set events; public UpdateUIJob(Set events, MercurialSynchronizeSubscriber subscriber) { super("Hg subscriber UI update"); this.events = events; this.subscriber = subscriber; } @Override protected IStatus run(IProgressMonitor monitor) { monitor.beginTask(Messages.getString("MercurialSynchronizeSubscriber.refreshingResources"), 1); try { ISubscriberChangeEvent[] deltas = events.toArray(new ISubscriberChangeEvent[events.size()]); subscriber.fireTeamResourceChange(deltas); monitor.worked(1); } finally { monitor.done(); } return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return UpdateUIJob.class.equals(family); } @Override public boolean equals(Object obj) { if(!(obj instanceof UpdateUIJob)){ return false; } UpdateUIJob job = (UpdateUIJob) obj; if(events.size() != job.events.size()){ return false; } if(!subscriber.equals(job.subscriber)){ return false; } return events.containsAll(job.events); } @Override public int hashCode() { return events.size() + subscriber.hashCode(); } } private static class UpdateDataJob extends Job { private final int flag; private final IResource[] roots; private final MercurialSynchronizeSubscriber subscriber; public UpdateDataJob(int flag, IResource[] roots, MercurialSynchronizeSubscriber subscriber) { super("Hg subscriber data update"); this.flag = flag; this.roots = roots; this.subscriber = subscriber; } @Override protected IStatus run(IProgressMonitor monitor) { monitor.beginTask(Messages.getString("MercurialSynchronizeSubscriber.refreshingResources"), 5); try { subscriber.refresh(roots, flag, monitor); } catch (TeamException e) { MercurialEclipsePlugin.logError(e); return Status.CANCEL_STATUS; } finally { monitor.done(); } return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return UpdateDataJob.class.equals(family); } @Override public boolean equals(Object obj) { if(!(obj instanceof UpdateDataJob)){ return false; } UpdateDataJob job = (UpdateDataJob) obj; if(flag != job.flag){ return false; } return subscriber.equals(job.subscriber); } @Override public int hashCode() { return flag + subscriber.hashCode(); } } } MercurialResourceVariant.java000066400000000000000000000035211173713500500365100ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.variants.IResourceVariant; import com.vectrace.MercurialEclipse.compare.RevisionNode; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.IHgFolder; import com.vectrace.MercurialEclipse.model.IHgResource; public class MercurialResourceVariant implements IResourceVariant { private final RevisionNode rev; public MercurialResourceVariant(RevisionNode rev) { this.rev = rev; } public byte[] asBytes() { return getContentIdentifier().getBytes(); } public String getContentIdentifier() { ChangeSet cs = rev.getHgResource().getChangeSet(); return cs.getChangesetIndex() + ":" + cs.getChangeset(); } public String getName() { return rev.getHgResource().getName(); } public IStorage getStorage(IProgressMonitor monitor) throws TeamException { IHgResource hgResource = rev.getHgResource(); if (hgResource instanceof IStorage) { return (IStorage) hgResource; } return null; } public boolean isContainer() { return rev.getHgResource() instanceof IHgFolder; } public RevisionNode getRev() { return rev; } } MercurialResourceVariantComparator.java000066400000000000000000000056621173713500500405500ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import org.eclipse.core.resources.IResource; import org.eclipse.team.core.variants.IResourceVariant; import org.eclipse.team.core.variants.IResourceVariantComparator; import com.vectrace.MercurialEclipse.compare.RevisionNode; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.model.IHgResource; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; /** * Comparator for the identity with remote content * @author Andrei */ public class MercurialResourceVariantComparator implements IResourceVariantComparator { private final MercurialStatusCache statusCache; public MercurialResourceVariantComparator() { statusCache = MercurialStatusCache.getInstance(); } public boolean compare(IResource local, IResourceVariant repoRevision) { if (!statusCache.isClean(local)) { return false; } if(repoRevision == null){ return true; } ChangeSet cs = ((MercurialResourceVariant)repoRevision).getRev().getHgResource().getChangeSet(); // if this is outgoing or incoming, it can't be equal to any other changeset Direction direction = cs.getDirection(); if (direction == Direction.INCOMING || direction == Direction.OUTGOING) { String branch = MercurialTeamProvider.getCurrentBranch(local); if (Branch.same(cs.getBranch(), branch)) { return false; } } // resource is clean and we compare against our local repository return true; } public boolean compare(IResourceVariant base, IResourceVariant remote) { MercurialResourceVariant mbase = (MercurialResourceVariant) base; MercurialResourceVariant mremote = (MercurialResourceVariant) remote; RevisionNode remoteRev = mremote.getRev(); if(mbase.getRev().getHgResource() == remoteRev.getHgResource()){ return true; } IHgResource resource = remoteRev.getHgResource(); String remoteBranch = remoteRev.getHgResource().getChangeSet().getBranch(); String currentBranch = MercurialTeamProvider.getCurrentBranch(resource.getHgRoot()); if (Branch.same(currentBranch, remoteBranch)) { return base.getContentIdentifier().equals(remote.getContentIdentifier()); } return true; } public boolean isThreeWay() { return true; } } MercurialSyncInfo.java000066400000000000000000000030261173713500500351240ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import org.eclipse.core.resources.IResource; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.core.variants.IResourceVariant; import org.eclipse.team.core.variants.IResourceVariantComparator; /** * @author bastian * */ public class MercurialSyncInfo extends SyncInfo { protected final int description; public MercurialSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote, IResourceVariantComparator comparator, int description) { super(local, base, remote, comparator); this.description = description; } @Override protected int calculateKind() throws TeamException { if(description >= 0){ return description; } return super.calculateKind(); } // here to avoid FindBugs warnings @Override public boolean equals(Object other) { return super.equals(other); } @Override public int hashCode() { return super.hashCode(); } } MercurialSynchronizeParticipant.java000066400000000000000000000252111173713500500401060ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2008 MercurialEclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.mapping.ModelProvider; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.CoreException; import org.eclipse.team.core.mapping.ISynchronizationScope; import org.eclipse.team.core.mapping.ISynchronizationScopeManager; import org.eclipse.team.core.mapping.ISynchronizationScopeParticipant; import org.eclipse.team.core.mapping.provider.MergeContext; import org.eclipse.team.core.mapping.provider.SynchronizationContext; import org.eclipse.team.internal.ui.synchronize.ChangeSetCapability; import org.eclipse.team.internal.ui.synchronize.IChangeSetProvider; import org.eclipse.team.ui.TeamUI; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.ISynchronizeParticipantDescriptor; import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipant; import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipantActionGroup; import org.eclipse.team.ui.synchronize.SubscriberParticipant; import org.eclipse.ui.IMemento; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.synchronize.actions.MercurialSynchronizePageActionGroup; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetCapability; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetModelProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * TODO why did we choose the {@link ModelSynchronizeParticipant} as a parent class? * Why not {@link SubscriberParticipant}??? * @author Andrei */ @SuppressWarnings("restriction") public class MercurialSynchronizeParticipant extends ModelSynchronizeParticipant implements IChangeSetProvider, ISynchronizationScopeParticipant { private static final String REPOSITORY_LOCATION = "REPOSITORY_LOCATION"; //$NON-NLS-1$ private static final String PROJECTS = "PROJECTS"; private String secondaryId; private IHgRepositoryLocation repositoryLocation; private Set restoredProjects; private HgChangeSetCapability changeSetCapability; public MercurialSynchronizeParticipant() { super(); } public MercurialSynchronizeParticipant(HgSubscriberMergeContext ctx, IHgRepositoryLocation repositoryLocation, RepositorySynchronizationScope scope) { super(ctx); this.repositoryLocation = repositoryLocation; secondaryId = computeSecondaryId(scope, repositoryLocation); try { ISynchronizeParticipantDescriptor descriptor = TeamUI .getSynchronizeManager().getParticipantDescriptor(getId()); setInitializationData(descriptor); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } private String computeSecondaryId(RepositorySynchronizationScope scope, IHgRepositoryLocation repo) { IProject[] projects = scope.getProjects(); StringBuilder sb = new StringBuilder(); if(projects.length > 0){ sb.append("["); for (IProject project : projects) { sb.append(project.getName()).append(','); } sb.deleteCharAt(sb.length() - 1); sb.append("] "); } sb.append(repo.getLocation()); if(sb.charAt(sb.length() - 1) == '/'){ sb.deleteCharAt(sb.length() - 1); } return sb.toString(); } @Override public void init(String secId, IMemento memento) throws PartInitException { secondaryId = secId; IMemento myMemento = memento.getChild(MercurialSynchronizeParticipant.class.getName()); String uri = myMemento.getString(REPOSITORY_LOCATION); try { repositoryLocation = MercurialEclipsePlugin.getRepoManager().getRepoLocation(uri); } catch (HgException e) { throw new PartInitException(e.getLocalizedMessage(), e); } restoreScope(myMemento); super.init(secondaryId, memento); } private void restoreScope(IMemento memento) { String encodedProjects = memento.getString(PROJECTS); if(encodedProjects == null){ return; } String[] projectNames = encodedProjects.split(","); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); Set repoProjects = MercurialEclipsePlugin.getRepoManager().getAllRepoLocationProjects( repositoryLocation); restoredProjects = new HashSet(); for (String pName : projectNames) { if(pName.length() == 0){ continue; } IProject project = root.getProject(pName); if(project != null && (repoProjects.contains(project) || (!project.isOpen() && project.exists()))){ restoredProjects.add(project); } } boolean addRoot = MercurialEclipsePlugin.getDefault().getPreferenceStore() .getBoolean(MercurialPreferenceConstants.PREF_SYNC_ALL_PROJECTS_IN_REPO); if(restoredProjects.isEmpty() && addRoot) { Map> byRoot = ResourceUtils.groupByRoot(repoProjects); Set roots = byRoot.keySet(); for (HgRoot hgRoot : roots) { restoredProjects.add(hgRoot.getResource()); } } } @Override public void saveState(IMemento memento) { IMemento myMemento = memento .createChild(MercurialSynchronizeParticipant.class.getName()); myMemento.putString(REPOSITORY_LOCATION, repositoryLocation.getLocation()); saveCurrentScope(myMemento); super.saveState(memento); } private void saveCurrentScope(IMemento memento){ IProject[] projects = getContext().getScope().getProjects(); Set repoProjects = MercurialEclipsePlugin.getRepoManager().getAllRepoLocationProjects( repositoryLocation); StringBuilder sb = new StringBuilder(); for (IProject project : projects) { if(repoProjects.contains(project) || !project.isOpen()) { sb.append(project.getName()).append(","); } } memento.putString(PROJECTS, sb.toString()); } @Override protected MergeContext restoreContext(ISynchronizationScopeManager manager) throws CoreException { Set repoProjects; if (restoredProjects != null && !restoredProjects.isEmpty()) { repoProjects = restoredProjects; } else { repoProjects = MercurialEclipsePlugin.getRepoManager().getAllRepoLocationProjects(repositoryLocation); } RepositorySynchronizationScope scope = new RepositorySynchronizationScope(repositoryLocation, repoProjects.toArray(new IProject[0])); MercurialSynchronizeSubscriber subscriber = new MercurialSynchronizeSubscriber(scope); HgSubscriberScopeManager manager2 = new HgSubscriberScopeManager(scope.getMappings(), subscriber); subscriber.setParticipant(this); return new HgSubscriberMergeContext(subscriber, manager2); } @Override protected void initializeContext(SynchronizationContext context) { if(context != null) { super.initializeContext(context); } } @Override public void dispose() { if(getContext() != null) { super.dispose(); } } @Override public String getId() { return getClass().getName(); } @Override public String getSecondaryId() { return secondaryId; } @Override public String getName() { return secondaryId; } /** * @return the repositoryLocation */ public IHgRepositoryLocation getRepositoryLocation() { return repositoryLocation; } @Override protected ModelSynchronizeParticipantActionGroup createMergeActionGroup() { // allows us to contribute our own actions to the synchronize view via java code return new MercurialSynchronizePageActionGroup(); } @Override protected void initializeConfiguration(ISynchronizePageConfiguration configuration) { super.initializeConfiguration(configuration); if(!isMergingEnabled()) { // add our action group in any case configuration.addActionContribution(createMergeActionGroup()); } // Set changesets mode as default configuration.setProperty(ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER, HgChangeSetModelProvider.ID); } @Override public boolean hasCompareInputFor(Object object) { if(object instanceof IFile || object instanceof FileFromChangeSet){ // always allow "Open in Compare Editor" menu to be shown return true; } return super.hasCompareInputFor(object); } @Override public boolean isMergingEnabled() { // do not sow Eclipse default "merge" action, which only breaks "native" hg merge return false; } @Override protected boolean isViewerContributionsSupported() { // allows us to contribute our own actions to the synchronize view via plugin.xml return true; } @Override public boolean doesSupportSynchronize() { return true; } @Override public void run(IWorkbenchPart part) { super.run(part); } public ChangeSetCapability getChangeSetCapability() { if(changeSetCapability == null) { changeSetCapability = new HgChangeSetCapability(); } return changeSetCapability; } @Override public ModelProvider[] getEnabledModelProviders() { ModelProvider[] providers = getContext().getScope().getModelProviders(); return providers; } public ResourceMapping[] handleContextChange(ISynchronizationScope scope, IResource[] resources, IProject[] projects) { return new ResourceMapping[0]; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("MercurialSynchronizeParticipant ["); if (repositoryLocation != null) { builder.append("repositoryLocation="); builder.append(repositoryLocation); builder.append(", "); } if (restoredProjects != null) { builder.append("restoredProjects="); builder.append(restoredProjects); builder.append(", "); } if (secondaryId != null) { builder.append("secondaryId="); builder.append(secondaryId); } builder.append("]"); return builder.toString(); } public Set getRestoredProjects() { return restoredProjects; } } MercurialSynchronizeSubscriber.java000066400000000000000000000601251173713500500377360ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bugfixes * Adam Berkes (Intland) - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.SYNC_COMPUTE_FULL_REMOTE_FILE_STATUS; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.diff.IDiff; import org.eclipse.team.core.subscribers.ISubscriberChangeEvent; import org.eclipse.team.core.subscribers.Subscriber; import org.eclipse.team.core.subscribers.SubscriberChangeEvent; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.core.variants.IResourceVariant; import org.eclipse.team.core.variants.IResourceVariantComparator; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgIdentClient; import com.vectrace.MercurialEclipse.compare.RevisionNode; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangesetsCollector; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.IncomingChangesetCache; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.OutgoingChangesetCache; import com.vectrace.MercurialEclipse.utils.Bits; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class MercurialSynchronizeSubscriber extends Subscriber /*implements Observer*/ { private static final LocalChangesetCache LOCAL_CACHE = LocalChangesetCache.getInstance(); private static final IncomingChangesetCache INCOMING_CACHE = IncomingChangesetCache.getInstance(); private static final OutgoingChangesetCache OUTGOING_CACHE = OutgoingChangesetCache.getInstance(); private static final MercurialStatusCache STATUS_CACHE = MercurialStatusCache.getInstance(); private static final boolean DEBUG = MercurialEclipsePlugin.getDefault().isDebugging(); private static final IResourceVariantComparator COMPARATOR = new MercurialResourceVariantComparator(); private static final Semaphore CACHE_SEMA = new Semaphore(1, true); private final RepositorySynchronizationScope scope; /** key is hg root, value is the *current* changeset of this root */ private static final Map CURRENT_CS_MAP = new ConcurrentHashMap(); private ISubscriberChangeEvent[] lastEvents; private MercurialSynchronizeParticipant participant; private HgChangesetsCollector collector; private boolean computeFullState; public MercurialSynchronizeSubscriber(RepositorySynchronizationScope synchronizationScope) { Assert.isNotNull(synchronizationScope); scope = synchronizationScope; synchronizationScope.setSubscriber(this); final IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); computeFullState = store.getBoolean(SYNC_COMPUTE_FULL_REMOTE_FILE_STATUS); store.addPropertyChangeListener(new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if(SYNC_COMPUTE_FULL_REMOTE_FILE_STATUS.equals(event.getProperty())){ computeFullState = store.getBoolean(SYNC_COMPUTE_FULL_REMOTE_FILE_STATUS); } } }); } @Override public String getName() { return Messages.getString("MercurialSynchronizeSubscriber.repoWatcher"); //$NON-NLS-1$ } @Override public IResourceVariantComparator getResourceComparator() { return COMPARATOR; } @Override public SyncInfo getSyncInfo(final IResource resource) { if (!isInteresting(resource)) { return null; } IFile file = (IFile) resource; HgRoot root = MercurialTeamProvider.hasHgRoot(file); if(root == null){ return null; } String syncBranch = getSyncBranch(root); IHgRepositoryLocation repo = getRepo(); if(computeFullState) { return getSyncInfo(file, root, syncBranch, repo); } return getFastSyncInfo(file, root, syncBranch, repo); } static SyncInfo getSyncInfo(IFile file, HgRoot root, String currentBranch, IHgRepositoryLocation repo) { ChangeSet csOutgoing = getNewestOutgoing(file, currentBranch, repo); MercurialRevisionStorage outgoingIStorage; IResourceVariant outgoing; // determine outgoing revision boolean hasOutgoingChanges = false; boolean hasIncomingChanges = false; Integer status = STATUS_CACHE.getStatus(file); int sMask = status != null? status.intValue() : 0; if (csOutgoing != null) { outgoingIStorage = new MercurialRevisionStorage(file, csOutgoing.getRevision().getRevision(), csOutgoing.getChangeset(), csOutgoing); outgoing = new MercurialResourceVariant(new RevisionNode(ResourceUtils.convertToHgFile(outgoingIStorage))); hasOutgoingChanges = true; } else { boolean exists = file.exists(); // if outgoing != null it's our base, else we gotta construct one if (exists && !Bits.contains(sMask, MercurialStatusCache.BIT_ADDED) // XXX Probably we do not need to check for BIT_REMOVED // || (!exists && Bits.contains(sMask, MercurialStatusCache.BIT_REMOVED)) || !exists) { try { // Find current working directory changeset (not head) String nodeId = getCurrentChangesetId(root); // try to get from cache (without loading) csOutgoing = getChangeset(file, nodeId, root); } catch (HgException e) { MercurialEclipsePlugin.logError(e); return null; } if(csOutgoing == null || !Branch.same(csOutgoing.getBranch(), currentBranch)){ return null; } // construct base revision outgoingIStorage = new MercurialRevisionStorage(file, csOutgoing.getChangesetIndex(), csOutgoing.getChangeset(), csOutgoing); outgoing = new MercurialResourceVariant(new RevisionNode(ResourceUtils.convertToHgFile(outgoingIStorage))); } else { // new incoming file - no local available outgoingIStorage = null; outgoing = null; } } // determine incoming revision get newest incoming changeset ChangeSet csIncoming = getNewestIncoming(file, currentBranch, repo); MercurialRevisionStorage incomingIStorage; int syncMode = -1; if (csIncoming != null) { hasIncomingChanges = true; boolean fileRemoved = csIncoming.isRemoved(file); if(fileRemoved){ incomingIStorage = null; } else { incomingIStorage = getIncomingIStorage(file, csIncoming); } } else { if(!hasOutgoingChanges && Bits.contains(sMask, MercurialStatusCache.BIT_CLEAN)){ return null; } if(DEBUG) { System.out.println("Visiting: " + file); } // if no incoming revision, incoming = base/outgoing // TODO it seems that the line below causes NO DIFF shown if the outgoing // change consists from MULTIPLE changes on same file, see issue 10486 // we have to get the parent of the first outgoing changeset on a given file here incomingIStorage = outgoingIStorage; // TODO validate if code below fixes the issue 10486 try { SortedSet sets = OUTGOING_CACHE.hasChangeSets(file, repo, currentBranch); int size = sets.size(); // case where we have one outgoung changeset AND one not committed change if(size == 1 && !Bits.contains(sMask, MercurialStatusCache.BIT_CLEAN)){ size++; } if(size > 1){ ChangeSet first = sets.first(); String[] parents = first.getParents(); String parentCs = null; if(parents.length > 0){ parentCs = parents[0]; } else { ChangeSet tmpCs = getChangeset(file, first.getChangeset(), null); if(tmpCs != null && tmpCs.getParents().length > 0){ parentCs = tmpCs.getParents()[0]; } } if(parentCs != null){ ChangeSet baseChangeset = getChangeset(file, parentCs, null); incomingIStorage = getIncomingIStorage(file, baseChangeset); // we change outgoing (base) to the first parent of the first outgoing changeset outgoing = new MercurialResourceVariant(new RevisionNode(ResourceUtils.convertToHgFile(incomingIStorage))); syncMode = SyncInfo.OUTGOING | SyncInfo.CHANGE; } } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } if(!hasIncomingChanges && !hasOutgoingChanges && Bits.contains(sMask, MercurialStatusCache.BIT_CLEAN)){ return null; } IResourceVariant incoming; if (incomingIStorage != null) { incoming = new MercurialResourceVariant(new RevisionNode(ResourceUtils.convertToHgFile(incomingIStorage))); } else { // neither base nor outgoing nor incoming revision incoming = null; } // now create the sync info object. everything may be null, // but resource and comparator SyncInfo info = new MercurialSyncInfo(file, outgoing, incoming, COMPARATOR, syncMode); try { info.init(); return info; } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return null; } } protected static ChangeSet getChangeset(IResource file, String nodeId, HgRoot root) throws HgException { try { return LOCAL_CACHE.getOrFetchChangeSetById(file, nodeId); } catch (HgException e) { // workaround for the case where the root version is not up-to-date anymore // simply clear the cache and restart if(root != null && e.getMessage() != null && e.getMessage().contains("unknown revision")) { CURRENT_CS_MAP.remove(root); return getChangeset(file, nodeId, null); } throw e; } } public static void executeLockedCacheTask(Runnable run) throws InterruptedException { if(!CACHE_SEMA.tryAcquire(60 * 10, TimeUnit.SECONDS)){ // waiting didn't worked for us... throw new InterruptedException("Timeout elapsed"); } try { run.run(); } catch (Exception e) { MercurialEclipsePlugin.logError(e); throw new InterruptedException("Cancelled due the exception: " + e.getMessage()); } finally { CACHE_SEMA.release(); } } private static ChangeSet getNewestOutgoing(IFile file, String currentBranch, IHgRepositoryLocation repo) { ChangeSet csOutgoing = null; SortedSet changeSets = OUTGOING_CACHE.hasChangeSets(file, repo, currentBranch); if (!changeSets.isEmpty()) { csOutgoing = changeSets.last(); } return csOutgoing; } private static ChangeSet getNewestIncoming(IFile file, String currentBranch, IHgRepositoryLocation repo) { ChangeSet csIncoming = null; SortedSet changeSets = INCOMING_CACHE.hasChangeSets(file, repo, currentBranch); if (!changeSets.isEmpty()) { csIncoming = changeSets.last(); } return csIncoming; } /** * Avoid calculation of added/removed states, as this costs us a HUGE performance * overhead for bigger repositories of many changesets (>1000) at once (see issue #10646). * * The expected performance improvement is about 5 to 10 times for repositories with * more then 50000 files. As a drawback, some diff info is lost in the "tree" view, * and the "compare to" action doesn't always deliver expected results. * * @return a simplified sync info object, which doesn't know if it was added or removed. */ // TODO calculation of the status flags need to be reviewed. Right now it has a prototype quality private static SyncInfo getFastSyncInfo(IFile file, HgRoot root, String currentBranch, IHgRepositoryLocation repo) { Integer status = STATUS_CACHE.getStatus(file); int sMask = status != null? status.intValue() : 0; boolean changedLocal = !Bits.contains(sMask, MercurialStatusCache.BIT_CLEAN); SortedSet changeSets = null; if(!changedLocal){ changeSets = OUTGOING_CACHE.hasChangeSets(file, repo, currentBranch); changedLocal = hasChanges(file, changeSets); } changeSets = INCOMING_CACHE.hasChangeSets(file, repo, currentBranch); boolean changedRemote = hasChanges(file, changeSets); if(!changedLocal && !changedRemote){ return null; } int flags; if (changedLocal && changedRemote) { flags = SyncInfo.CONFLICTING; } else { flags = SyncInfo.CHANGE; flags |= changedLocal ? SyncInfo.OUTGOING : SyncInfo.INCOMING; } return new DelayedSyncInfo(file, root, currentBranch, repo, COMPARATOR, flags); } @Override public IDiff getDiff(IResource resource) throws CoreException { SyncInfo info = getSyncInfo(resource); if (info == null || info.getKind() == SyncInfo.IN_SYNC) { return null; } if(computeFullState) { return super.getDiff(resource); } return ((DelayedSyncInfo) info).getDiff(); } private static boolean hasChanges(IFile file, SortedSet changeSets) { if(changeSets == null || changeSets.isEmpty()){ return false; } for (ChangeSet cs : changeSets) { if(cs.contains(file)){ return true; } } return false; } static String getCurrentChangesetId(HgRoot root) throws HgException { String nodeId = CURRENT_CS_MAP.get(root); if(nodeId == null){ nodeId = HgIdentClient.getCurrentChangesetId(root); CURRENT_CS_MAP.put(root, nodeId); } return nodeId; } private boolean isInteresting(IResource resource) { return resource instanceof IFile && MercurialTeamProvider.isHgTeamProviderFor(resource.getProject()) && (isSupervised(resource) || (!resource.exists())); } private static MercurialRevisionStorage getIncomingIStorage(IFile resource, ChangeSet csRemote) { MercurialRevisionStorage incomingIStorage = new MercurialRevisionStorage( resource, csRemote.getRevision().getRevision(), csRemote .getChangeset(), csRemote); return incomingIStorage; } @Override public boolean isSupervised(IResource resource) { boolean result = resource.getType() == IResource.FILE && !resource.isTeamPrivateMember() /* && MercurialUtilities.isPossiblySupervised(resource)*/; if(!result){ return false; } // fix for issue 10153: Resources ignored in .hgignore are still shown in Synchronize view if(STATUS_CACHE.isIgnored(resource)){ return false; } return true; } @Override public IResource[] members(IResource resource) throws TeamException { return new IResource[0]; } /** * @param flag one of {@link HgSubscriberScopeManager} constants, if the value is negative, * otherwise some depth hints from the Team API (which are ignored here). *

* {@inheritDoc} */ @Override public void refresh(IResource[] resources, int flag, IProgressMonitor monitor) throws TeamException { if (resources == null) { return; } List resources2 = Arrays.asList(resources); Map> byProject = ResourceUtils.groupByProject(resources2); Set projects = byProject.keySet(); if(projects.isEmpty()){ return; } Map> byRoot = ResourceUtils.groupByRoot(new ArrayList(byProject.keySet())); // we need to send events only if WE trigger status update, not if the refresh // is called from the framework (like F5 hit by user) Set resourcesToRefresh; if(flag < 0){ resourcesToRefresh = new HashSet(); } else { // no need resourcesToRefresh = null; } IHgRepositoryLocation repositoryLocation = getRepo(); Set repoLocationProjects = MercurialEclipsePlugin.getRepoManager() .getAllRepoLocationProjects(repositoryLocation); Set roots = byRoot.keySet(); try { CACHE_SEMA.acquire(); for (HgRoot hgRoot : roots) { CURRENT_CS_MAP.remove(hgRoot); if (flag == HgSubscriberScopeManager.INCOMING || flag >= 0) { if (DEBUG) { System.out.println("clear incoming: " + hgRoot + ", depth: " + flag); } INCOMING_CACHE.clear(hgRoot, false); } if(flag == HgSubscriberScopeManager.OUTGOING || flag >= 0) { if(DEBUG) { System.out.println("clear outgoing: " + hgRoot + ", depth: " + flag); } OUTGOING_CACHE.clear(hgRoot, false); } if(flag == HgSubscriberScopeManager.LOCAL || flag >= 0) { if(DEBUG) { System.out.println("clear and refresh local: " + hgRoot + ", depth: " + flag); } STATUS_CACHE.clear(hgRoot, false); STATUS_CACHE.refreshStatus(hgRoot, monitor); } } } catch (InterruptedException e) { MercurialEclipsePlugin.logError(e); } finally { CACHE_SEMA.release(); } for (IProject project : projects) { if (!repoLocationProjects.contains(project)) { continue; } // clear caches in any case, but refresh them only if project exists HgRoot hgRoot = MercurialTeamProvider.getHgRoot(project); if(repositoryLocation.isLocal() && hgRoot.equals(repositoryLocation)) { continue; } monitor.beginTask(getName(), 2); boolean forceRefresh = project.exists(); String syncBranch = getSyncBranch(hgRoot); try { CACHE_SEMA.acquire(); if(DEBUG) { System.out.println("going to refresh local/in/out: " + project + ", depth: " + flag); } if (monitor.isCanceled()) { return; } monitor.subTask(Messages.getString("MercurialSynchronizeSubscriber.refreshingOutgoing")); //$NON-NLS-1$ refreshOutgoing(flag, resourcesToRefresh, project, repositoryLocation, forceRefresh, syncBranch); monitor.worked(1); if (monitor.isCanceled()) { return; } monitor.subTask(Messages.getString("MercurialSynchronizeSubscriber.refreshingIncoming")); //$NON-NLS-1$ refreshIncoming(flag, resourcesToRefresh, project, repositoryLocation, forceRefresh, syncBranch); monitor.worked(1); if (monitor.isCanceled()) { return; } } catch (HgException e) { throw new TeamException(new Status(IStatus.INFO, MercurialEclipsePlugin.ID, Messages.getString("MercurialSynchronizeSubscriber.connectError"))); } catch (InterruptedException e) { MercurialEclipsePlugin.logError(e); } finally { CACHE_SEMA.release(); } } // we need to send events only if WE trigger status update, not if the refresh // is called from the framework (like F5 hit by user) if(resourcesToRefresh != null){ List changeEvents = createEvents(resources, resourcesToRefresh); monitor.worked(1); if (monitor.isCanceled()) { return; } monitor.subTask(Messages.getString("MercurialSynchronizeSubscriber.triggeringStatusCalc")); //$NON-NLS-1$ lastEvents = changeEvents.toArray(new ISubscriberChangeEvent[changeEvents.size()]); fireTeamResourceChange(lastEvents); monitor.worked(1); } monitor.done(); } private List createEvents(IResource[] resources, Set resourcesToRefresh) { for (IResource resource : resources) { if(resource.getType() == IResource.FILE) { resourcesToRefresh.add(resource); } else { Set localMembers = STATUS_CACHE.getLocalMembers(resource); resourcesToRefresh.addAll(localMembers); } } List changeEvents = new ArrayList(); for (IResource res : resourcesToRefresh) { changeEvents.add(new SubscriberChangeEvent(this, ISubscriberChangeEvent.SYNC_CHANGED, res)); } if(DEBUG) { System.out.println("created: " + changeEvents.size() + " change events"); } return changeEvents; } private static void refreshIncoming(int flag, Set resourcesToRefresh, IProject project, IHgRepositoryLocation repositoryLocation, boolean forceRefresh, String branch) throws HgException { if(forceRefresh && flag != HgSubscriberScopeManager.OUTGOING){ if(DEBUG) { System.out.println("\nget incoming: " + project + ", depth: " + flag); } // this can trigger a refresh and a call to the remote server... if(resourcesToRefresh != null){ Set incomingMembers = INCOMING_CACHE.getMembers(project, repositoryLocation, branch); resourcesToRefresh.addAll(incomingMembers); } else { INCOMING_CACHE.getChangeSets(project, repositoryLocation, branch); } } } private static void refreshOutgoing(int flag, Set resourcesToRefresh, IProject project, IHgRepositoryLocation repositoryLocation, boolean forceRefresh, String branch) throws HgException { if(forceRefresh && flag != HgSubscriberScopeManager.INCOMING){ if(DEBUG) { System.out.println("get outgoing: " + project + ", depth: " + flag); } // this can trigger a refresh and a call to the remote server... if(resourcesToRefresh != null){ Set outgoingMembers = OUTGOING_CACHE.getMembers(project, repositoryLocation, branch); resourcesToRefresh.addAll(outgoingMembers); } else { OUTGOING_CACHE.getChangeSets(project, repositoryLocation, branch); } } } public RepositorySynchronizationScope getScope() { return scope; } protected IHgRepositoryLocation getRepo(){ return scope.getRepositoryLocation(); } public IProject[] getProjects() { return scope.getProjects(); } @Override public IResource[] roots() { return scope.getRoots(); } public void branchChanged(final HgRoot hgRoot){ IResource[] roots = roots(); boolean related = false; for (IResource resource : roots) { if(hgRoot.equals(MercurialTeamProvider.hasHgRoot(resource))){ related = true; break; } } if(!related){ return; } Job job = new Job("Updating branch info for " + hgRoot.getName()){ @Override protected IStatus run(IProgressMonitor monitor) { CURRENT_CS_MAP.remove(hgRoot); if(lastEvents != null) { fireTeamResourceChange(lastEvents); } return Status.OK_STATUS; } }; job.schedule(100); } /** * Overriden to made it accessible from {@link HgSubscriberScopeManager#update(java.util.Observable, Object)} * {@inheritDoc} */ @Override public void fireTeamResourceChange(ISubscriberChangeEvent[] deltas) { super.fireTeamResourceChange(deltas); if(collector != null) { collector.refresh(null); } } public void setParticipant(MercurialSynchronizeParticipant participant){ this.participant = participant; } public MercurialSynchronizeParticipant getParticipant() { return participant; } public void setCollector(HgChangesetsCollector collector){ this.collector = collector; } public HgChangesetsCollector getCollector() { return collector; } /** * @return The branch name to synchronize, or null to synchronize all branches */ public static String getSyncBranch(HgRoot hgRoot) { boolean syncCurBranch = MercurialEclipsePlugin.getDefault().getPreferenceStore().getBoolean(MercurialPreferenceConstants.PREF_SYNC_ONLY_CURRENT_BRANCH); return syncCurBranch ? MercurialTeamProvider.getCurrentBranch(hgRoot) : null; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("MercurialSynchronizeSubscriber ["); if (collector != null) { builder.append("collector="); builder.append(collector); builder.append(", "); } if (participant != null) { builder.append("participant="); builder.append(participant); builder.append(", "); } if (scope != null) { builder.append("scope="); builder.append(scope); } builder.append("]"); return builder.toString(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/Messages.java000066400000000000000000000021371173713500500333600ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.synchronize.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } PresentationMode.java000066400000000000000000000033201173713500500350050ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; /** * @author johnpeb */ public enum PresentationMode { FLAT(Messages.getString("PresentationMode.Flat")), // TREE(Messages.getString("PresentationMode.Tree")), // COMPRESSED_TREE(Messages.getString("PresentationMode.CompressedTree")); public static final String PREFERENCE_KEY = MercurialPreferenceConstants.PREF_SYNC_PRESENTATION_MODE; private final String localized; PresentationMode(String localized) { if (localized == null) { throw new IllegalStateException(); } this.localized = localized; } @Override public String toString() { return localized; } public static PresentationMode get() { String name = MercurialEclipsePlugin.getDefault().getPreferenceStore().getString(PREFERENCE_KEY); if (name != null) { try { return valueOf(name); } catch (IllegalArgumentException t) { } } return FLAT; } public void set() { MercurialEclipsePlugin.getDefault().getPreferenceStore().setValue(PREFERENCE_KEY, name()); } public boolean isSet() { return get() == this; } } RepositorySynchronizationScope.java000066400000000000000000000153461173713500500400330ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.mapping.ModelProvider; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.resources.mapping.ResourceMappingContext; import org.eclipse.core.resources.mapping.ResourceTraversal; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.team.core.mapping.ISynchronizationScope; import org.eclipse.team.core.mapping.ISynchronizationScopeChangeListener; import org.eclipse.team.internal.core.mapping.AbstractResourceMappingScope; import org.eclipse.team.internal.ui.Utils; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetModelProvider; /** * @author Andrei */ public class RepositorySynchronizationScope extends AbstractResourceMappingScope { private final IProject[] roots; private final ListenerList listeners; private final IHgRepositoryLocation repo; private MercurialSynchronizeSubscriber subscriber; private HgChangeSetModelProvider provider; public RepositorySynchronizationScope(IHgRepositoryLocation repo, IProject[] roots) { Assert.isNotNull(repo); this.repo = repo; if(roots != null) { this.roots = roots; } else { Set projects = MercurialEclipsePlugin.getRepoManager().getAllRepoLocationProjects(repo); this.roots = projects.toArray(new IProject[projects.size()]); } listeners = new ListenerList(ListenerList.IDENTITY); } @Override public void addScopeChangeListener(ISynchronizationScopeChangeListener listener) { listeners.add(listener); } public ISynchronizationScope asInputScope() { return this; } @Override public boolean contains(IResource resource) { ResourceTraversal[] traversals = getTraversals(); if(traversals == null){ return false; } for (ResourceTraversal traversal : traversals) { if (traversal.contains(resource)) { return true; } } return false; } public ResourceMappingContext getContext() { // TODO unclear return ResourceMappingContext.LOCAL_CONTEXT; } public ResourceMapping[] getInputMappings() { return Utils.getResourceMappings(getRoots()); } @Override public ResourceMapping getMapping(Object modelObject) { ResourceMapping[] mappings = getMappings(); for (ResourceMapping mapping : mappings) { if (mapping.getModelObject().equals(modelObject)) { return mapping; } } return null; } public ResourceMapping[] getMappings() { return getInputMappings(); } @Override public ResourceMapping[] getMappings(String modelProviderId) { if(!isSupportedModelProvider(modelProviderId)){ return null; } Set result = new HashSet(); ResourceMapping[] mappings = getMappings(); for (ResourceMapping mapping : mappings) { if (mapping.getModelProviderId().equals(modelProviderId)) { result.add(mapping); } } return result.toArray(new ResourceMapping[result.size()]); } private boolean isSupportedModelProvider(String modelProviderId) { return ModelProvider.RESOURCE_MODEL_PROVIDER_ID.equals(modelProviderId) || HgChangeSetModelProvider.ID.equals(modelProviderId); } @Override public ModelProvider[] getModelProviders() { Set result = new HashSet(); ResourceMapping[] mappings = getMappings(); for (ResourceMapping mapping : mappings) { ModelProvider modelProvider = mapping.getModelProvider(); if (modelProvider != null && isSupportedModelProvider(modelProvider.getId())) { result.add(modelProvider); } } result.add(getChangesetProvider()); return result.toArray(new ModelProvider[result.size()]); } public HgChangeSetModelProvider getChangesetProvider() { if (provider == null) { try { provider = (HgChangeSetModelProvider) ModelProvider.getModelProviderDescriptor(HgChangeSetModelProvider.ID) .getModelProvider(); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } return provider; } public IProject[] getProjects() { Set projects = new HashSet(); for (IProject res : roots) { projects.add(res); } return projects.toArray(new IProject[projects.size()]); } @Override public IProject[] getRoots() { return roots; } public ResourceTraversal[] getTraversals() { return new ResourceTraversal[] { new ResourceTraversal(getRoots(), IResource.DEPTH_INFINITE, IContainer.EXCLUDE_DERIVED) }; } public ResourceTraversal[] getTraversals(ResourceMapping mapping) { try { return mapping.getTraversals(getContext(), new NullProgressMonitor()); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return null; } } public boolean hasAdditionalMappings() { return false; } public boolean hasAdditonalResources() { return false; } public void refresh(ResourceMapping[] mappings) { if(!listeners.isEmpty()){ Object[] objects = listeners.getListeners(); for (Object object : objects) { ((ISynchronizationScopeChangeListener) object).scopeChanged(this, mappings, getTraversals()); } } } @Override public void removeScopeChangeListener(ISynchronizationScopeChangeListener listener) { listeners.remove(listener); } public IHgRepositoryLocation getRepositoryLocation() { return repo; } public void setSubscriber(MercurialSynchronizeSubscriber mercurialSynchronizeSubscriber) { this.subscriber = mercurialSynchronizeSubscriber; } public MercurialSynchronizeSubscriber getSubscriber() { return subscriber; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("RepositorySynchronizationScope ["); if (repo != null) { builder.append("repo="); builder.append(repo); builder.append(", "); } if (roots != null) { builder.append("roots="); builder.append(Arrays.toString(roots)); } builder.append("]"); return builder.toString(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/000077500000000000000000000000001173713500500324035ustar00rootroot00000000000000AbstractResourceSynchronizeAction.java000066400000000000000000000100451173713500500420340ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2004, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - Adaption to Mercurial * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.ArrayList; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * Get action that appears in the synchronize view. It's main purpose is to * filter the selection and delegate its execution to the get operation. */ public abstract class AbstractResourceSynchronizeAction extends PathAwareAction { public AbstractResourceSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); ImageDescriptor descriptor = createImageDescriptor(); if (descriptor != null) { setImageDescriptor(descriptor); } } protected ImageDescriptor createImageDescriptor() { return null; } @Override final protected SynchronizeModelOperation getSubscriberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements) { List selectedResources = new ArrayList(); List changesets = new ArrayList(); Object[] objects = getNormalizedSelection(); for (Object object : objects) { if (object instanceof IResource) { selectedResources.add((IResource) object); } else if (object instanceof IAdaptable){ IAdaptable adaptable = (IAdaptable) object; IResource resource = (IResource) adaptable.getAdapter(IResource.class); if(resource != null){ selectedResources.add(resource); } } else if (object instanceof WorkingChangeSet){ changesets.add((WorkingChangeSet) object); } } IResource[] resources = new IResource[selectedResources.size()]; selectedResources.toArray(resources); return createOperation(configuration, elements, resources, changesets); } abstract protected SynchronizeModelOperation createOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources, List changesets); @Override protected boolean isSupported(Object object) { if (object instanceof ChangeSet) { return object instanceof WorkingChangeSet && ((WorkingChangeSet) object).getFiles().size() > 0; } IResource resource = ResourceUtils.getResource(object); if (resource == null) { return false; } if (object instanceof FileFromChangeSet) { return ((FileFromChangeSet) object).getChangeset() instanceof WorkingChangeSet && isResourceSupported(resource); } return isResourceSupported(resource); } /** * Template method to determine if this action should be enabled for the given resource * * @param resource The resource to check * @return True if this action should be enabled */ protected boolean isResourceSupported(IResource resource) { return !MercurialStatusCache.getInstance().isClean(resource); } } AddAction.java000066400000000000000000000055321173713500500350220ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 Andrei Loskutov and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.ArrayList; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Andrei */ public class AddAction extends PathAwareAction { private final ISynchronizePageConfiguration configuration; public AddAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( ISharedImages.IMG_OBJ_ADD)); this.configuration = configuration; } @Override protected SynchronizeModelOperation getSubscriberOperation(ISynchronizePageConfiguration config, IDiffElement[] elements) { List selectedResources = new ArrayList(); Object[] objects = getNormalizedSelection(); for (Object object : objects) { if (object instanceof WorkingChangeSet){ selectedResources.addAll(((WorkingChangeSet) object).getFiles()); } else if(!(object instanceof ChangeSet)){ IResource resource = ResourceUtils.getResource(object); if(resource != null) { selectedResources.add(resource); } } } IResource[] resources = new IResource[selectedResources.size()]; selectedResources.toArray(resources); return new AddOperation(configuration, elements, resources); } /** * @see com.vectrace.MercurialEclipse.synchronize.actions.PathAwareAction#isSupported(java.lang.Object) */ @Override protected boolean isSupported(Object object) { IResource adapter = MercurialEclipsePlugin.getAdapter(object, IResource.class); if (adapter != null) { return MercurialStatusCache.getInstance().isUnknown(adapter); } return false; } } AddOperation.java000066400000000000000000000041101173713500500355340ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 Andrei Loskutov and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.AddHandler; /** * @author Andrei */ public class AddOperation extends SynchronizeModelOperation { private final IResource[] resources; protected AddOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources) { super(configuration, elements); this.resources = resources; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { if(resources.length == 0){ monitor.done(); return; } new SafeUiJob("Adding selected resources...") { @Override protected IStatus runSafe(IProgressMonitor moni) { AddHandler handler = new AddHandler(); try { handler.run(Arrays.asList(resources)); } catch (HgException e) { MercurialEclipsePlugin.showError(e); } moni.done(); return Status.OK_STATUS; } }.schedule(); monitor.done(); } } BackoutSynchronizeAction.java000066400000000000000000000055331173713500500401570ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov (Intland) implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.wizards.BackoutWizard; /** * @author Ilya Ivanov (Intland) */ public class BackoutSynchronizeAction extends SynchronizeModelAction { private final HgRoot hgRoot; private final ChangeSet changeSet; protected BackoutSynchronizeAction(String text, ISynchronizePageConfiguration configuration, HgRoot hgRoot, ChangeSet changeSet) { super(text, configuration); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/revert.gif")); this.hgRoot = hgRoot; this.changeSet = changeSet; } private class BackoutSynchronizeModelOperation extends SynchronizeModelOperation { protected BackoutSynchronizeModelOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements) { super(configuration, elements); } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { getShell().getDisplay().asyncExec(new Runnable() { public void run() { BackoutWizard backoutWizard = new BackoutWizard(hgRoot, changeSet); WizardDialog dialog = new WizardDialog(getShell(), backoutWizard); dialog.setBlockOnOpen(true); int result = dialog.open(); if(result == Window.OK){ new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.ALL).schedule(); } } }); } } @Override protected SynchronizeModelOperation getSubscriberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements) { return new BackoutSynchronizeModelOperation(configuration, elements); } } CommitSynchronizeAction.java000066400000000000000000000040271173713500500400140ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2004, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - Adaption to Mercurial * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; /** * Get action that appears in the synchronize view. It's main purpose is to * filter the selection and delegate its execution to the get operation. */ public class CommitSynchronizeAction extends AbstractResourceSynchronizeAction { public CommitSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); } @Override protected ImageDescriptor createImageDescriptor() { return MercurialEclipsePlugin.getImageDescriptor("actions/commit.gif"); } @Override protected SynchronizeModelOperation createOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources, List changesets) { return new CommitSynchronizeOperation(configuration, elements, resources, changesets); } } CommitSynchronizeOperation.java000066400000000000000000000101021173713500500405260ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2008 MercurialEclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.dialogs.CommitDialog.Options; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.CommitHandler; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.utils.StringUtils; public class CommitSynchronizeOperation extends SynchronizeModelOperation { private final IResource[] resources; private final List changesets; public CommitSynchronizeOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources, List changesets) { super(configuration, elements); this.resources = resources; this.changesets = changesets; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Loading Commit Window...", 1); new SafeUiJob("Committing selected resources...") { @Override protected IStatus runSafe(IProgressMonitor moni) { if (resources.length == 0 && !hasFiles(changesets)) { MessageDialog.openInformation(getShell(), "Mercurial Commit", //$NON-NLS-1$ "Please select at least one file to commit!"); //$NON-NLS-1$ return super.runSafe(moni); } if(resources.length == 0) { for (WorkingChangeSet cs : changesets) { if(cs.getFiles().isEmpty()) { continue; } CommitHandler commithandler = new CommitHandler(); if (cs instanceof GroupedUncommittedChangeSet) { Options options = new Options(); if (!StringUtils.isEmpty(cs.getComment())) { options.defaultCommitMessage = cs.getComment(); } else { options.defaultCommitMessage = cs.getName(); } commithandler.setOptions(options); } List files = new ArrayList(); files.addAll(cs.getFiles()); boolean done = commit(commithandler, files.toArray(new IResource[0])); if(done && cs instanceof GroupedUncommittedChangeSet) { GroupedUncommittedChangeSet gucs = (GroupedUncommittedChangeSet) cs; gucs.getGroup().committed(gucs); } } } else { final CommitHandler commithandler = new CommitHandler(); commit(commithandler, resources); } return super.runSafe(moni); } }.schedule(); monitor.done(); } protected boolean commit(final CommitHandler commithandler, IResource[] resources) { try { commithandler.run(Arrays.asList(resources)); return commithandler.getResult() == Window.OK; } catch (HgException e) { MercurialEclipsePlugin.logError(e); } return false; } static boolean hasFiles(List set) { for (WorkingChangeSet cs : set) { if(!cs.getFiles().isEmpty()) { return true; } } return false; } } CreateNewChangesetSynchronizeAction.java000066400000000000000000000073111173713500500422620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2011 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.viewers.ContentViewer; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import org.eclipse.ui.navigator.CommonViewer; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider; import com.vectrace.MercurialEclipse.synchronize.cs.UncommittedChangesetGroup; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted; /** * Creates new empty uncommitted changeset with default name */ public class CreateNewChangesetSynchronizeAction extends SynchronizeModelAction { public static final String ID = "hg.createNewChangeset"; public CreateNewChangesetSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); setId(ID); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("elcl16/uncommitted_cs.gif", "ovr/add_ovr.gif", IDecoration.TOP_RIGHT)); } @Override protected SynchronizeModelOperation getSubscriberOperation( final ISynchronizePageConfiguration configuration, IDiffElement[] elements) { IStructuredSelection sel = getStructuredSelection(); // it's guaranteed that we have exact one element final Object object = sel.getFirstElement(); if(object instanceof UncommittedChangesetGroup){ return new SynchronizeModelOperation(configuration, elements) { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { Viewer viewer = configuration.getPage().getViewer(); if(!(viewer instanceof ContentViewer)){ return; } CommonViewer commonViewer = (CommonViewer) viewer; final HgChangeSetContentProvider csProvider = OpenAction.getProvider(commonViewer.getNavigatorContentService()); IUncommitted uc = csProvider.getUncommittedEntry(); if (uc instanceof UncommittedChangesetGroup) { ((UncommittedChangesetGroup)uc).create(new IFile[0]); } else { MercurialEclipsePlugin.logError( "Unexped invocation of CreateNewChangesetSynchronizeAction", new IllegalStateException()); } } }; } return null; } @Override protected boolean updateSelection(IStructuredSelection selection) { boolean updateSelection = super.updateSelection(selection); if(!updateSelection){ Object[] array = selection.toArray(); if(selection.size() != 1){ return false; } return isSupported(array[0]); } return updateSelection; } private static boolean isSupported(Object object) { return object instanceof UncommittedChangesetGroup; } } DeleteAction.java000066400000000000000000000101541173713500500355300ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * adam.berkes - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author adam.berkes */ public class DeleteAction extends SynchronizeModelAction { public static final String HG_DELETE_GROUP = "hg.delete"; private final ISynchronizePageConfiguration configuration; public DeleteAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( ISharedImages.IMG_ETOOL_DELETE)); this.configuration = configuration; } @Override protected SynchronizeModelOperation getSubscriberOperation(ISynchronizePageConfiguration config, IDiffElement[] elements) { List selectedResources = new ArrayList(); IStructuredSelection sel = getStructuredSelection(); if(sel.size() == 1 && sel.getFirstElement() instanceof GroupedUncommittedChangeSet) { final GroupedUncommittedChangeSet changeSet = (GroupedUncommittedChangeSet) sel.getFirstElement(); return new SynchronizeModelOperation(config, elements) { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { changeSet.getGroup().delete(changeSet); } }; } Object[] objects = sel.toArray(); for (Object object : objects) { if (object instanceof WorkingChangeSet){ selectedResources.addAll(((WorkingChangeSet) object).getFiles()); } else if(!(object instanceof ChangeSet)){ IResource resource = ResourceUtils.getResource(object); if(resource != null) { selectedResources.add(resource); } } } IResource[] resources = new IResource[selectedResources.size()]; selectedResources.toArray(resources); return new DeleteOperation(configuration, elements, resources); } @Override protected final boolean updateSelection(IStructuredSelection selection) { boolean updateSelection = super.updateSelection(selection); if(!updateSelection){ if(selection.size() == 1 && selection.getFirstElement() instanceof GroupedUncommittedChangeSet) { GroupedUncommittedChangeSet changeSet = (GroupedUncommittedChangeSet) selection.getFirstElement(); if(changeSet.isDefault()) { return false; } return true; } Object[] array = selection.toArray(); for (Object object : array) { if(!isSupported(object)){ return false; } } return true; } return updateSelection; } private boolean isSupported(Object object) { IResource adapter = MercurialEclipsePlugin.getAdapter(object, IResource.class); if (adapter != null) { return true; } return false; } } DeleteOperation.java000066400000000000000000000044761173713500500362650ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * adam.berkes implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import org.eclipse.ui.actions.DeleteResourceAction; import com.vectrace.MercurialEclipse.SafeUiJob; /** * @author adam.berkes */ public class DeleteOperation extends SynchronizeModelOperation { private final IResource[] resources; protected DeleteOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources) { super(configuration, elements); this.resources = resources; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { if(resources.length == 0){ monitor.done(); return; } new SafeUiJob("Deleting selected resources...") { @Override protected IStatus runSafe(IProgressMonitor moni) { DeleteResourceAction resourceAction = new DeleteResourceAction(getShell()) { @Override protected List getSelectedResources() { return Arrays.asList(resources); } @Override protected boolean updateSelection(IStructuredSelection selection) { return true; } }; resourceAction.selectionChanged(new StructuredSelection(resources)); resourceAction.run(); moni.done(); return super.runSafe(moni); } }.schedule(); monitor.done(); } } EditChangesetSynchronizeAction.java000066400000000000000000000053551173713500500413000ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2004, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - Adaption to Mercurial * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; /** * Get action that appears in the synchronize view. It's main purpose is to * filter the selection and delegate its execution to the get operation. */ public class EditChangesetSynchronizeAction extends SynchronizeModelAction { public static final String ID = "hg.editChangeset"; public EditChangesetSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); setId(ID); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("elcl16/uncommitted_cs.gif", "ovr/edited_ovr.gif", IDecoration.TOP_RIGHT)); } @Override protected SynchronizeModelOperation getSubscriberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements) { IStructuredSelection sel = getStructuredSelection(); // it's guaranteed that we have exact one element Object object = sel.getFirstElement(); if (isSupported(object)){ return new EditChangesetSynchronizeOperation(configuration, elements, (GroupedUncommittedChangeSet) object); } return null; } @Override protected boolean updateSelection(IStructuredSelection selection) { boolean updateSelection = super.updateSelection(selection); if(!updateSelection){ Object[] array = selection.toArray(); if(selection.size() != 1){ return false; } return isSupported(array[0]); } return updateSelection; } private static boolean isSupported(Object object) { return object instanceof GroupedUncommittedChangeSet; } } EditChangesetSynchronizeOperation.java000066400000000000000000000055521173713500500420220ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2008 MercurialEclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Subclipse - original impl.o * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import java.util.Set; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.window.Window; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.dialogs.EditChangesetDialog; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class EditChangesetSynchronizeOperation extends SynchronizeModelOperation { private final GroupedUncommittedChangeSet changeset; // private final ISynchronizePageConfiguration configuration; // private MercurialSynchronizeParticipant participant; public EditChangesetSynchronizeOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements, GroupedUncommittedChangeSet input) { super(configuration, elements); // this.configuration = configuration; // ISynchronizeParticipant participant1 = configuration.getParticipant(); // if(participant1 instanceof MercurialSynchronizeParticipant) { // this.participant = (MercurialSynchronizeParticipant) participant1; // } this.changeset = input; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { getPart(); getShell().getDisplay().asyncExec(new Runnable() { public void run() { // TODO get hg root and get the changeset type boolean isDefaultChangeset = changeset.isDefault(); HgRoot hgRoot; Set files = changeset.getFiles(); if(files.isEmpty()){ hgRoot = HgRoot.NO_ROOT; } else { // TODO not elegant. Should we restrict changesets to one root only? hgRoot = ResourceUtils.groupByRoot(files).keySet().iterator().next(); } EditChangesetDialog dialog = new EditChangesetDialog(getShell(), hgRoot, changeset, isDefaultChangeset); int ok = dialog.open(); if(Window.OK != ok){ return; } changeset.getGroup().changesetChanged(changeset); } }); monitor.done(); } } ExportPatchSynchronizeAction.java000066400000000000000000000065771173713500500410410ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.wizards.ExportPatchWizard; public class ExportPatchSynchronizeAction extends SynchronizeModelAction { public ExportPatchSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("export.gif")); } // operations protected ChangeSet getChangeSet(IStructuredSelection selection) { Object el; if (selection.size() == 1 && (el = selection.getFirstElement()) instanceof ChangeSet && ((ChangeSet) el).getDirection() == Direction.OUTGOING) { return (ChangeSet) el; } return null; } /** * @see com.vectrace.MercurialEclipse.synchronize.actions.PathAwareAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) */ @Override protected boolean updateSelection(IStructuredSelection selection) { super.updateSelection(selection); // Needed? return getChangeSet(selection) != null; } /** * @see org.eclipse.team.ui.synchronize.SynchronizeModelAction#getSubscriberOperation(org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration, * org.eclipse.compare.structuremergeviewer.IDiffElement[]) */ @Override protected final SynchronizeModelOperation getSubscriberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements) { return getSubsciberOperation(configuration, elements, getChangeSet(getStructuredSelection())); } protected SynchronizeModelOperation getSubsciberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements, final ChangeSet cs) { return new SynchronizeModelOperation(configuration, elements) { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { if (cs != null) { getShell().getDisplay().asyncExec(new Runnable() { public void run() { ExportPatchWizard wizard = new ExportPatchWizard(cs); WizardDialog dialog = new WizardDialog(getShell(), wizard); dialog.setBlockOnOpen(true); dialog.open(); } }); } } }; } } MercurialSynchronizePageActionGroup.java000066400000000000000000000406541173713500500423270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2008 MercurialEclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) * Adam Berkes (Intland) - modifications * Ilya Ivanov (Intland) - modifications ******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.ArrayList; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.team.internal.ui.synchronize.SynchronizePageConfiguration; import org.eclipse.team.internal.ui.synchronize.actions.OpenInCompareAction; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipantActionGroup; import org.eclipse.ui.IActionBars; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeParticipant; import com.vectrace.MercurialEclipse.synchronize.Messages; import com.vectrace.MercurialEclipse.synchronize.PresentationMode; import com.vectrace.MercurialEclipse.synchronize.cs.ChangesetGroup; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetActionProvider; @SuppressWarnings("restriction") public class MercurialSynchronizePageActionGroup extends ModelSynchronizeParticipantActionGroup { static final String EDIT_CHANGESET_ACTION = "hg.editChangeset"; private static final String HG_COMMIT_GROUP = "hg.commit"; private static final String HG_PUSH_PULL_GROUP = "hg.push.pull"; // see org.eclipse.ui.IWorkbenchCommandConstants.EDIT_DELETE which was introduced in 3.5 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=54581 // TODO replace with the constant as soon as we drop Eclipse 3.4 support public static final String EDIT_DELETE = "org.eclipse.ui.edit.delete"; public static final String HG_CHANGESETS_GROUP = "hg.changesets"; private final IAction expandAction; private final PreferenceAction allBranchesAction; private final ArrayList presentationModeActions; private OpenAction openAction; private final LocalChangeSetEnableAction localChangeSetEnableAction; // constructor public MercurialSynchronizePageActionGroup() { super(); expandAction = new Action("Expand All", MercurialEclipsePlugin.getImageDescriptor("elcl16/expandall.gif")) { @Override public void run() { Viewer viewer = getConfiguration().getPage().getViewer(); if(viewer instanceof AbstractTreeViewer){ AbstractTreeViewer treeViewer = (AbstractTreeViewer) viewer; treeViewer.expandAll(); } } }; IPreferenceStore prefStore = MercurialEclipsePlugin.getDefault().getPreferenceStore(); presentationModeActions = new ArrayList(); for (PresentationMode mode : PresentationMode.values()) { presentationModeActions.add(new PresentationModeAction(mode, prefStore)); } localChangeSetEnableAction = new LocalChangeSetEnableAction(prefStore); allBranchesAction = new PreferenceAction("Synchronize all branches", IAction.AS_CHECK_BOX, prefStore, MercurialPreferenceConstants.PREF_SYNC_ONLY_CURRENT_BRANCH) { @Override public void run() { prefStore.setValue(prefKey, !isChecked()); MercurialSynchronizeParticipant participant = (MercurialSynchronizeParticipant)getConfiguration().getParticipant(); participant.refresh(getConfiguration().getSite().getWorkbenchSite(), participant .getContext().getScope().getMappings()); } @Override protected void update() { setChecked(!prefStore.getBoolean(prefKey)); } }; allBranchesAction.setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/branch.gif")); allBranchesAction.update(); } // operations @Override public void initialize(ISynchronizePageConfiguration configuration) { super.initialize(configuration); String keyOpen = SynchronizePageConfiguration.P_OPEN_ACTION; Object property = configuration.getProperty(keyOpen); if(property instanceof Action){ openAction = new OpenAction((Action) property, configuration); // override default action used on double click with our custom configuration.setProperty(keyOpen, openAction); } appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, ISynchronizePageConfiguration.FILE_GROUP, new OpenMergeEditorAction("Open In Merge Editor", configuration, getVisibleRootsSelectionProvider())); appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, ISynchronizePageConfiguration.FILE_GROUP, new ShowHistorySynchronizeAction("Show History", configuration, getVisibleRootsSelectionProvider())); appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, HG_PUSH_PULL_GROUP, new PushPullSynchronizeAction("Push", configuration, getVisibleRootsSelectionProvider(), false, false)); appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, HG_PUSH_PULL_GROUP, new PushPullSynchronizeAction("Pull and Update", configuration, getVisibleRootsSelectionProvider(), true, true)); appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, HG_PUSH_PULL_GROUP, new PushPullSynchronizeAction("Pull", configuration, getVisibleRootsSelectionProvider(), true, false)); appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, HG_CHANGESETS_GROUP, new CreateNewChangesetSynchronizeAction("Create New Change Set", configuration, getVisibleRootsSelectionProvider())); EditChangesetSynchronizeAction editAction = new EditChangesetSynchronizeAction("Edit Change Set...", configuration, getVisibleRootsSelectionProvider()); appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, HG_CHANGESETS_GROUP, editAction); // remember action to allow OpenAction re-use it on double click configuration.setProperty(EDIT_CHANGESET_ACTION, editAction); appendToGroup(ISynchronizePageConfiguration.P_CONTEXT_MENU, HG_CHANGESETS_GROUP, new SetDefaultChangesetSynchronizeAction("Set as Default Change Set", configuration, getVisibleRootsSelectionProvider())); } @Override public void fillContextMenu(IMenuManager menu) { if(menu.find(DeleteAction.HG_DELETE_GROUP) == null){ menu.insertBefore(ISynchronizePageConfiguration.NAVIGATE_GROUP, new Separator( DeleteAction.HG_DELETE_GROUP)); } if(menu.find(HG_COMMIT_GROUP) == null){ menu.insertBefore(DeleteAction.HG_DELETE_GROUP, new Separator(HG_COMMIT_GROUP)); } if (localChangeSetEnableAction.getBoolean()) { if(menu.find(HG_CHANGESETS_GROUP) == null) { menu.insertAfter(ISynchronizePageConfiguration.EDIT_GROUP, new Separator(HG_CHANGESETS_GROUP)); } } else { menu.remove(HG_CHANGESETS_GROUP); } if (menu.find(HG_PUSH_PULL_GROUP) == null) { menu.insertAfter(ISynchronizePageConfiguration.NAVIGATE_GROUP, new Separator(HG_PUSH_PULL_GROUP)); } addUndoMenu(menu); if (isSelectionUncommited()) { menu.insertAfter( HG_COMMIT_GROUP, new AddAction("Add...", getConfiguration(), getVisibleRootsSelectionProvider())); menu.insertAfter( HG_COMMIT_GROUP, new CommitSynchronizeAction("Commit...", getConfiguration(), getVisibleRootsSelectionProvider())); menu.insertAfter( HG_COMMIT_GROUP, new RevertSynchronizeAction("Revert...", getConfiguration(), getVisibleRootsSelectionProvider())); menu.insertAfter( HG_COMMIT_GROUP, new ResolveSynchronizeAction("Mark as Resolved", getConfiguration(), getVisibleRootsSelectionProvider())); } else if (isSelectionOutgoing()) { menu.insertAfter( HG_COMMIT_GROUP, new ExportPatchSynchronizeAction("Export as patch...", getConfiguration(), getVisibleRootsSelectionProvider())); menu.insertAfter( HG_COMMIT_GROUP, new SwitchToSynchronizeAction("Switch to", "Switch to parent", getConfiguration(), getVisibleRootsSelectionProvider())); } super.fillContextMenu(menu); // menu.remove("org.eclipse.team.ui.synchronizeLast"); replaceCompareAndMoveDeleteAction(menu); } private boolean isSelectionUncommited() { Object[] selectedObjects = getSelectedObjects(); if (selectedObjects.length == 0) { return false; } for (Object object : selectedObjects) { if (object instanceof WorkingChangeSet) { continue; } else if (object instanceof FileFromChangeSet) { FileFromChangeSet file = (FileFromChangeSet) object; if (!(file.getChangeset() instanceof WorkingChangeSet)) { return false; } } else { return false; } } return true; } private boolean isSelectionOutgoing() { Object[] selectedObjects = getSelectedObjects(); if (selectedObjects.length == 0) { return false; } for (Object object : selectedObjects) { if (object instanceof ChangesetGroup) { ChangesetGroup csGroup = (ChangesetGroup) object; if (csGroup.getDirection() != Direction.OUTGOING) { return false; } } else if (object instanceof ChangeSet) { ChangeSet cs = (ChangeSet) object; if (cs.getDirection() != Direction.OUTGOING || cs instanceof WorkingChangeSet) { return false; } } else { return false; } } return true; } private void addUndoMenu(IMenuManager menu) { MenuManager submenu = new MenuManager("Undo", MercurialEclipsePlugin.getImageDescriptor("undo_edit.gif"), null); menu.insertBefore(ISynchronizePageConfiguration.NAVIGATE_GROUP, submenu); ISelection selection = getContext().getSelection(); if (!(selection instanceof StructuredSelection)) { return; } StructuredSelection stSelection = (StructuredSelection) selection; if (stSelection.size() != 1) { return; } Object object = stSelection.iterator().next(); if (object instanceof WorkingChangeSet) { return; } if (object instanceof ChangesetGroup) { ChangesetGroup csGroup = ((ChangesetGroup) object); if (csGroup.getChangesets().isEmpty() || csGroup.getDirection() != Direction.OUTGOING) { return; } HgRoot hgRoot = csGroup.getChangesets().iterator().next().getHgRoot(); menu.insertBefore(ISynchronizePageConfiguration.NAVIGATE_GROUP, new RollbackSynchronizeAction("Rollback", getConfiguration(), hgRoot, null)); } else if (object instanceof ChangeSet) { ChangeSet changeSet = (ChangeSet) object; if (changeSet.getDirection() != Direction.OUTGOING) { return; } HgRoot hgRoot = changeSet.getHgRoot(); submenu.add(new BackoutSynchronizeAction("Backout...", getConfiguration(), hgRoot, changeSet)); submenu.add(new StripSynchronizeAction("Strip...", getConfiguration(), hgRoot, changeSet)); } } /** * @return Not null. */ private Object[] getSelectedObjects() { ISelection selection = getContext().getSelection(); Object[] arr = null; if (selection instanceof StructuredSelection) { arr = ((StructuredSelection) selection).toArray(); } return PathAwareAction.normalize(arr); } /** * Replaces default "OpenInCompareAction" action with our custom, moves delete action * * @see OpenInCompareAction * @see ModelSynchronizeParticipantActionGroup * @see HgChangeSetActionProvider */ private void replaceCompareAndMoveDeleteAction(IMenuManager menu) { if(openAction == null){ return; } Object[] elements = ((IStructuredSelection) getContext().getSelection()).toArray(); if (elements.length == 0) { return; } IContributionItem fileGroup = findGroup(menu, ISynchronizePageConfiguration.FILE_GROUP); if (fileGroup == null) { return; } IContributionItem[] items = menu.getItems(); for (IContributionItem ci : items) { if(!(ci instanceof ActionContributionItem)){ continue; } ActionContributionItem ai = (ActionContributionItem) ci; IAction action = ai.getAction(); if(action instanceof OpenInCompareAction){ menu.remove(ai); openAction.setImageDescriptor(action.getImageDescriptor()); openAction.setText(action.getText()); menu.prependToGroup(fileGroup.getId(), openAction); } else if(EDIT_DELETE.equals(action.getActionDefinitionId())){ menu.remove(ai); menu.appendToGroup(DeleteAction.HG_DELETE_GROUP, ai); } } } @Override public void fillActionBars(IActionBars actionBars) { super.fillActionBars(actionBars); IToolBarManager manager = actionBars.getToolBarManager(); appendToGroup(manager, ISynchronizePageConfiguration.NAVIGATE_GROUP, expandAction); appendToGroup(manager, ISynchronizePageConfiguration.MODE_GROUP, allBranchesAction); IMenuManager menu = actionBars.getMenuManager(); IContributionItem group = findGroup(menu, ISynchronizePageConfiguration.LAYOUT_GROUP); if (menu != null && group != null) { menu.appendToGroup(group.getId(), allBranchesAction); MenuManager layout = new MenuManager(Messages .getString("MercurialSynchronizePageActionGroup.PresentationMode")); menu.appendToGroup(group.getId(), layout); for (PresentationModeAction action : presentationModeActions) { layout.add(action); } menu.appendToGroup(group.getId(), localChangeSetEnableAction); } } /** * @see org.eclipse.team.ui.synchronize.ModelSynchronizeParticipantActionGroup#dispose() */ @Override public void dispose() { for (PresentationModeAction action : presentationModeActions) { action.dispose(); } allBranchesAction.dispose(); localChangeSetEnableAction.dispose(); super.dispose(); } // inner types /** * Listens to a preference store. Must be disposed. */ private static abstract class PreferenceAction extends Action implements IPropertyChangeListener { protected final IPreferenceStore prefStore; protected final String prefKey; protected PreferenceAction(String name, int style, IPreferenceStore configuration, String prefKey) { super(name, style); this.prefStore = configuration; this.prefKey = prefKey; configuration.addPropertyChangeListener(this); } protected abstract void update(); public void dispose() { prefStore.removePropertyChangeListener(this); } public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(prefKey)) { update(); } } protected boolean getBoolean() { return prefStore.getBoolean(prefKey); } protected void set(boolean val) { prefStore.setValue(prefKey, val); } } private static class PresentationModeAction extends PreferenceAction { private final PresentationMode mode; protected PresentationModeAction(PresentationMode mode, IPreferenceStore configuration) { super(mode.toString(), IAction.AS_RADIO_BUTTON, configuration, PresentationMode.PREFERENCE_KEY); this.mode = mode; update(); } @Override public void run() { mode.set(); } @Override public void update() { setChecked(mode.isSet()); } } private static class LocalChangeSetEnableAction extends PreferenceAction { protected LocalChangeSetEnableAction(IPreferenceStore configuration) { super("Enable local changesets", IAction.AS_CHECK_BOX, configuration, MercurialPreferenceConstants.PREF_SYNC_ENABLE_LOCAL_CHANGESETS); setToolTipText("Enable local changesets (Grouping of uncommitted changes)"); update(); } @Override public void run() { set(isChecked()); } @Override public void update() { setChecked(getBoolean()); } } } OpenAction.java000066400000000000000000000175411173713500500352360ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.Set; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ContentViewer; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.ui.navigator.CommonViewer; import org.eclipse.ui.navigator.INavigatorContentExtension; import org.eclipse.ui.navigator.INavigatorContentService; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.model.ChangeSet.ParentChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.synchronize.cs.ChangesetGroup; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetModelProvider; import com.vectrace.MercurialEclipse.team.CompareAction; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.NullRevision; import com.vectrace.MercurialEclipse.utils.CompareUtils; /** * @author Andrei */ public class OpenAction extends Action { private final Action defaultOpen; private final ISynchronizePageConfiguration configuration; public OpenAction(Action defaultOpen, ISynchronizePageConfiguration configuration) { super(); this.defaultOpen = defaultOpen; this.configuration = configuration; } @Override public void run() { Object input = configuration.getPage().getViewer().getInput(); if(!(input instanceof HgChangeSetModelProvider)) { // this is the "default" workspace resources mode if(defaultOpen != null){ defaultOpen.run(); } return; } ISelection selection = configuration.getSite().getSelectionProvider().getSelection(); if(!(selection instanceof IStructuredSelection)){ return; } IStructuredSelection selection2 = (IStructuredSelection) selection; if(selection2.size() != 1){ return; } Object object = selection2.getFirstElement(); if(!(object instanceof FileFromChangeSet)){ if(object instanceof WorkingChangeSet) { tryToEditChangeset(selection2); } return; } FileFromChangeSet fcs = (FileFromChangeSet) object; Viewer viewer = configuration.getPage().getViewer(); if(!(viewer instanceof ContentViewer)){ return; } CommonViewer commonViewer = (CommonViewer) viewer; final HgChangeSetContentProvider csProvider = getProvider(commonViewer.getNavigatorContentService()); final ChangeSet cs = csProvider.getParentOfSelection(fcs); if(cs == null){ return; } final IFile file = fcs.getFile(); if(file == null){ // TODO this can happen, if the file was modified but is OUTSIDE Eclipse workspace MessageDialog.openInformation(null, "Compare", "Diff for files external to Eclipse workspace is not supported yet!"); return; } IFile sourceFile = fcs.getCopySourceFile(); final IFile parentFile = sourceFile != null? sourceFile : file; if(cs instanceof WorkingChangeSet){ // default: compare local file against parent changeset CompareAction compareAction = new CompareAction(file); compareAction.setUncommittedCompare(true); compareAction.setSynchronizePageConfiguration(configuration); compareAction.run(this); return; } // XXX Andrei: the code below is copied from Incoming/Outgoing Page classes. // it has to be moved to a common class/method and verified if it works at all in all cases Job job = new Job("Diff for " + file.getName()) { @Override protected IStatus run(IProgressMonitor monitor) { if(cs.getDirection() == Direction.OUTGOING){ String[] parents = cs.getParents(); MercurialRevisionStorage thisRev = new MercurialRevisionStorage(file, cs.getChangeset()); MercurialRevisionStorage parentRev; if(parents.length == 0){ // TODO for some reason, we do not always have right parent info in the changesets // if we are on the different branch then the changeset. So simply enforce the parents resolving try { parents = HgParentClient.getParentNodeIds(file, cs); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } if(cs.getRevision().getRevision() == 0 || parents.length == 0){ parentRev = new NullRevision(file, cs); } else { parentRev = new MercurialRevisionStorage(parentFile, parents[0]); } CompareUtils.openEditor(thisRev, parentRev, false, configuration); } else { // incoming MercurialRevisionStorage remoteRev = new MercurialRevisionStorage( file, cs.getChangesetIndex(), cs.getChangeset(), cs); MercurialRevisionStorage parentRev; String[] parents = cs.getParents(); if(cs.getRevision().getRevision() == 0 || parents.length == 0){ parentRev = new NullRevision(file, cs); } else { String parentId = parents[0]; ChangeSet parentCs = null; ChangesetGroup group = csProvider.getParentGroup(cs); Set changesets = new TreeSet(); if(group != null){ changesets.addAll(group.getChangesets()); } for (ChangeSet cset : changesets) { if(parentId.endsWith(cset.getChangeset()) && parentId.startsWith("" + cset.getChangesetIndex())){ parentCs = cset; break; } } if(parentCs == null) { parentCs = new ParentChangeSet(parentId, cs); } parentRev = new MercurialRevisionStorage( parentFile, parentCs.getChangesetIndex(), parentCs.getChangeset(), parentCs); } CompareUtils.openEditor(remoteRev, parentRev, false, configuration); // the line below compares the remote changeset with the local copy. // it was replaced with the code above to fix the issue 10364 // CompareUtils.openEditor(file, cs, true, true); } return Status.OK_STATUS; } }; job.schedule(); } protected void tryToEditChangeset(IStructuredSelection selection) { Object property = configuration.getProperty(MercurialSynchronizePageActionGroup.EDIT_CHANGESET_ACTION); if(property instanceof EditChangesetSynchronizeAction) { EditChangesetSynchronizeAction editAction = (EditChangesetSynchronizeAction) property; editAction.selectionChanged(selection); if(editAction.isEnabled()) { editAction.run(); } } } public static HgChangeSetContentProvider getProvider(INavigatorContentService service) { INavigatorContentExtension extensionById = service .getContentExtensionById(HgChangeSetContentProvider.ID); IContentProvider provider = extensionById.getContentProvider(); if (provider instanceof HgChangeSetContentProvider) { return (HgChangeSetContentProvider) provider; } return null; } } OpenMergeEditorAction.java000066400000000000000000000055411173713500500373620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 Andrei Loskutov and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.team.CompareAction; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; /** * @author Andrei */ public class OpenMergeEditorAction extends SynchronizeModelAction { public OpenMergeEditorAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/merge.gif")); } @Override protected SynchronizeModelOperation getSubscriberOperation(ISynchronizePageConfiguration config, IDiffElement[] elements) { IStructuredSelection sel = getStructuredSelection(); Object object = sel.getFirstElement(); final IFile file = MercurialEclipsePlugin.getAdapter(object, IFile.class); return new SynchronizeModelOperation(config, elements){ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { CompareAction compareAction = new CompareAction(file); compareAction.setEnableMerge(true); compareAction.run(null); } }; } @Override protected final boolean updateSelection(IStructuredSelection selection) { boolean updateSelection = super.updateSelection(selection); if(!updateSelection){ if(selection.size() != 1){ return false; } Object object = selection.getFirstElement(); return isSupported(object); } return updateSelection; } private boolean isSupported(Object object) { IFile adapter = MercurialEclipsePlugin.getAdapter(object, IFile.class); if (adapter != null) { return !MercurialStatusCache.getInstance().isClean(adapter) && MercurialStatusCache.getInstance().isMergeInProgress(adapter); } return false; } } PathAwareAction.java000066400000000000000000000067611173713500500362130ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import com.vectrace.MercurialEclipse.model.PathFromChangeSet; /** * An action that can operate on folder nodes in "compressed tree" or "tree" mode in the synchronize * view. * * @see PathFromChangeSet */ public abstract class PathAwareAction extends SynchronizeModelAction { public PathAwareAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); } // operations /** * @see org.eclipse.ui.actions.BaseSelectionListenerAction#getStructuredSelection() * @deprecated Use {@link #getNormalizedSelection()} */ @Override @Deprecated public IStructuredSelection getStructuredSelection() { return super.getStructuredSelection(); } /** * @return Selected items with tree nodes replaced with their children. */ protected Object[] getNormalizedSelection() { return normalize(super.getStructuredSelection().toArray()); } @Override protected boolean updateSelection(IStructuredSelection selection) { // TODO: why do we calculate this only if parent says it should be disabled? if (!super.updateSelection(selection)) { Object[] array = normalize(selection.toArray()); for (Object object : array) { if (!isSupported(object)) { return false; } } return true; } return true; } /** * Whether the action should be enabled for this object. * * @param object * The object to check. Note: Will never be a PathFromChangeSet. * @return False to disable the action */ protected abstract boolean isSupported(Object object); /** * Depending on the synchronize presentation mode there may be {@link PathFromChangeSet}s * present in selection, but actions need not operate on them. This method replaces such path * nodes with their children. * * @param selection * The selection to normalize. May be null. * @return Normalized copy of selection. Not null. */ public static Object[] normalize(Object[] selection) { if (selection != null) { return normalize(selection, new ArrayList(selection.length)).toArray(); } return new Object[0]; } /** * @param selection * Selection to normalize * @param l * (Output) All the elements of selection are added to this, replacing path nodes * with their children * @return l */ private static List normalize(Object[] selection, List l) { for (int i = 0; i < selection.length; i++) { if (selection[i] instanceof PathFromChangeSet) { normalize(((PathFromChangeSet) selection[i]).getChildren(), l); } else { l.add(selection[i]); } } return l; } } PushPullSynchronizeAction.java000066400000000000000000000075511173713500500403450ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2004, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - Adaption to Mercurial * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IProject; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.synchronize.cs.ChangesetGroup; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * Get action that appears in the synchronize view. It's main purpose is to * filter the selection and delegate its execution to the get operation. */ public class PushPullSynchronizeAction extends SynchronizeModelAction { private final boolean update; private final boolean isPull; public PushPullSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider, boolean isPull, boolean update) { super(text, configuration, selectionProvider); this.isPull = isPull; this.update = update; if(isPull) { setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/update.gif")); } else { setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/commit.gif")); } } @Override protected SynchronizeModelOperation getSubscriberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements) { IStructuredSelection sel = getStructuredSelection(); // it's guaranteed that we have exact one, allowed element (project, changeset or csGroup) Object object = sel.getFirstElement(); return new PushPullSynchronizeOperation(configuration, elements, object, isPull, update); } @Override protected boolean updateSelection(IStructuredSelection selection) { boolean updateSelection = super.updateSelection(selection); if(!updateSelection){ Object[] array = selection.toArray(); if(selection.size() != 1){ return false; } return isSupported(array[0]); } return updateSelection; } public boolean isPull() { return isPull; } private boolean isSupported(Object object) { if(object instanceof IProject){ return true; } if(object instanceof ChangesetGroup){ ChangesetGroup group = (ChangesetGroup) object; return isMatching(group.getDirection()) && !group.getChangesets().isEmpty(); } if (object instanceof ChangeSet) { ChangeSet changeSet = (ChangeSet) object; return !(changeSet instanceof WorkingChangeSet) && isMatching(changeSet.getDirection()) && (!update || !isPull || isMatchingBranch(changeSet)); } return false; } private boolean isMatching(Direction d) { return (d == Direction.INCOMING && isPull) || (d == Direction.OUTGOING && !isPull); } private boolean isMatchingBranch(ChangeSet cs) { return Branch.same(MercurialTeamProvider.getCurrentBranch(cs.getHgRoot()), cs.getBranch()); } } PushPullSynchronizeOperation.java000066400000000000000000000213431173713500500410630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2008 MercurialEclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import java.util.Set; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import org.eclipse.ui.statushandlers.StatusManager; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgPushPullClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.PushHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeParticipant; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeSubscriber; import com.vectrace.MercurialEclipse.synchronize.Messages; import com.vectrace.MercurialEclipse.synchronize.cs.ChangesetGroup; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class PushPullSynchronizeOperation extends SynchronizeModelOperation { private final MercurialSynchronizeParticipant participant; private final boolean update; private final boolean isPull; private final Object target; public PushPullSynchronizeOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements, Object target, boolean isPull, boolean update) { super(configuration, elements); this.target = target; this.participant = (MercurialSynchronizeParticipant) configuration.getParticipant(); this.isPull = isPull; this.update = update; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { HgRoot hgRoot = null; ChangeSet changeSet = null; if (target instanceof IProject) { hgRoot = MercurialTeamProvider.getHgRoot((IProject) target); } else if (target instanceof ChangeSet) { changeSet = (ChangeSet) target; hgRoot = changeSet.getHgRoot(); } if (target instanceof ChangesetGroup) { ChangesetGroup group = (ChangesetGroup) target; checkChangesets(monitor, group); if(monitor.isCanceled()){ return; } // Alternative: Find all the heads and push/pull them individually (without doing // workspace refreshes in between) changeSet = null; hgRoot = group.getChangesets().iterator().next().getHgRoot(); } if(hgRoot == null){ String message = "No hg root found for: " + target + ". Operation cancelled."; Status status = new Status(IStatus.WARNING, MercurialEclipsePlugin.ID, message); StatusManager.getManager().handle(status, StatusManager.SHOW); monitor.setCanceled(true); return; } checkProjects(monitor, hgRoot); if(monitor.isCanceled()){ return; } monitor.beginTask(getTaskName(hgRoot), 1); String jobName = isPull ? Messages.getString("PushPullSynchronizeOperation.PullJob") : Messages.getString("PushPullSynchronizeOperation.PushJob"); PushPullJob job = new PushPullJob(jobName, hgRoot, changeSet, monitor); if (changeSet == null) { job.setBranch(MercurialSynchronizeSubscriber.getSyncBranch(hgRoot)); } job.schedule(); } private String getTaskName(HgRoot hgRoot) { String taskName; if (isPull) { taskName = Messages.getString("PushPullSynchronizeOperation.PullTask") + " " + participant.getRepositoryLocation(); } else { taskName = Messages.getString("PushPullSynchronizeOperation.PushTask") + " " + hgRoot.getName(); } return taskName; } private void checkChangesets(final IProgressMonitor monitor, ChangesetGroup group) { int csCount = group.getChangesets().size(); if(csCount < 1){ // paranoia... monitor.setCanceled(true); return; } final String title; final String message; if(isPull){ title = "Hg Pull"; message = "Pulling " + csCount + " changesets (or more) from the remote repository.\n" + "The pull will fetch the *latest* version available remote.\n" + "Continue?"; } else { if(csCount == 1){ return; } title = "Hg Push"; message = "Pushing " + csCount + " changesets to the remote repository. Continue?"; } getShell().getDisplay().syncExec(new Runnable(){ public void run() { if (!MercurialEclipsePlugin.showDontShowAgainConfirmDialog(title, message, MessageDialog.CONFIRM, MercurialPreferenceConstants.PREF_SHOW_PULL_WARNING_DIALOG, getShell())) { monitor.setCanceled(true); } } }); } private void checkProjects(final IProgressMonitor monitor, HgRoot hgRoot) { Set projects = ResourceUtils.getProjects(hgRoot); if(!isPull || projects.size() <= 1) { if(projects.size() == 0){ // paranoia monitor.setCanceled(true); } return; } final String title = "Hg Pull"; final String message = "Pull will affect " + projects.size() + " projects in workspace. Continue?"; getShell().getDisplay().syncExec(new Runnable(){ public void run() { if (!MercurialEclipsePlugin .showDontShowAgainConfirmDialog(title, message, MessageDialog.CONFIRM, MercurialPreferenceConstants.PREF_SHOW_MULTIPLE_PROJECTS_DIALOG, getShell())) { monitor.setCanceled(true); } } }); } private final class PushPullJob extends /*NON UI!*/Job { private final IProgressMonitor opMonitor; private final HgRoot hgRoot; private final ChangeSet changeSet; private String branch; /** * @param name Human readable name * @param hgRoot The hg root * @param changeSet The changeset, may be null to push/pull everything * @param opMonitor The progress monitor */ private PushPullJob(String name, HgRoot hgRoot, ChangeSet changeSet, IProgressMonitor opMonitor) { super(name); this.hgRoot = hgRoot; this.changeSet = changeSet; this.opMonitor = opMonitor; } /** * @param branch The branch name, or null for all/any */ public void setBranch(String branch) { this.branch = branch; } @Override protected IStatus run(IProgressMonitor moni) { IHgRepositoryLocation location = participant.getRepositoryLocation(); if(location == null){ return Status.OK_STATUS; } // re-validate the location as it might have changed credentials... try { location = MercurialEclipsePlugin.getRepoManager().getRepoLocation(location.getLocation()); } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); return Status.OK_STATUS; } if(opMonitor.isCanceled() || moni.isCanceled()){ return Status.CANCEL_STATUS; } try { if (isPull) { boolean rebase = false; boolean force = false; boolean timeout = true; HgPushPullClient.pull(hgRoot, changeSet, location, update, rebase, force, timeout, false, branch); // pull client does the refresh automatically, no extra job required here } else { HgPushPullClient.push(hgRoot, location, false, changeSet, Integer.MAX_VALUE, branch); new RefreshRootJob(hgRoot, RefreshRootJob.OUTGOING).schedule(); } } catch (final HgException ex) { MercurialEclipsePlugin.logError(ex); if(!isPull){ // try to recover: open the default dialog, where user can change some // settings like password/force flag etc (issue #10720) MercurialEclipsePlugin.getStandardDisplay().asyncExec(new Runnable() { public void run() { try { PushHandler handler = new PushHandler(); handler.setInitialMessage(Messages .getString("PushPullSynchronizeOperation.PushFailed") + ex.getConciseMessage()); handler.run(hgRoot); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } } }); } return Status.CANCEL_STATUS; } finally { opMonitor.done(); } return Status.OK_STATUS; } } } ResolveSynchronizeAction.java000066400000000000000000000036201173713500500402010ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; /** * Handles resolve from the synchronize view */ public class ResolveSynchronizeAction extends AbstractResourceSynchronizeAction { public ResolveSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); } @Override protected SynchronizeModelOperation createOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources, List changesets) { return new ResolveSynchronizeOperation(configuration, elements, resources); } @Override protected boolean isResourceSupported(IResource resource) { return super.isResourceSupported(resource) && resource instanceof IFile && MercurialStatusCache.getInstance().isConflict(resource); } } ResolveSynchronizeOperation.java000066400000000000000000000046621173713500500407330ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.team.core.TeamException; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.operations.ResolveOperation; /** * @see ResolveSynchronizeAction */ public class ResolveSynchronizeOperation extends SynchronizeModelOperation { private final IResource[] resources; public ResolveSynchronizeOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources) { super(configuration, elements); this.resources = resources; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Resolving...", 1); new SafeUiJob("Resolving selected resources...") { @Override protected IStatus runSafe(IProgressMonitor moni) { try { new ResolveOperation(MercurialEclipsePlugin.getActivePage().getActivePart(), resources, false).run(moni); } catch (InvocationTargetException e1) { return getStatus(e1.getTargetException()); } catch (InterruptedException e1) { return getStatus(e1); } return Status.OK_STATUS; } }.schedule(); monitor.done(); } protected IStatus getStatus(Throwable t) { if (t instanceof TeamException) { return ((TeamException) t).getStatus(); } return new HgException("Error resolving files", t).getStatus(); } } RevertSynchronizeAction.java000066400000000000000000000034401173713500500400310ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; /** * @author Andrei */ public class RevertSynchronizeAction extends AbstractResourceSynchronizeAction { public RevertSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); } @Override protected ImageDescriptor createImageDescriptor() { return MercurialEclipsePlugin.getImageDescriptor("actions/revert.gif"); } @Override protected SynchronizeModelOperation createOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources, List changesets) { return new RevertSynchronizeOperation(configuration, elements, resources, changesets); } } RevertSynchronizeOperation.java000066400000000000000000000065161173713500500405630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.dialogs.CommitDialog.Options; import com.vectrace.MercurialEclipse.menu.CommitHandler; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.team.ActionRevert; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * @author Andrei * */ public class RevertSynchronizeOperation extends SynchronizeModelOperation { private IResource[] resources; private final List changesets; public RevertSynchronizeOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements, IResource[] resources, List changesets) { super(configuration, elements); this.resources = resources; this.changesets = changesets; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { new SafeUiJob("Reverting selected resources...") { @Override protected IStatus runSafe(IProgressMonitor moni) { if (resources.length == 0 && !CommitSynchronizeOperation.hasFiles(changesets)) { MessageDialog.openInformation(getShell(), "Mercurial Revert", //$NON-NLS-1$ "Please select at least one file to revert!"); //$NON-NLS-1$ return Status.OK_STATUS; } if(resources.length != 0) { revert(moni); return Status.OK_STATUS; } for (WorkingChangeSet cs : changesets) { if(cs.getFiles().isEmpty()) { continue; } CommitHandler commithandler = new CommitHandler(); Options options = new Options(); if(!StringUtils.isEmpty(cs.getComment())) { options.defaultCommitMessage = cs.getComment(); } else { options.defaultCommitMessage = cs.getName(); } commithandler.setOptions(options); List files = new ArrayList(); files.addAll(cs.getFiles()); resources = files.toArray(new IResource[0]); revert(moni); } return Status.OK_STATUS; } }.schedule(); monitor.done(); } protected void revert(IProgressMonitor moni) { final ActionRevert revert = new ActionRevert(); revert.selectionChanged(null, new StructuredSelection(resources)); revert.run(null); } } RollbackSynchronizeAction.java000066400000000000000000000056161173713500500403220ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov (Intland) implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgRollbackClient; import com.vectrace.MercurialEclipse.menu.Messages; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author Ilya Ivanov (Intland) */ public class RollbackSynchronizeAction extends SynchronizeModelAction { private final HgRoot hgRoot; // private final ChangeSet changeSet; protected RollbackSynchronizeAction(String text, ISynchronizePageConfiguration configuration, HgRoot hgRoot, ChangeSet changeSet) { super(text, configuration); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/revert.gif")); this.hgRoot = hgRoot; // this.changeSet = changeSet; } private class RollbackSynchronizeOperation extends SynchronizeModelOperation { protected RollbackSynchronizeOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements) { super(configuration, elements); } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { final String result = HgRollbackClient.rollback(hgRoot); getShell().getDisplay().asyncExec(new Runnable() { public void run() { MessageDialog.openInformation(getShell(), Messages.getString("RollbackHandler.output"), result); //$NON-NLS-1$ } }); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } @Override protected SynchronizeModelOperation getSubscriberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements) { return new RollbackSynchronizeOperation(configuration, elements); } @Override protected boolean updateSelection(IStructuredSelection selection) { return true; // should be always available } } SetDefaultChangesetSynchronizeAction.java000066400000000000000000000100201173713500500424340ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2004, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - Adaption to Mercurial * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.viewers.ContentViewer; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import org.eclipse.ui.navigator.CommonViewer; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider; import com.vectrace.MercurialEclipse.synchronize.cs.UncommittedChangesetGroup; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted; /** * Get action that appears in the synchronize view. It's main purpose is to * filter the selection and delegate its execution to the get operation. */ public class SetDefaultChangesetSynchronizeAction extends SynchronizeModelAction { public static final String ID = "hg.setDefaultChangeset"; public SetDefaultChangesetSynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); setId(ID); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("elcl16/uncommitted_cs.gif", "ovr/pinned_ovr.gif", IDecoration.TOP_RIGHT)); } @Override protected SynchronizeModelOperation getSubscriberOperation( final ISynchronizePageConfiguration configuration, IDiffElement[] elements) { IStructuredSelection sel = getStructuredSelection(); // it's guaranteed that we have exact one element final Object object = sel.getFirstElement(); if(object instanceof WorkingChangeSet){ return new SynchronizeModelOperation(configuration, elements) { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { Viewer viewer = configuration.getPage().getViewer(); if(!(viewer instanceof ContentViewer)){ return; } CommonViewer commonViewer = (CommonViewer) viewer; final HgChangeSetContentProvider csProvider = OpenAction.getProvider(commonViewer.getNavigatorContentService()); IUncommitted uc = csProvider.getUncommittedEntry(); if (uc instanceof UncommittedChangesetGroup) { ((UncommittedChangesetGroup)uc).makeDefault((GroupedUncommittedChangeSet) object); } else { MercurialEclipsePlugin.logError( "Unexped invocation of SetDefaultChangesetSynchronizeAction", new IllegalStateException()); } } }; } return null; } @Override protected boolean updateSelection(IStructuredSelection selection) { boolean updateSelection = super.updateSelection(selection); if(!updateSelection){ Object[] array = selection.toArray(); if(selection.size() != 1){ return false; } return isSupported(array[0]); } return updateSelection; } private boolean isSupported(Object object) { return object instanceof WorkingChangeSet; } } ShowHistorySynchronizeAction.java000066400000000000000000000100541173713500500410630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2004, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - Adaption to Mercurial * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeParticipant; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * Get action that appears in the synchronize view. It's main purpose is to * filter the selection and delegate its execution to the get operation. */ public class ShowHistorySynchronizeAction extends SynchronizeModelAction { public static final String ID = "hg.history"; public ShowHistorySynchronizeAction(String text, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(text, configuration, selectionProvider); setId(ID); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("history.gif")); } @Override protected SynchronizeModelOperation getSubscriberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements) { IStructuredSelection sel = getStructuredSelection(); // it's guaranteed that we have exact one element Object object = sel.getFirstElement(); if(object instanceof ChangeSet){ ChangeSet changeSet = (ChangeSet) object; if(changeSet.getHgRoot() != null) { object = changeSet.getHgRoot(); } else if (object instanceof WorkingChangeSet) { IProject[] projects = ((MercurialSynchronizeParticipant)configuration.getParticipant()).getContext().getScope().getProjects(); Map> byRoot = ResourceUtils.groupByRoot(Arrays.asList(projects)); Set roots = byRoot.keySet(); if (roots.size() == 1) { object = roots.iterator().next(); } } else { IResource resource = ResourceUtils.getResource(object); if(resource != null){ object = MercurialTeamProvider.getHgRoot(resource); } } } else { object = ResourceUtils.getResource(object); } return new ShowHistorySynchronizeOperation(configuration, elements, object); } @Override protected boolean updateSelection(IStructuredSelection selection) { boolean updateSelection = super.updateSelection(selection); if(!updateSelection){ Object[] array = selection.toArray(); if(selection.size() != 1){ return false; } return isSupported(array[0]); } return updateSelection; } private boolean isSupported(Object object) { IResource resource = ResourceUtils.getResource(object); if(resource != null){ return true; } return object instanceof ChangeSet && isMatching(((ChangeSet) object) .getDirection()); } private boolean isMatching(Direction d){ return d == Direction.OUTGOING; } } ShowHistorySynchronizeOperation.java000066400000000000000000000042061173713500500416100ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2008 MercurialEclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Subclipse - original impl.o * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.ui.TeamUI; import org.eclipse.team.ui.history.IHistoryView; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import org.eclipse.ui.PartInitException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; public class ShowHistorySynchronizeOperation extends SynchronizeModelOperation { private final Object input; public ShowHistorySynchronizeOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements, Object input) { super(configuration, elements); this.input = input; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Opening History View...", 1); getShell().getDisplay().asyncExec(new Runnable() { public void run() { if (input instanceof HgRoot) { TeamUI.getHistoryView().showHistoryFor(input); } else { try { IHistoryView view = (IHistoryView) getPart().getSite().getPage() .showView(IHistoryView.VIEW_ID); if (view != null) { view.showHistoryFor(input); } } catch (PartInitException e) { MercurialEclipsePlugin.logError(e); } } } }); monitor.done(); } } StripSynchronizeAction.java000066400000000000000000000045411173713500500376660ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Ilya Ivanov (Intland) implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelAction; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.menu.StripHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author Ilya Ivanov (Intland) */ public class StripSynchronizeAction extends SynchronizeModelAction { private final HgRoot hgRoot; private final ChangeSet changeSet; protected StripSynchronizeAction(String text, ISynchronizePageConfiguration configuration, HgRoot hgRoot, ChangeSet changeSet) { super(text, configuration); setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/revert.gif")); this.hgRoot = hgRoot; this.changeSet = changeSet; } private class StripSynchronizeModelOperation extends SynchronizeModelOperation { protected StripSynchronizeModelOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements) { super(configuration, elements); } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { getShell().getDisplay().asyncExec(new Runnable() { public void run() { StripHandler.openWizard(hgRoot, getShell(), changeSet); } }); } } @Override protected SynchronizeModelOperation getSubscriberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements) { return new StripSynchronizeModelOperation(configuration, elements); } } SwitchToSynchronizeAction.java000066400000000000000000000071271173713500500403340ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/actions/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.actions; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.structuremergeviewer.IDiffElement; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizeModelOperation; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.UpdateHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; public class SwitchToSynchronizeAction extends ExportPatchSynchronizeAction { private boolean isParent; private final String parentText; private final String normalText; public SwitchToSynchronizeAction(String normalText, String parentText, ISynchronizePageConfiguration configuration, ISelectionProvider selectionProvider) { super(normalText, configuration, selectionProvider); this.normalText = normalText; this.parentText = parentText; setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/switch.gif")); } // operations /** * @see com.vectrace.MercurialEclipse.synchronize.actions.ExportPatchSynchronizeAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) */ @Override protected boolean updateSelection(IStructuredSelection selection) { ChangeSet cs = getChangeSet(selection); isParent = cs != null && cs.isCurrentOutgoing(); setText(isParent ? parentText : normalText); return super.updateSelection(selection); } /** * @see com.vectrace.MercurialEclipse.synchronize.actions.ExportPatchSynchronizeAction#getSubsciberOperation(org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration, * org.eclipse.compare.structuremergeviewer.IDiffElement[], * com.vectrace.MercurialEclipse.model.ChangeSet) */ @Override protected SynchronizeModelOperation getSubsciberOperation( ISynchronizePageConfiguration configuration, IDiffElement[] elements, final ChangeSet cs) { final boolean isParentMode = this.isParent; return new SynchronizeModelOperation(configuration, elements) { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { if (cs != null && cs.getHgRoot() != null) { UpdateHandler update = new UpdateHandler(false); HgRevision rev; update.setCleanEnabled(true); if (isParentMode) { rev = cs.getParentRevision(0, true); if (rev == null && cs.getRevision().getRevision() == 0) { return; } } else { rev = cs.getRevision(); } if (rev == null) { MercurialEclipsePlugin.logError(new IllegalStateException("Missing revision")); return; } update.setRevision(rev); update.setShell(getShell()); try { update.run(cs.getHgRoot()); } catch (HgException e) { throw new InvocationTargetException(e); } } } }; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/000077500000000000000000000000001173713500500313505ustar00rootroot00000000000000ChangesetGroup.java000066400000000000000000000035001173713500500350500ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; /** * @author Andrei */ public class ChangesetGroup { private final Direction direction; private final String name; private final Set changesets; public ChangesetGroup(String name, Direction direction) { this.name = name; this.direction = direction; // CopyOnWriteArraySet to prevent ConcurrentModificationException. this.changesets = new CopyOnWriteArraySet(); } public Direction getDirection() { return direction; } public String getName() { return name; } public Set getChangesets() { return changesets; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ChangesetGroup ["); if (direction != null) { builder.append("direction="); builder.append(direction); builder.append(", "); } if (name != null) { builder.append("name="); builder.append(name); builder.append(", "); } if (changesets != null) { builder.append("changesets="); builder.append(changesets); } builder.append("]"); return builder.toString(); } } HgChangeSetActionProvider.java000066400000000000000000000170771173713500500371410ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.team.internal.ui.TeamUIMessages; import org.eclipse.team.internal.ui.synchronize.actions.OpenFileInSystemEditorAction; import org.eclipse.team.ui.mapping.SynchronizationActionProvider; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.ISynchronizePageSite; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchSite; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.actions.OpenWithMenu; import org.eclipse.ui.navigator.ICommonViewerSite; import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite; import org.eclipse.ui.plugin.AbstractUIPlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.properties.OpenPropertiesAction; import com.vectrace.MercurialEclipse.synchronize.actions.DeleteAction; import com.vectrace.MercurialEclipse.synchronize.actions.MercurialSynchronizePageActionGroup; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * This class adds some actions supporting different objects in the sync view * @author Andrei */ @SuppressWarnings("restriction") public class HgChangeSetActionProvider extends SynchronizationActionProvider { private OpenFileInSystemEditorAction openFileAction; private ISynchronizePageConfiguration configuration; private DeleteAction deleteAction; private Action propertiesAction; public HgChangeSetActionProvider() { super(); } @Override protected void initializeOpenActions() { super.initializeOpenActions(); ICommonViewerSite cvs = getActionSite().getViewSite(); configuration = getSynchronizePageConfiguration(); if (cvs instanceof ICommonViewerWorkbenchSite && configuration != null) { ICommonViewerWorkbenchSite cvws = (ICommonViewerWorkbenchSite) cvs; final IWorkbenchPartSite wps = cvws.getSite(); if (wps instanceof IViewSite) { openFileAction = new OpenFileInSystemEditorAction(wps.getPage()); deleteAction = new DeleteAction("Delete", configuration, wps.getSelectionProvider()); deleteAction.setActionDefinitionId(MercurialSynchronizePageActionGroup.EDIT_DELETE); deleteAction.setId(MercurialSynchronizePageActionGroup.EDIT_DELETE); propertiesAction = new Action("Properties", AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.ui", "/icons/full/eview16/prop_ps.gif")) { { setId(OpenPropertiesAction.class.getName()); } @Override public void run() { new OpenPropertiesAction().run(this); } }; } } } @Override public void fillContextMenu(IMenuManager menu) { super.fillContextMenu(menu); if(menu.find(DeleteAction.HG_DELETE_GROUP) == null){ menu.insertBefore(ISynchronizePageConfiguration.NAVIGATE_GROUP, new Separator( DeleteAction.HG_DELETE_GROUP)); } ISelection selection = getSite().getSelectionProvider().getSelection(); if (selection instanceof IStructuredSelection && !hasFileMenu(menu)) { fillOpenWithMenu(menu, ISynchronizePageConfiguration.FILE_GROUP, (IStructuredSelection) selection); } if (selection instanceof IStructuredSelection && !hasDeleteMenu(menu)) { fillDeleteMenu(menu, DeleteAction.HG_DELETE_GROUP, (IStructuredSelection) selection); } if (selection instanceof IStructuredSelection && !hasPropertiesMenu(menu)) { fillPropertiesMenu(menu, ISynchronizePageConfiguration.OBJECT_CONTRIBUTIONS_GROUP, (IStructuredSelection) selection); } } private void fillDeleteMenu(IMenuManager menu, String groupId, IStructuredSelection selection) { // Only supported if at least one file is selected. if (selection == null || selection.size() != 1) { return; } Object element = selection.getFirstElement(); if(element instanceof ChangeSet && !(element instanceof WorkingChangeSet)){ return; } Object selected; if(element instanceof GroupedUncommittedChangeSet && !((GroupedUncommittedChangeSet)element).isDefault()) { selected = element; } else { IResource resource = ResourceUtils.getResource(element); if ((!(resource instanceof IFile) && !(resource instanceof IFolder)) || !resource.exists()) { return; } selected = resource; } if (deleteAction != null) { deleteAction.selectionChanged(new StructuredSelection(selected)); menu.appendToGroup(groupId, deleteAction); } } private void fillPropertiesMenu(IMenuManager menu, String groupId, IStructuredSelection selection) { // Only supported if at least one changeset is selected. if (selection == null || selection.size() != 1) { return; } Object element = selection.getFirstElement(); if(!(element instanceof ChangeSet) || element instanceof WorkingChangeSet) { return; } if (propertiesAction != null) { menu.appendToGroup(groupId, propertiesAction); } } /** * Adds the OpenWith submenu to the context menu. * * @param menu the context menu * @param selection the current selection */ private void fillOpenWithMenu(IMenuManager menu, String groupId, IStructuredSelection selection) { // Only supported if at least one file is selected. if (selection == null || selection.size() != 1) { return; } Object element = selection.getFirstElement(); if(element instanceof ChangeSet){ return; } IResource resource = ResourceUtils.getResource(element); if (!(resource instanceof IFile) || !resource.exists()) { return; } if (openFileAction != null) { openFileAction.selectionChanged(new StructuredSelection(resource)); menu.appendToGroup(groupId, openFileAction); } IWorkbenchSite ws = getSite().getWorkbenchSite(); if (ws != null) { MenuManager submenu = new MenuManager(TeamUIMessages.OpenWithActionGroup_0); submenu.add(new OpenWithMenu(ws.getPage(), resource)); menu.appendToGroup(groupId, submenu); } } private ISynchronizePageSite getSite() { return configuration.getSite(); } private boolean hasFileMenu(IMenuManager menu) { return openFileAction != null && menu.find(openFileAction.getId()) != null; } private boolean hasDeleteMenu(IMenuManager menu) { return deleteAction != null && menu.find(deleteAction.getId()) != null; } private boolean hasPropertiesMenu(IMenuManager menu) { return propertiesAction != null && menu.find(propertiesAction.getId()) != null; } @Override public void fillActionBars(IActionBars actionBars) { super.fillActionBars(actionBars); actionBars.setGlobalActionHandler(ActionFactory.DELETE.getId(), deleteAction); } } HgChangeSetAdapterFactory.java000066400000000000000000000027551173713500500371160ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.IAdapterFactory; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; public class HgChangeSetAdapterFactory implements IAdapterFactory { @SuppressWarnings("unchecked") public Object getAdapter(Object adaptableObject, Class adapterType) { if (adaptableObject instanceof ChangeSet && adapterType == ResourceMapping.class) { ChangeSet cs = (ChangeSet) adaptableObject; return new HgChangeSetResourceMapping(cs); } if (adaptableObject instanceof FileFromChangeSet && adapterType == ResourceMapping.class) { FileFromChangeSet cs = (FileFromChangeSet) adaptableObject; return new HgChangeSetResourceMapping(cs); } return null; } @SuppressWarnings("unchecked") public Class[] getAdapterList() { return new Class[] { ResourceMapping.class }; } } HgChangeSetCapability.java000066400000000000000000000035501173713500500362610ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import org.eclipse.team.core.diff.IDiff; import org.eclipse.team.internal.core.subscribers.ActiveChangeSet; import org.eclipse.team.internal.core.subscribers.ActiveChangeSetManager; import org.eclipse.team.internal.ui.synchronize.ChangeSetCapability; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SynchronizePageActionGroup; /** * @author Andrei */ @SuppressWarnings("restriction") public class HgChangeSetCapability extends ChangeSetCapability { public HgChangeSetCapability() { super(); } @Override public HgChangesetsCollector createSyncInfoSetChangeSetCollector( ISynchronizePageConfiguration configuration) { return new HgChangesetsCollector(configuration); } @Override public ActiveChangeSetManager getActiveChangeSetManager() { return null; } @Override public ActiveChangeSet createChangeSet(ISynchronizePageConfiguration configuration, IDiff[] diffs) { return null; } @Override public boolean supportsActiveChangeSets() { return false; } @Override public SynchronizePageActionGroup getActionGroup() { return super.getActionGroup(); } @Override public boolean enableChangeSetsByDefault() { return true; } @Override public boolean supportsCheckedInChangeSets() { return true; } } HgChangeSetContentProvider.java000066400000000000000000000613601173713500500373300ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Andrei Loskutov - adopting to hg *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Observer; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.mapping.ResourceTraversal; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.team.core.diff.IDiffChangeEvent; import org.eclipse.team.core.mapping.ISynchronizationContext; import org.eclipse.team.internal.core.subscribers.BatchingChangeSetManager; import org.eclipse.team.internal.core.subscribers.IChangeSetChangeListener; import org.eclipse.team.internal.core.subscribers.BatchingChangeSetManager.CollectorChangeEvent; import org.eclipse.team.internal.ui.Utils; import org.eclipse.team.internal.ui.synchronize.ChangeSetCapability; import org.eclipse.team.internal.ui.synchronize.IChangeSetProvider; import org.eclipse.team.ui.mapping.SynchronizationContentProvider; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.ISynchronizeParticipant; import org.eclipse.ui.model.WorkbenchContentProvider; import org.eclipse.ui.navigator.ICommonContentExtensionSite; import org.eclipse.ui.navigator.INavigatorContentExtension; import org.eclipse.ui.navigator.INavigatorContentService; import org.eclipse.ui.navigator.INavigatorSorterService; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.PathFromChangeSet; import com.vectrace.MercurialEclipse.model.UncommittedChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.synchronize.HgDragAdapterAssistant; import com.vectrace.MercurialEclipse.synchronize.HgSubscriberMergeContext; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeParticipant; import com.vectrace.MercurialEclipse.synchronize.PresentationMode; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; @SuppressWarnings("restriction") public class HgChangeSetContentProvider extends SynchronizationContentProvider /* ResourceModelContentProvider */ { public static final String ID = "com.vectrace.MercurialEclipse.changeSetContent"; private static final MercurialStatusCache STATUS_CACHE = MercurialStatusCache.getInstance(); private final class UcommittedSetListener implements IPropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { Object input = getTreeViewer().getInput(); if (input instanceof HgChangeSetModelProvider) { Utils.asyncExec(new Runnable() { public void run() { TreeViewer treeViewer = getTreeViewer(); treeViewer.getTree().setRedraw(false); treeViewer.refresh(uncommitted, true); if (uncommitted instanceof ChangesetGroup) { for (ChangeSet cs : ((ChangesetGroup) uncommitted).getChangesets()) { treeViewer.refresh(cs, true); } } treeViewer.getTree().setRedraw(true); } }, getTreeViewer()); } } } private final class PreferenceListener implements IPropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { Object input = getTreeViewer().getInput(); String property = event.getProperty(); final boolean bLocal = property .equals(MercurialPreferenceConstants.PREF_SYNC_ENABLE_LOCAL_CHANGESETS); if ((property.equals(PresentationMode.PREFERENCE_KEY) || bLocal) && input instanceof HgChangeSetModelProvider) { Utils.asyncExec(new Runnable() { public void run() { TreeViewer treeViewer = getTreeViewer(); if (bLocal) { recreateUncommittedEntry(treeViewer); } else { treeViewer.getTree().setRedraw(false); treeViewer.refresh(uncommitted, true); treeViewer.refresh(outgoing, true); treeViewer.refresh(incoming, true); treeViewer.getTree().setRedraw(true); } } }, getTreeViewer()); } } } private final class CollectorListener implements IChangeSetChangeListener, BatchingChangeSetManager.IChangeSetCollectorChangeListener { public void setAdded(final org.eclipse.team.internal.core.subscribers.ChangeSet cs) { ChangeSet set = (ChangeSet)cs; if (isVisibleInMode(set)) { final ChangesetGroup toRefresh = set.getDirection() == Direction.INCOMING ? incoming : outgoing; boolean added = toRefresh.getChangesets().add(set); if(added) { Utils.asyncExec(new Runnable() { public void run() { getTreeViewer().refresh(toRefresh, true); } }, getTreeViewer()); } } } public void setRemoved(final org.eclipse.team.internal.core.subscribers.ChangeSet cs) { ChangeSet set = (ChangeSet)cs; if (isVisibleInMode(set)) { final ChangesetGroup toRefresh = set.getDirection() == Direction.INCOMING ? incoming : outgoing; boolean removed = toRefresh.getChangesets().remove(set); if(removed) { Utils.asyncExec(new Runnable() { public void run() { getTreeViewer().refresh(toRefresh, true); } }, getTreeViewer()); } } } public void defaultSetChanged(final org.eclipse.team.internal.core.subscribers.ChangeSet previousDefault, final org.eclipse.team.internal.core.subscribers.ChangeSet set) { // user has requested a manual refresh: simply refresh root elements getRootElements(); } public void nameChanged(final org.eclipse.team.internal.core.subscribers.ChangeSet set) { // ignored } public void resourcesChanged(final org.eclipse.team.internal.core.subscribers.ChangeSet set, final IPath[] paths) { // ignored } public void changeSetChanges(final CollectorChangeEvent event, IProgressMonitor monitor) { // ignored } } private HgChangesetsCollector csCollector; private boolean collectorInitialized; private final IChangeSetChangeListener collectorListener; private final IPropertyChangeListener uncommittedSetListener; private final IPropertyChangeListener preferenceListener; private final ChangesetGroup incoming; private final ChangesetGroup outgoing; private WorkbenchContentProvider provider; private IUncommitted uncommitted; public HgChangeSetContentProvider() { super(); incoming = new ChangesetGroup("Incoming", Direction.INCOMING); outgoing = new ChangesetGroup("Outgoing", Direction.OUTGOING); collectorListener = new CollectorListener(); uncommittedSetListener = new UcommittedSetListener(); preferenceListener = new PreferenceListener(); MercurialEclipsePlugin.getDefault().getPreferenceStore().addPropertyChangeListener(preferenceListener); uncommitted = makeUncommittedEntry(); } private IUncommitted makeUncommittedEntry() { if (MercurialEclipsePlugin.getDefault().getPreferenceStore().getBoolean( MercurialPreferenceConstants.PREF_SYNC_ENABLE_LOCAL_CHANGESETS)) { return new UncommittedChangesetGroup(); } return new UncommittedChangeSet(); } @Override protected String getModelProviderId() { return HgChangeSetModelProvider.ID; } private boolean isOutgoingVisible(){ return getConfiguration().getMode() != ISynchronizePageConfiguration.INCOMING_MODE; } private boolean isIncomingVisible(){ return getConfiguration().getMode() != ISynchronizePageConfiguration.OUTGOING_MODE; } private boolean isEnabled() { final Object input = getViewer().getInput(); return input instanceof HgChangeSetModelProvider; } @Override public Object[] getChildren(Object parent) { return getElements(parent); } @Override public Object[] getElements(Object parent) { if (parent instanceof ISynchronizationContext) { // Do not show change sets when all models are visible because // model providers that override the resource content may cause // problems for the change set content provider return new Object[0]; } if(isEnabled()){ if(!((HgChangeSetModelProvider) getViewer().getInput()).isParticipantCreated()){ initCollector(); // on startup, do not start to show anything for the first time: // show "reminder" page which allows user to choose synchronize or not // return new Object[0]; // TODO right now it doesn't make sense to show "reminder page" as we // connect to the remote servers automatically as soon as the sync view // shows up. } } if (parent == getModelProvider()) { return getRootElements(); } else if (parent instanceof ChangesetGroup) { ChangesetGroup group = (ChangesetGroup) parent; Direction direction = group.getDirection(); if (isOutgoing(direction)) { if (isOutgoingVisible()) { return group.getChangesets().toArray(); } return new Object[] {new FilteredPlaceholder()}; } if(direction == Direction.INCOMING){ if (isIncomingVisible()) { return group.getChangesets().toArray(); } return new Object[] {new FilteredPlaceholder()}; } if(direction == Direction.LOCAL){ return group.getChangesets().toArray(); } } else if (parent instanceof ChangeSet) { FileFromChangeSet[] files = ((ChangeSet) parent).getChangesetFiles(); if (files.length != 0) { switch (PresentationMode.get()) { case FLAT: return files; case TREE: return collectTree(parent, files); case COMPRESSED_TREE: return collectCompressedTree(parent, files); } } } else if (parent instanceof PathFromChangeSet) { return ((PathFromChangeSet) parent).getChildren(); } return new Object[0]; } private Object[] collectTree(Object parent, FileFromChangeSet[] files) { List out = new ArrayList(files.length * 2); for (FileFromChangeSet file : files) { IPath path = file.getPath(); if(path == null) { out.add(Path.EMPTY); } else { out.add(path.removeLastSegments(1)); } out.add(file); } return collectTree(parent, out); } private Object[] collectTree(Object parent, List files) { HashMap> map = new HashMap>(); List out = new ArrayList(); for (Iterator it = files.iterator(); it.hasNext();) { IPath path = (IPath) it.next(); FileFromChangeSet file = (FileFromChangeSet) it.next(); if (path == null || 0 == path.segmentCount()) { out.add(file); } else { String seg = path.segment(0); List l = map.get(seg); if (l == null) { map.put(seg, l = new ArrayList()); } l.add(path.removeFirstSegments(1)); l.add(file); } } for (String seg : map.keySet()) { out.add(new TreePathFromChangeSet(parent, seg, map.get(seg))); } return out.toArray(new Object[out.size()]); } private Object[] collectCompressedTree(Object parent, FileFromChangeSet[] files) { HashMap> map = new HashMap>(); List out = new ArrayList(); for (FileFromChangeSet file : files) { IPath path; if(file.getPath() == null) { path = Path.EMPTY; } else { path = file.getPath().removeLastSegments(1); } List l = map.get(path); if (l == null) { map.put(path, l = new ArrayList()); } l.add(file); } for (IPath path : map.keySet()) { final List data = map.get(path); if (path.isEmpty()) { out.addAll(data); } else { out.add(new CompressedTreePathFromChangeSet(parent, path.toString(), data)); } } return out.toArray(new Object[out.size()]); } private void ensureRootsAdded() { TreeViewer viewer = getTreeViewer(); TreeItem[] children = viewer.getTree().getItems(); if(children.length == 0) { viewer.add(viewer.getInput(), getRootElements()); } } private Object[] getRootElements() { initCollector(); List result = new ArrayList(); Collection allSets = getAllSets(); for (ChangeSet set : allSets) { if (hasChildren(set)) { result.add(set); } } boolean showOutgoing = isOutgoingVisible(); boolean showIncoming = isIncomingVisible(); for (ChangeSet set : result) { Direction direction = set.getDirection(); if(showOutgoing && (isOutgoing(direction))){ outgoing.getChangesets().add(set); } if(showIncoming && direction == Direction.INCOMING){ incoming.getChangesets().add(set); } } uncommitted.update(STATUS_CACHE, null); return new Object[]{uncommitted, outgoing, incoming}; } private synchronized void initCollector() { if (!collectorInitialized) { initializeChangeSets(getChangeSetCapability()); collectorInitialized = true; } } @Override protected ResourceTraversal[] getTraversals( ISynchronizationContext context, Object object) { if (object instanceof ChangeSet) { ChangeSet set = (ChangeSet) object; IResource[] resources = set.getResources(); return new ResourceTraversal[] { new ResourceTraversal(resources, IResource.DEPTH_ZERO, IResource.NONE) }; } if(object instanceof IResource){ IResource[] resources = new IResource[]{(IResource) object}; return new ResourceTraversal[] { new ResourceTraversal(resources, IResource.DEPTH_ZERO, IResource.NONE) }; } if(object instanceof ChangesetGroup){ ChangesetGroup group = (ChangesetGroup) object; Set changesets = group.getChangesets(); Set all = new HashSet(); for (ChangeSet changeSet : changesets) { all.addAll(changeSet.getFiles()); } IResource[] resources = all.toArray(new IResource[0]); return new ResourceTraversal[] { new ResourceTraversal(resources, IResource.DEPTH_ZERO, IResource.NONE) }; } return new ResourceTraversal[0]; } /** * @see org.eclipse.team.ui.mapping.SynchronizationContentProvider#hasChildrenInContext(org.eclipse.team.core.mapping.ISynchronizationContext, * java.lang.Object) */ @Override protected boolean hasChildrenInContext(ISynchronizationContext context, Object element) { if (element instanceof ChangeSet) { return hasChildren((ChangeSet) element); } else if (element instanceof ChangesetGroup) { ChangesetGroup group = (ChangesetGroup) element; Direction direction = group.getDirection(); if (isOutgoingVisible() && isOutgoing(direction)) { return true; } if(isIncomingVisible() && direction == Direction.INCOMING){ return true; } } else if (element instanceof PathFromChangeSet) { return true; } return false; } private boolean isVisibleInMode(ChangeSet cs) { int mode = getConfiguration().getMode(); if (cs != null) { switch (mode) { case ISynchronizePageConfiguration.BOTH_MODE: return true; case ISynchronizePageConfiguration.CONFLICTING_MODE: return containsConflicts(cs); case ISynchronizePageConfiguration.INCOMING_MODE: return cs.getDirection() == Direction.INCOMING; case ISynchronizePageConfiguration.OUTGOING_MODE: return hasConflicts(cs) || isOutgoing(cs.getDirection()); default: break; } } return true; } private static boolean isOutgoing(Direction direction) { return direction == Direction.OUTGOING || direction == Direction.LOCAL; } private static boolean hasConflicts(ChangeSet cs) { // Conflict mode not meaningful in a DVCS return false; } private static boolean containsConflicts(ChangeSet cs) { // Conflict mode not meaningful in a DVCS return false; } private boolean hasChildren(ChangeSet changeset) { return isVisibleInMode(changeset) && (!changeset.getFiles().isEmpty() || changeset.getChangesetFiles().length > 0); } /** * Return all the change sets (incoming and outgoing). This * list must not include the unassigned set. * @return all the change sets (incoming and outgoing) */ private Collection getAllSets() { if (csCollector != null) { return csCollector.getChangeSets(); } return new HashSet(); } @Override public void init(ICommonContentExtensionSite site) { super.init(site); HgChangeSetSorter sorter = getSorter(); if (sorter != null) { sorter.setConfiguration(getConfiguration()); } MercurialSynchronizeParticipant participant = (MercurialSynchronizeParticipant) getConfiguration().getParticipant(); getExtensionSite().getService().getDnDService().bindDragAssistant(new HgDragAdapterAssistant()); uncommitted.setContext((HgSubscriberMergeContext) participant.getContext()); } private HgChangeSetSorter getSorter() { INavigatorContentService contentService = getExtensionSite().getService(); INavigatorSorterService sortingService = contentService.getSorterService(); INavigatorContentExtension extension = getExtensionSite().getExtension(); if (extension != null) { ViewerSorter sorter = sortingService.findSorter(extension.getDescriptor(), getModelProvider(), incoming, incoming); if (sorter instanceof HgChangeSetSorter) { return (HgChangeSetSorter) sorter; } } return null; } private void initializeChangeSets(ChangeSetCapability csc) { if (csc.supportsCheckedInChangeSets()) { csCollector = ((HgChangeSetCapability) csc).createSyncInfoSetChangeSetCollector(getConfiguration()); csCollector.addListener(collectorListener); initializeUncommittedEntry(csCollector.getSubscriber().getProjects()); } } private void initializeUncommittedEntry(IProject[] projects) { uncommitted.setProjects(projects); uncommitted.addListener(uncommittedSetListener); STATUS_CACHE.addObserver(uncommitted); } @Override public void dispose() { if (csCollector != null) { csCollector.removeListener(collectorListener); csCollector.dispose(); } MercurialEclipsePlugin.getDefault().getPreferenceStore().removePropertyChangeListener(preferenceListener); disposeUncommittedEntry(); outgoing.getChangesets().clear(); incoming.getChangesets().clear(); super.dispose(); } private void disposeUncommittedEntry() { uncommitted.removeListener(uncommittedSetListener); STATUS_CACHE.deleteObserver(uncommitted); uncommitted.dispose(); uncommitted = null; } protected void recreateUncommittedEntry(TreeViewer tree) { IProject[] projects = uncommitted.getProjects(); HgSubscriberMergeContext ctx = uncommitted.getContext(); disposeUncommittedEntry(); uncommitted = makeUncommittedEntry(); uncommitted.setContext(ctx); if (collectorInitialized) { initializeUncommittedEntry(projects); } tree.refresh(); } @Override public void diffsChanged(IDiffChangeEvent event, IProgressMonitor monitor) { Utils.asyncExec(new Runnable() { public void run() { ensureRootsAdded(); } }, getTreeViewer()); if (csCollector != null) { csCollector.handleChange(event); } // no other updates here, as it simply doesn't fit into the changeset concept. } private ChangeSetCapability getChangeSetCapability() { ISynchronizeParticipant participant = getConfiguration().getParticipant(); if (participant instanceof IChangeSetProvider) { IChangeSetProvider csProvider = (IChangeSetProvider) participant; return csProvider.getChangeSetCapability(); } return null; } private TreeViewer getTreeViewer() { return (TreeViewer) getViewer(); } @Override protected ITreeContentProvider getDelegateContentProvider() { if (provider == null) { provider = new WorkbenchContentProvider(); } return provider; } @Override protected Object getModelRoot() { return ResourcesPlugin.getWorkspace().getRoot(); } /** * * @param file may be null * @return may return null, if the given file is null, not selected or is not contained * in any selected changesets */ public ChangeSet getParentOfSelection(FileFromChangeSet file){ TreeItem[] selection = getTreeViewer().getTree().getSelection(); for (TreeItem treeItem : selection) { if(treeItem.getData() != file){ continue; } TreeItem parentItem = treeItem.getParentItem(); while (parentItem != null && !(parentItem.getData() instanceof ChangeSet)) { parentItem = parentItem.getParentItem(); } if (parentItem != null) { return (ChangeSet) parentItem.getData(); } } return null; } /** * @param changeset may be null * @return may return null */ public ChangesetGroup getParentGroup(ChangeSet changeset){ if(changeset == null || changeset instanceof WorkingChangeSet){ return null; } if(changeset.getDirection() == Direction.INCOMING){ return incoming; } return outgoing; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("HgChangeSetContentProvider [collectorInitialized="); builder.append(collectorInitialized); builder.append(", "); if (csCollector != null) { builder.append("csCollector="); builder.append(csCollector); builder.append(", "); } if (provider != null) { builder.append("provider="); builder.append(provider); builder.append(", "); } if (incoming != null) { builder.append("incoming="); builder.append(incoming); builder.append(", "); } if (outgoing != null) { builder.append("outgoing="); builder.append(outgoing); builder.append(", "); } if (uncommitted != null) { builder.append("uncommitted="); builder.append(uncommitted); } builder.append("]"); return builder.toString(); } public IUncommitted getUncommittedEntry() { return uncommitted; } private class CompressedTreePathFromChangeSet extends PathFromChangeSet { protected final List data; public CompressedTreePathFromChangeSet(Object prnt, String seg, List data) { super(prnt, seg); this.data = data; if (data != null && data.size() > 0) { IFile file = data.get(0).getFile(); this.resource = file != null? file.getParent() : null; } } @Override public Object[] getChildren() { return data.toArray(new FileFromChangeSet[data.size()]); } @Override public Set getFiles() { return new LinkedHashSet(data); } } private class TreePathFromChangeSet extends PathFromChangeSet { protected final List data; public TreePathFromChangeSet(Object prnt, String seg, List data) { super(prnt, seg); this.data = data; this.resource = getResource(); } @Override public Object[] getChildren() { return collectTree(HgChangeSetContentProvider.this, data); } private IResource getResource() { IResource result = null; if (data.size() > 1) { // first object must be an IPath Object o1 = data.get(0); // and second must be FileFromChangeSet Object o2 = data.get(1); if (o1 instanceof IPath && o2 instanceof FileFromChangeSet) { FileFromChangeSet fcs = (FileFromChangeSet) o2; IResource childResource = ResourceUtils.getResource(fcs); if(childResource != null) { IPath folderPath = ResourceUtils.getPath(childResource).removeLastSegments( ((IPath) o1).segmentCount() + 1); return ResourcesPlugin.getWorkspace().getRoot().getContainerForLocation( folderPath); } } } return result; } @Override public Set getFiles() { Set files = new LinkedHashSet(); for (Object o : data) { if(o instanceof FileFromChangeSet) { files.add((FileFromChangeSet) o); } } return files; } } protected static class FilteredPlaceholder { /** * @see java.lang.Object#toString() */ @Override public String toString() { return ""; } } public interface IUncommitted extends Observer { void setProjects(IProject[] projects); IProject[] getProjects(); void dispose(); void removeListener(IPropertyChangeListener listener); void addListener(IPropertyChangeListener listener); void setContext(HgSubscriberMergeContext context); HgSubscriberMergeContext getContext(); } } HgChangeSetModelProvider.java000066400000000000000000000056671173713500500367660ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import org.eclipse.core.resources.mapping.ModelProvider; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.team.core.mapping.ISynchronizationScope; import org.eclipse.team.core.mapping.ISynchronizationScopeParticipant; import org.eclipse.team.core.mapping.ISynchronizationScopeParticipantFactory; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeSubscriber; import com.vectrace.MercurialEclipse.synchronize.RepositorySynchronizationScope; /** * @author Andrei * */ public class HgChangeSetModelProvider extends ModelProvider { public static final String ID = "com.vectrace.MercurialEclipse.changeSetModel"; private boolean participantCreated; private MercurialSynchronizeSubscriber subscriber; public HgChangeSetModelProvider() { super(); } public boolean isParticipantCreated() { return participantCreated; } public MercurialSynchronizeSubscriber getSubscriber() { return subscriber; } public static class HgModelScopeParticipantFactory implements ISynchronizationScopeParticipantFactory, IAdapterFactory { public HgModelScopeParticipantFactory() { } public ISynchronizationScopeParticipant createParticipant(ModelProvider provider1, ISynchronizationScope scope) { HgChangeSetModelProvider modelProvider = (HgChangeSetModelProvider) provider1; RepositorySynchronizationScope rscope = (RepositorySynchronizationScope) scope; MercurialSynchronizeSubscriber subscriber = rscope.getSubscriber(); modelProvider.participantCreated = true; modelProvider.subscriber = subscriber; return subscriber.getParticipant(); } @SuppressWarnings("unchecked") public Object getAdapter(Object adaptableObject, Class adapterType) { if (adaptableObject instanceof ModelProvider) { ModelProvider provider1 = (ModelProvider) adaptableObject; if (provider1.getDescriptor().getId().equals(ID)) { // if (adapterType == IResourceMappingMerger.class) { // return new DefaultResourceMappingMerger((ModelProvider)adaptableObject); // } if (adapterType == ISynchronizationScopeParticipantFactory.class) { return this; } } } return null; } @SuppressWarnings("unchecked") public Class[] getAdapterList() { return new Class[] { // IResourceMappingMerger.class, // ISynchronizationCompareAdapter.class, ISynchronizationScopeParticipantFactory.class }; } } } HgChangeSetResourceMapping.java000066400000000000000000000064031173713500500373030ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Andrei Loskutov - adopting to hg *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.resources.mapping.ResourceMappingContext; import org.eclipse.core.resources.mapping.ResourceTraversal; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class HgChangeSetResourceMapping extends ResourceMapping { private final ChangeSet changeSet; private final IResource[] resources; private FileFromChangeSet file; public HgChangeSetResourceMapping(ChangeSet changeSet) { this.changeSet = changeSet; resources = changeSet.getResources(); } public HgChangeSetResourceMapping(FileFromChangeSet file) { this.file = file; changeSet = file.getChangeset(); if(file.getFile() != null) { resources = new IResource[]{file.getFile()}; } else { resources = new IResource[0]; } } @Override public Object getModelObject() { return file != null? file : changeSet; } @Override public String getModelProviderId() { return HgChangeSetModelProvider.ID; } @Override public IProject[] getProjects() { Set result = new HashSet(); Set files = changeSet.getFiles(); for (IFile changeSetFile : files) { if (changeSetFile != null && changeSetFile.getProject() != null) { result.add(changeSetFile.getProject()); } else { // it is possible that files are out of eclipse project scope // so resolve project according to hg root. final HgRoot root = changeSet.getHgRoot(); IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject project : projects) { String projectPath = ResourceUtils.getPath(project).toFile().getAbsolutePath(); String rootPath = root.getAbsolutePath(); if (projectPath.length() > 0 && projectPath.startsWith(rootPath)) { result.add(project); } } } } return result.toArray(new IProject[result.size()]); } @Override public ResourceTraversal[] getTraversals(ResourceMappingContext context, IProgressMonitor monitor) throws CoreException { if (resources.length == 0) { return new ResourceTraversal[0]; } return new ResourceTraversal[] { new ResourceTraversal(resources, IResource.DEPTH_ZERO, IResource.NONE) }; } } HgChangeSetSorter.java000066400000000000000000000072371173713500500354640ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import org.eclipse.core.resources.IResource; import org.eclipse.jface.viewers.ContentViewer; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import com.vectrace.MercurialEclipse.history.ChangeSetComparator; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; /** * @author Andrei */ public class HgChangeSetSorter extends ViewerSorter { private final ChangeSetComparator csComparator; public HgChangeSetSorter() { super(); csComparator = new ChangeSetComparator(); } @Override public int category(Object element) { if(element instanceof WorkingChangeSet){ return 0; } if(element instanceof ChangesetGroup){ return 1; } if(element instanceof ChangeSet){ return 2; } if(element instanceof IResource){ return 3; } return super.category(element); } public void setConfiguration(ISynchronizePageConfiguration configuration) { // not used yet } @Override public int compare(Viewer viewer, Object e1, Object e2) { int cat1 = category(e1); int cat2 = category(e2); if (cat1 != cat2) { return cat1 - cat2; } if(e1 instanceof ChangeSet && e2 instanceof ChangeSet){ ChangeSet cs1 = (ChangeSet) e1; ChangeSet cs2 = (ChangeSet) e2; if (cs1 instanceof GroupedUncommittedChangeSet && ((GroupedUncommittedChangeSet) cs1).isDefault()) { return -1; } if (cs2 instanceof GroupedUncommittedChangeSet && ((GroupedUncommittedChangeSet) cs2).isDefault()) { return 1; } return csComparator.compare(cs1, cs2); } if(e1 instanceof ChangesetGroup && e2 instanceof ChangesetGroup){ ChangesetGroup group1 = (ChangesetGroup) e1; ChangesetGroup group2 = (ChangesetGroup) e2; if(group1.getDirection() == group2.getDirection()){ return compareByName(viewer, e1, e2); } if(group1.getDirection() == Direction.LOCAL){ return -1; } if(group1.getDirection() == Direction.OUTGOING){ return 0; } return 1; } return compareByName(viewer, e1, e2); } @SuppressWarnings("unchecked") private int compareByName(Viewer viewer, Object e1, Object e2) { String name1; String name2; if (viewer == null || !(viewer instanceof ContentViewer)) { name1 = e1.toString(); name2 = e2.toString(); } else { IBaseLabelProvider prov = ((ContentViewer) viewer) .getLabelProvider(); if (prov instanceof ILabelProvider) { ILabelProvider lprov = (ILabelProvider) prov; name1 = lprov.getText(e1); name2 = lprov.getText(e2); } else { name1 = e1.toString(); name2 = e2.toString(); } } if (name1 == null) { name1 = ""; //$NON-NLS-1$ } if (name2 == null) { name2 = ""; //$NON-NLS-1$ } // use the comparator to compare the strings return getComparator().compare(name1, name2); } } HgChangesetsCollector.java000066400000000000000000000233031173713500500363470ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.team.core.diff.IDiffChangeEvent; import org.eclipse.team.core.mapping.ISynchronizationContext; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.internal.core.subscribers.IChangeSetChangeListener; import org.eclipse.team.internal.ui.synchronize.SyncInfoSetChangeSetCollector; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.ui.IPropertyListener; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeParticipant; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeSubscriber; import com.vectrace.MercurialEclipse.synchronize.RepositorySynchronizationScope; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.AbstractRemoteCache; import com.vectrace.MercurialEclipse.team.cache.IncomingChangesetCache; import com.vectrace.MercurialEclipse.team.cache.OutgoingChangesetCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Andrei */ @SuppressWarnings("restriction") public class HgChangesetsCollector extends SyncInfoSetChangeSetCollector { private final MercurialSynchronizeParticipant participant; private final IPropertyListener branchListener; private static final Set EMPTY_SET = Collections.unmodifiableSet(new HashSet()); private final class ChangesetsCollectorJob extends Job { private ChangesetsCollectorJob(String name) { super(name); } @Override protected IStatus run(IProgressMonitor monitor) { monitor.beginTask("Get remote hg data", 2); Set oldSets = getChangeSets(); Set newSets; AbstractRemoteCache in = IncomingChangesetCache.getInstance(); AbstractRemoteCache out = OutgoingChangesetCache.getInstance(); int mode = getConfiguration().getMode(); switch (mode) { case ISynchronizePageConfiguration.INCOMING_MODE: monitor.subTask("Collecting incoming changesets"); newSets = initRemote(in); updateChangesets(oldSets, newSets, null); monitor.internalWorked(2); break; case ISynchronizePageConfiguration.OUTGOING_MODE: monitor.subTask("Collecting outgoing changesets"); newSets = initRemote(out); updateChangesets(oldSets, newSets, null); monitor.internalWorked(2); break; case ISynchronizePageConfiguration.BOTH_MODE: monitor.subTask("Collecting outgoing changesets"); newSets = initRemote(out); updateChangesets(oldSets, newSets, Direction.OUTGOING); monitor.internalWorked(1); monitor.subTask("Collecting incoming changesets"); newSets = initRemote(in); updateChangesets(oldSets, newSets, Direction.INCOMING); monitor.internalWorked(1); break; case ISynchronizePageConfiguration.CONFLICTING_MODE: monitor.subTask("Collecting outgoing changesets"); newSets = initRemote(out); monitor.internalWorked(1); monitor.subTask("Collecting incoming changesets"); newSets.addAll(initRemote(in)); monitor.internalWorked(1); newSets = retainConflicts(newSets); updateChangesets(oldSets, newSets, null); break; default: break; } monitor.done(); return Status.OK_STATUS; } } private void updateChangesets(Set oldSets, Set newSets, Direction direction){ Set removed = new HashSet(); for (ChangeSet changeSet : oldSets) { if(direction != null && direction != changeSet.getDirection()){ continue; } if(!newSets.contains(changeSet)){ remove(changeSet); removed.add(changeSet); } } for (ChangeSet changeSet : newSets) { if(!oldSets.contains(changeSet)){ add(changeSet); } } oldSets.removeAll(removed); } private static class ExclusiveRule implements ISchedulingRule { public boolean isConflicting(ISchedulingRule rule) { return contains(rule); } public boolean contains(ISchedulingRule rule) { return rule instanceof ExclusiveRule; } } public HgChangesetsCollector(ISynchronizePageConfiguration configuration) { super(configuration); this.participant = (MercurialSynchronizeParticipant) configuration.getParticipant(); branchListener = new IPropertyListener() { public void propertyChanged(Object source, int propId) { if(getScope().getChangesetProvider().isParticipantCreated()) { branchChanged((HgRoot) source); } } }; MercurialTeamProvider.addBranchListener(branchListener); getSubscriber().setCollector(this); } protected void branchChanged(HgRoot hgRoot) { MercurialSynchronizeSubscriber subscriber = getSubscriber(); IProject[] projects = subscriber.getProjects(); boolean needUpdate = false; for (IProject project : projects) { if(hgRoot.equals(MercurialTeamProvider.hasHgRoot(project))){ needUpdate = true; break; } } if(needUpdate){ initializeSets(); } } @Override protected void add(SyncInfo[] infos) { // noop } @Override protected void initializeSets() { Job job = new ChangesetsCollectorJob("Initializing changesets"); job.setRule(new ExclusiveRule()); job.schedule(100); } private Set retainConflicts(Set newSets) { // TODO let only changesets with conflicting changes return newSets; } private Set initRemote(final AbstractRemoteCache cache) { MercurialSynchronizeSubscriber subscriber = getSubscriber(); final IProject[] projects = subscriber.getProjects(); if(projects.length == 0){ return EMPTY_SET; } final IHgRepositoryLocation repo = participant.getRepositoryLocation(); final Set result = new HashSet(); Runnable runnable = new Runnable() { public void run() { for (IProject project : projects) { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(project); if(hgRoot == null){ continue; } String syncBranch = MercurialSynchronizeSubscriber.getSyncBranch(hgRoot); try { result.addAll(cache.getChangeSets(project, repo, syncBranch)); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } Set roots = ResourceUtils.groupByRoot(Arrays.asList(projects)).keySet(); for (HgRoot hgRoot : roots) { String syncBranch = MercurialSynchronizeSubscriber.getSyncBranch(hgRoot); try { result.addAll(cache.getUnmappedChangeSets(hgRoot, repo, syncBranch, result)); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } } }; try { MercurialSynchronizeSubscriber.executeLockedCacheTask(runnable); } catch (InterruptedException e) { MercurialEclipsePlugin.logError(e); return EMPTY_SET; } return result; } public MercurialSynchronizeSubscriber getSubscriber() { ISynchronizationContext context = participant.getContext(); RepositorySynchronizationScope scope = (RepositorySynchronizationScope) context.getScope(); return scope.getSubscriber(); } public RepositorySynchronizationScope getScope() { ISynchronizationContext context = participant.getContext(); return (RepositorySynchronizationScope) context.getScope(); } public void handleChange(IDiffChangeEvent event) { initializeSets(); } public Set getChangeSets() { Set result = new HashSet(); org.eclipse.team.internal.core.subscribers.ChangeSet[] sets = super.getSets(); for (org.eclipse.team.internal.core.subscribers.ChangeSet set : sets) { result.add((ChangeSet) set); } return result; } @Override public void dispose() { getSubscriber().setCollector(null); MercurialTeamProvider.removeBranchListener(branchListener); Object[] objects = getListeners(); for (Object object : objects) { removeListener((IChangeSetChangeListener) object); } super.dispose(); } /** * user has requested a manual refresh * @param roots currently unused */ public void refresh(ResourceMapping[] roots) { // the line below doesn't seem to work anymore as for some reason there is no // diff tree events anymore if we've updated to the the changeset and it should be removed // fireDefaultChangedEvent(null, null); // TODO not sure if this is a too big hammer, but right now it seems to fix the update issue #10985 initializeSets(); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("HgChangesetsCollector ["); if (participant != null) { builder.append("participant="); builder.append(participant); } builder.append("]"); return builder.toString(); } } SyncViewLabelProvider.java000066400000000000000000000172611173713500500363650ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import org.eclipse.compare.structuremergeviewer.Differencer; import org.eclipse.core.resources.IProject; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.team.internal.ui.mapping.ResourceModelLabelProvider; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.PathFromChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.FilteredPlaceholder; import com.vectrace.MercurialEclipse.utils.StringUtils; @SuppressWarnings("restriction") public class SyncViewLabelProvider extends ResourceModelLabelProvider { @Override public Image getImage(Object element) { // we MUST call super, to get the nice in/outgoing decorations... return super.getImage(element); } @Override protected Image getDelegateImage(Object element) { Image image = null; if (element instanceof ChangeSet) { image = MercurialEclipsePlugin.getImage("elcl16/changeset_obj.gif"); } else if (element instanceof ChangesetGroup){ ChangesetGroup group = (ChangesetGroup) element; if(group.getDirection() == Direction.OUTGOING){ image = MercurialEclipsePlugin.getImage("actions/commit.gif"); } else { image = MercurialEclipsePlugin.getImage("actions/update.gif"); } } else if(element instanceof FileFromChangeSet){ FileFromChangeSet file = (FileFromChangeSet) element; if(file.getFile() != null){ image = getDelegateLabelProvider().getImage(file.getFile()); } else { image = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FILE); } } else if (element instanceof PathFromChangeSet) { PathFromChangeSet path = (PathFromChangeSet) element; if(path.isProjectClosed()) { image = PlatformUI.getWorkbench().getSharedImages().getImage( IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED); } else { image = PlatformUI.getWorkbench().getSharedImages().getImage( ISharedImages.IMG_OBJ_FOLDER); } } else { try { image = super.getDelegateImage(element); } catch (NullPointerException npex) { // if element is invalid or not yet fully handled // NPE is possible MercurialEclipsePlugin.logError(npex); } } return image; } @Override protected Image decorateImage(Image base, Object element) { Image decoratedImage; if (element instanceof FileFromChangeSet) { FileFromChangeSet ffc = (FileFromChangeSet) element; int kind = ffc.getDiffKind(); decoratedImage = getImageManager().getImage(base, kind); } else if (element instanceof ChangesetGroup){ ChangesetGroup group = (ChangesetGroup) element; if(group.getDirection() == Direction.LOCAL){ decoratedImage = getImageManager().getImage(base, Differencer.CHANGE); } else { decoratedImage = getImageManager().getImage(base, Differencer.NO_CHANGE); } } else if (element instanceof WorkingChangeSet) { WorkingChangeSet cs = (WorkingChangeSet) element; if (cs instanceof GroupedUncommittedChangeSet && ((GroupedUncommittedChangeSet) cs).isDefault()) { decoratedImage = getDefaultChangesetIcon(); } else { decoratedImage = getWorkingChangesetIcon(); } } else { decoratedImage = getImageManager().getImage(base, Differencer.NO_CHANGE); } return decoratedImage; } public static Image getDefaultChangesetIcon() { return MercurialEclipsePlugin.getImage("elcl16/uncommitted_cs.gif", "ovr/pinned_ovr.gif", IDecoration.TOP_RIGHT); } public static Image getWorkingChangesetIcon() { return MercurialEclipsePlugin.getImage("elcl16/uncommitted_cs.gif", "ovr/edited_ovr.gif", IDecoration.TOP_RIGHT); } @Override protected String getDelegateText(Object elementOrPath) { if(elementOrPath instanceof ChangeSet){ ChangeSet cset = (ChangeSet) elementOrPath; StringBuilder sb = new StringBuilder(); if(!(cset instanceof WorkingChangeSet)){ sb.append(cset.getChangesetIndex()); if (cset.isCurrentOutgoing()) { sb.append('*'); } sb.append(" [").append(cset.getPerson()).append(']'); sb.append(" (").append(cset.getAgeDate()).append(')'); } else { sb.append(cset.getName()); sb.append(" (").append(cset.getChangesetFiles().length).append(')'); } if (!Branch.isDefault(cset.getBranch())) { sb.append(' ').append(cset.getBranch()); } sb.append(':').append(' ').append(getShortComment(cset)); return StringUtils.removeLineBreaks(sb.toString()); } if(elementOrPath instanceof ChangesetGroup){ ChangesetGroup group = (ChangesetGroup) elementOrPath; String name = group.getName(); if(group.getChangesets().isEmpty()){ return name + " (empty)"; } if(group.getDirection() == Direction.LOCAL) { int files = 0; for (ChangeSet cs : group.getChangesets()) { files += cs.getChangesetFiles().length; } if(files == 0) { return name + " (empty)"; } return name + " (" + files + ')'; } return name + " (" + group.getChangesets().size() + ')'; } if(elementOrPath instanceof FileFromChangeSet){ FileFromChangeSet file = (FileFromChangeSet) elementOrPath; String delegateText; if(file.getFile() != null) { delegateText = super.getDelegateText(file.getFile()); IProject project = file.getFile().getProject(); if(!project.isOpen()) { delegateText += " (closed!)"; } } else { delegateText = file.toString(); } if(file.getCopySourceFile() != null) { delegateText += " (" + super.getDelegateText(file.getCopySourceFile()) + ")"; } if(delegateText != null && delegateText.length() > 0){ delegateText = " " + delegateText; } return delegateText; } else if (elementOrPath instanceof PathFromChangeSet) { return elementOrPath.toString(); } else if (elementOrPath instanceof FilteredPlaceholder) { return elementOrPath.toString(); } String delegateText = super.getDelegateText(elementOrPath); if(delegateText != null && delegateText.length() > 0){ delegateText = " " + delegateText; } return delegateText; } /** * TODO: The entire comment should be shown in a tool tip */ private String getShortComment(ChangeSet cset) { String comment = cset.getComment(); if(comment.length() > 100){ comment = comment.substring(0, 100) + "..."; } return comment; } /** * @see org.eclipse.team.ui.synchronize.AbstractSynchronizeLabelProvider#getFont(java.lang.Object) */ @Override public Font getFont(Object element) { if (element instanceof GroupedUncommittedChangeSet) { if (((GroupedUncommittedChangeSet) element).isDefault()) { return JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT); } } return super.getFont(element); } } UncommittedChangesetGroup.java000066400000000000000000000262641173713500500372750ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Observable; import java.util.Observer; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.model.WorkingChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.synchronize.HgSubscriberMergeContext; import com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; /** * The group containing both "dirty" files as also not yet committed changesets *

* This group CAN observe changes of the status cache. If it is added as a listener * to the {@link MercurialStatusCache}, it only tracks the state of the enabled (root) * projects (see {@link UncommittedChangesetManager#getProjects()}). * * @author Andrei */ public class UncommittedChangesetGroup extends ChangesetGroup implements Observer, IUncommitted { private final List listeners; private final PropertyChangeEvent event; private HgSubscriberMergeContext context; private volatile boolean updateRequired; private volatile boolean cachingOn; private final MercurialStatusCache cache; private final Set files; private final UncommittedChangesetManager ucsManager; private static final String DEFAULT_NAME = "New changeset"; public UncommittedChangesetGroup() { super("Uncommitted", Direction.LOCAL); this.ucsManager = new UncommittedChangesetManager(this); cache = MercurialStatusCache.getInstance(); listeners = new CopyOnWriteArrayList(); event = new PropertyChangeEvent(this, "", null, ""); files = new HashSet(); } public void addListener(IPropertyChangeListener listener){ if(!listeners.contains(listener)) { listeners.add(listener); } } public void removeListener(IPropertyChangeListener listener){ listeners.remove(listener); } public void setContext(HgSubscriberMergeContext context) { this.context = context; } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#getContext() */ public HgSubscriberMergeContext getContext() { return context; } public void dispose() { cache.deleteObserver(this); clear(); } public void clear(){ Set files2 = ucsManager.getDefaultChangeset().getFiles(); files.removeAll(files2); ucsManager.getDefaultChangeset().clear(); Set set = getChangesets(); for (ChangeSet cs : set) { Iterator iterator = cs.getFiles().iterator(); while(iterator.hasNext()) { IFile file = iterator.next(); if (cache.isClean(file)) { ((GroupedUncommittedChangeSet) cs).removeFile(file); } } } } private boolean add(IFile file){ return add(file, ucsManager.getDefaultChangeset()); } public boolean contains(IFile file) { return files.contains(file); } public boolean add(IFile file, GroupedUncommittedChangeSet set){ if(!getChangesets().contains(set)) { return false; } if(context != null && context.isHidden(file)){ return false; } if(cache.isDirectory(file.getLocation())){ return false; } boolean added; synchronized (files){ added = files.add(file); } if(added) { // update files in the given changeset set.add(file); // we need only one event if(cachingOn){ updateRequired = true; } else { notifyListeners(); } } return added; } public boolean add(WorkingChangeSet cs) { if(getChangesets().contains(cs)) { return false; } getChangesets().add(cs); Set files2 = cs.getFiles(); for (IFile file : files2) { if(!files.add(file)) { cs.remove(file); } } changesetChanged(cs); return true; } public void committed(GroupedUncommittedChangeSet cs) { Set set = new LinkedHashSet(cs.getFiles()); for (IFile file : set) { remove(file, cs); } if(cs.isDefault()) { cs.setName(generateNewChangesetName()); cs.setComment(""); changesetChanged(cs); return; } getChangesets().remove(cs); move(cs.getFiles().toArray(new IFile[0]), ucsManager.getDefaultChangeset()); } public boolean delete(GroupedUncommittedChangeSet cs) { if(cs.isDefault()) { return false; } getChangesets().remove(cs); move(cs.getFiles().toArray(new IFile[0]), ucsManager.getDefaultChangeset()); return true; } public WorkingChangeSet create(IFile[] filesToAdd) { GroupedUncommittedChangeSet cs = new GroupedUncommittedChangeSet(generateNewChangesetName(), this); move(filesToAdd, cs); return cs; } /** * @return */ private String generateNewChangesetName() { Set allSets = getChangesets(); int count = 0; String name = DEFAULT_NAME; main: for (ChangeSet cs : allSets) { if(cs.getName().equals(name)) { if(count > 10000) { // stop looping, user is crazy anyway return DEFAULT_NAME; } count ++; name = DEFAULT_NAME + " #" + count; continue main; } } return name; } public void move(IFile[] files1, GroupedUncommittedChangeSet to){ Set changesets = getChangesets(); for (ChangeSet cs : changesets) { for (IFile file : files1) { if (cs.contains(file)) { ((GroupedUncommittedChangeSet)cs).removeFile(file); } } } if(!changesets.contains(to)) { changesets.add(to); } for (IFile file : files1) { to.add(file); } changesetChanged(to); } public void remove(IResource file, GroupedUncommittedChangeSet set){ if(file instanceof IFile) { set.removeFile((IFile) file); } files.remove(file); } /** * TODO currently unused but initially implemented for the issue 10732 * @param paths */ protected void hide(IPath[] paths){ if(context == null){ return; } boolean changed = false; MercurialStatusCache statusCache = MercurialStatusCache.getInstance(); Set projects = getProjectSet(); for (IPath path : paths) { if(path.segmentCount() < 2){ continue; } IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IProject project = root.getProject(path.segment(0)); if(project == null || !projects.contains(project)){ continue; } IResource res = project.findMember(path.removeFirstSegments(1)); // only allow to hide files which are dirty if(res instanceof IFile && !statusCache.isClean(res)){ IFile file = (IFile) res; synchronized (files) { if(files.contains(file)){ context.hide(file); files.remove(file); changed = true; } } } } if(changed){ updateRequired = true; endInput(null); } } private Set getProjectSet() { Set projects = new HashSet(); if(ucsManager.getProjects() != null){ projects.addAll(Arrays.asList(ucsManager.getProjects())); } return projects; } private void beginInput() { cachingOn = true; } private void endInput(IProgressMonitor monitor) { cachingOn = false; if(!updateRequired){ return; } updateRequired = false; notifyListeners(); } private void update(Set projectSet){ boolean changed = false; try { beginInput(); clear(); for (IProject project : projectSet) { changed |= update(project); } } finally { updateRequired |= changed; endInput(null); } } private boolean update(IProject project){ Set projects = getProjectSet(); if(!projects.contains(project)){ return false; } final int bits = MercurialStatusCache.MODIFIED_MASK; Set files2 = cache.getFiles(bits, project); if(files2.isEmpty()){ return true; } boolean changed = false; for (IFile file : files2) { changed |= add(file); } return changed; } public void changesetChanged(WorkingChangeSet set) { // TODO: add argument to avoid too much updates? ucsManager.storeChangesets(); // ucsManager.assignRemainingFiles(); notifyListeners(); } private void notifyListeners() { Job updateJob = new Job("Uncommitted changeset update"){ @Override protected IStatus run(IProgressMonitor monitor) { for (IPropertyChangeListener listener : listeners) { listener.propertyChange(event); } monitor.done(); return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return family == ExclusiveRule.class; } @Override public boolean shouldSchedule() { Job[] jobs = Job.getJobManager().find(ExclusiveRule.class); for (Job job : jobs) { ExclusiveRule rule = (ExclusiveRule) job.getRule(); if(UncommittedChangesetGroup.this.equals(rule.cs)){ // do not schedule me because exactly the same job is waiting to be started! return false; } } return true; } }; updateJob.setRule(new ExclusiveRule(this)); updateJob.schedule(50); } private final class ExclusiveRule implements ISchedulingRule { private final UncommittedChangesetGroup cs; public ExclusiveRule(UncommittedChangesetGroup cs) { this.cs = cs; } public boolean isConflicting(ISchedulingRule rule) { return contains(rule); } public boolean contains(ISchedulingRule rule) { return rule instanceof ExclusiveRule && cs.equals(((ExclusiveRule)rule).cs); } } @Override public boolean equals(Object obj) { return this == obj; } @Override public int hashCode() { return System.identityHashCode(this); } public void update(Observable o, Object arg) { update(getProjectSet()); } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#setProjects(org.eclipse.core.resources.IProject[]) */ public void setProjects(IProject[] projects) { ucsManager.setProjects(projects); cache.addObserver(this); } /** * @see com.vectrace.MercurialEclipse.synchronize.cs.HgChangeSetContentProvider.IUncommitted#getProjects() */ public IProject[] getProjects() { return ucsManager.getProjects(); } public void makeDefault(GroupedUncommittedChangeSet set) { ucsManager.makeDefault(set); } } UncommittedChangesetManager.java000066400000000000000000000171041173713500500375440ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronize/cs/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.synchronize.cs; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.Path; import org.eclipse.jface.preference.IPreferenceStore; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.GroupedUncommittedChangeSet; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * Loads and saves uncommitted changeset state in preferences * * @author Andrei */ class UncommittedChangesetManager { private static final String PATH_NAME_SEPARATOR = "="; private static final String MAPPINGS_SEPARATOR = ";"; private static final String KEY_FILES_PER_PROJECT_PREFIX = "projectFiles/"; private static final String KEY_CS_COMMENT_PREFIX = "changesetComment/"; private static final String KEY_CS_DEFAULT = "changesetIsDefault/"; private static final String KEY_CS_LIST = "changesets"; private boolean loadingFromPrefs; private GroupedUncommittedChangeSet defaultChangeset; private IProject[] projects; private final UncommittedChangesetGroup group; public UncommittedChangesetManager(UncommittedChangesetGroup group) { this.group = group; } protected GroupedUncommittedChangeSet createDefaultChangeset() { GroupedUncommittedChangeSet changeset = new GroupedUncommittedChangeSet("Default Changeset", group); changeset.setDefault(true); changeset.setComment("(no commit message)"); return changeset; } public UncommittedChangesetGroup getUncommittedGroup(){ return group; } private void loadSavedChangesets(){ Set sets = new HashSet(); loadfromPreferences(sets); assignRemainingFiles(); } private void assignRemainingFiles() { if(projects == null) { return; } group.update(null, null); } public void storeChangesets(){ if(loadingFromPrefs) { return; } IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); Set changesets = group.getChangesets(); Map> projectMap = new HashMap>(); StringBuilder changesetNames = new StringBuilder(); for (ChangeSet changeSet : changesets) { String name = changeSet.getName(); String comment = changeSet.getComment(); changesetNames.append(name).append(MAPPINGS_SEPARATOR); store.putValue(KEY_CS_COMMENT_PREFIX + name, comment); if(((GroupedUncommittedChangeSet)changeSet).isDefault()) { store.putValue(KEY_CS_DEFAULT, name); } Set files = changeSet.getFiles(); for (IFile file : files) { IProject project = file.getProject(); Map fileToChangeset = projectMap.get(project); if(fileToChangeset == null){ fileToChangeset = new HashMap(); projectMap.put(project, fileToChangeset); } fileToChangeset.put(file, name); } } store.putValue(KEY_CS_LIST, changesetNames.toString()); Set>> entrySet = projectMap.entrySet(); for (Entry> entry : entrySet) { IProject project = entry.getKey(); Map fileToChangeset = entry.getValue(); store.putValue(KEY_FILES_PER_PROJECT_PREFIX + project.getName(), encode(fileToChangeset)); } } public GroupedUncommittedChangeSet getDefaultChangeset(){ if(defaultChangeset == null) { defaultChangeset = createDefaultChangeset(); } return defaultChangeset; } private void loadfromPreferences(Set sets) { loadingFromPrefs = true; try { IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); String changesets = store.getString(KEY_CS_LIST); String defName = store.getString(KEY_CS_DEFAULT); if(!StringUtils.isEmpty(changesets)){ String[] names = changesets.split(MAPPINGS_SEPARATOR); for (String name : names) { if(!StringUtils.isEmpty(name)) { GroupedUncommittedChangeSet changeset = new GroupedUncommittedChangeSet(name, group); sets.add(changeset); } } } for (GroupedUncommittedChangeSet changeSet : sets) { String comment = store.getString(KEY_CS_COMMENT_PREFIX + changeSet.getName()); changeSet.setComment(comment); if(changeSet.getName().equals(defName)) { makeDefault(changeSet); } } if(projects == null){ return; } for (IProject project : projects) { String filesStr = store.getString(KEY_FILES_PER_PROJECT_PREFIX + project.getName()); if(StringUtils.isEmpty(filesStr)){ continue; } Map fileToChangeset = decode(filesStr, project); Set> entrySet = fileToChangeset.entrySet(); for (Entry entry : entrySet) { String name = entry.getValue(); GroupedUncommittedChangeSet changeset = getChangeset(name, sets); if(changeset == null){ continue; // changeset = new WorkingChangeSet(name, group); // sets.add(changeset); } changeset.add(entry.getKey()); } } } finally { loadingFromPrefs = false; } } private static GroupedUncommittedChangeSet getChangeset(String name, Set sets){ for (GroupedUncommittedChangeSet set : sets) { if(name.equals(set.getName())){ return set; } } return null; } /** * @param filesStr non null string encoded like "(project_rel_path=changeset_name;)*" * @param project * @return */ private static Map decode(String filesStr, IProject project) { Map fileToChangeset = new HashMap(); String[] mappings = filesStr.split(MAPPINGS_SEPARATOR); for (String mapping : mappings) { if(StringUtils.isEmpty(mapping)){ continue; } String[] pathAndName = mapping.split(PATH_NAME_SEPARATOR); if(pathAndName.length != 2){ continue; } IFile file = project.getFile(new Path(pathAndName[0])); if(file != null) { fileToChangeset.put(file, pathAndName[1]); } } return fileToChangeset; } private static String encode(Map fileToChangeset){ Set> entrySet = fileToChangeset.entrySet(); StringBuilder sb = new StringBuilder(); for (Entry entry : entrySet) { IFile file = entry.getKey(); String changesetName = entry.getValue(); sb.append(file.getProjectRelativePath()).append(PATH_NAME_SEPARATOR).append(changesetName); sb.append(MAPPINGS_SEPARATOR); } return sb.toString(); } public void setProjects(IProject[] projects) { this.projects = projects; loadSavedChangesets(); if(projects != null){ assignRemainingFiles(); } } public IProject[] getProjects() { return projects; } public void makeDefault(GroupedUncommittedChangeSet set) { if(set == null || !group.getChangesets().contains(set)){ return; } if(defaultChangeset != null) { defaultChangeset.setDefault(false); } defaultChangeset = set; defaultChangeset.setDefault(true); group.changesetChanged(set); } } messages.properties000066400000000000000000000024631173713500500346160ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/synchronizeMercurialSynchronizeSubscriber.refreshing=Refreshing MercurialSynchronizeSubscriber.refreshing.2=\ for MercurialSynchronizeSubscriber.refreshingIncoming=Refreshing incoming changesets... MercurialSynchronizeSubscriber.refreshingLocal=Refreshing local resource status... MercurialSynchronizeSubscriber.refreshingOutgoing=Refreshing outgoing changesets... MercurialSynchronizeSubscriber.refreshingResources=Refreshing resources... MercurialSynchronizeSubscriber.repoWatcher=Mercurial Repository Watcher MercurialSynchronizeSubscriber.triggeringStatusCalc=Triggering sync status calculation. MercurialSynchronizeSubscriber.connectError=Remote repository is not accessible. Check the URL and internet connection. PushPullSynchronizeOperation.PullTask=Starting pull from PushPullSynchronizeOperation.PullJob=Pulling... PushPullSynchronizeOperation.PushTask=Starting push to PushPullSynchronizeOperation.PushJob=Pushing... PushPullSynchronizeOperation.PushFailed=Could not perform push: HgSubscriberMergeContext.AvoidMergeTitle=Disallowed operation HgSubscriberMergeContext.AvoidMergeMessage=Merge is not allowed here. Use 'Pull' or 'Pull and update' from context menu! MercurialSynchronizePageActionGroup.PresentationMode=Presentation PresentationMode.Flat=Flat PresentationMode.Tree=Tree PresentationMode.CompressedTree=Compressed Treeeclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/000077500000000000000000000000001173713500500273165ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ActionAdd.java000066400000000000000000000035361173713500500320160ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.AddHandler; public class ActionAdd implements IWorkbenchWindowActionDelegate { private IStructuredSelection selection; public ActionAdd() { super(); } public void dispose() { } public void init(IWorkbenchWindow w) { } private List getSelectedResources() { List l = new ArrayList(); for (Object o : selection.toList()) { l.add((IResource) o); } return l; } public void run(IAction action) { try { new AddHandler().run(getSelectedResources()); } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } } public void selectionChanged(IAction action, ISelection inSelection) { if (inSelection != null && inSelection instanceof IStructuredSelection) { selection = (IStructuredSelection) inSelection; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ActionAnnotate.java000066400000000000000000000055021173713500500330720ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * David Watson - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.annotations.ShowAnnotationOperation; import com.vectrace.MercurialEclipse.menu.Messages; public class ActionAnnotate implements IWorkbenchWindowActionDelegate { private IStructuredSelection selection; public ActionAnnotate() { super(); } /** * We can use this method to dispose of any system resources we previously * allocated. * * @see IWorkbenchWindowActionDelegate#dispose */ public void dispose() { } /** * We will cache window object in order to be able to provide parent shell * for the message dialog. * * @see IWorkbenchWindowActionDelegate#init */ public void init(IWorkbenchWindow w) { } /** * The action has been activated. The argument of the method represents the * 'real' action sitting in the workbench UI. * * @see IWorkbenchWindowActionDelegate#run */ public void run(IAction action) { if (selection.getFirstElement() instanceof IResource) { run((IResource) selection.getFirstElement()); } } public void run(IResource res) { IWorkbenchPart part = MercurialEclipsePlugin.getActivePage().getActivePart(); try { new ShowAnnotationOperation(part, res).run(); } catch (Exception e) { MessageDialog.openError(part.getSite().getShell(), Messages.getString("ShowAnnotationHandler.hgSays"), e.getMessage() //$NON-NLS-1$ + Messages.getString("ShowAnnotationHandler.seeErrorLogForMoreDetails")); //$NON-NLS-1$ } } /** * Selection in the workbench has been changed. We can change the state of * the 'real' action here if we want, but this can only happen after the * delegate has been created. * * @see IWorkbenchWindowActionDelegate#selectionChanged */ public void selectionChanged(IAction action, ISelection inSelection) { if (inSelection instanceof IStructuredSelection) { selection = (IStructuredSelection) inSelection; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ActionChangeLog.java000066400000000000000000000046561173713500500331610ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Software Balm Consulting Inc (Peter Hunnisett ) - some updates * StefanC - some updates, code cleanup * Stefan Groschupf - logError *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.team.ui.TeamUI; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; public class ActionChangeLog implements IWorkbenchWindowActionDelegate { private IStructuredSelection selection; public ActionChangeLog() { super(); } /** * We can use this method to dispose of any system resources we previously * allocated. * * @see IWorkbenchWindowActionDelegate#dispose */ public void dispose() { } /** * We will cache window object in order to be able to provide parent shell * for the message dialog. * * @see IWorkbenchWindowActionDelegate#init */ public void init(IWorkbenchWindow window) { } /** * The action has been activated. The argument of the method represents the * 'real' action sitting in the workbench UI. * * @see IWorkbenchWindowActionDelegate#run */ public void run(IAction action) { final IResource resource = (IResource) selection.getFirstElement(); TeamUI.getHistoryView().showHistoryFor(resource); } /** * Selection in the workbench has been changed. We can change the state of * the 'real' action here if we want, but this can only happen after the * delegate has been created. * * @see IWorkbenchWindowActionDelegate#selectionChanged */ public void selectionChanged(IAction action, ISelection inSelection) { if (inSelection != null && inSelection instanceof IStructuredSelection) { selection = (IStructuredSelection) inSelection; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ActionCommit.java000066400000000000000000000052361173713500500325550ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * David Watson - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.CommitHandler; public class ActionCommit implements IWorkbenchWindowActionDelegate { private IStructuredSelection selection; public ActionCommit() { super(); } /** * We can use this method to dispose of any system resources we previously * allocated. * * @see IWorkbenchWindowActionDelegate#dispose */ public void dispose() { } /** * We will cache window object in order to be able to provide parent shell * for the message dialog. * * @see IWorkbenchWindowActionDelegate#init */ public void init(IWorkbenchWindow w) { } /** * @return */ private List getSelectedResources() { List l = new ArrayList(); for (Object o : selection.toList()) { l.add((IResource) o); } return l; } /** * The action has been activated. The argument of the method represents the * 'real' action sitting in the workbench UI. * @throws HgException * * @see IWorkbenchWindowActionDelegate#run */ public void run(IAction action) { try { new CommitHandler().run(getSelectedResources()); } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } } /** * Selection in the workbench has been changed. We can change the state of * the 'real' action here if we want, but this can only happen after the * delegate has been created. * * @see IWorkbenchWindowActionDelegate#selectionChanged */ public void selectionChanged(IAction action, ISelection inSelection) { if (inSelection != null && inSelection instanceof IStructuredSelection) { selection = (IStructuredSelection) inSelection; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ActionRemove.java000066400000000000000000000072761173713500500325700ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Software Balm Consulting Inc (Peter Hunnisett ) - some updates * Stefan Groschupf - logError * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgRemoveClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.RefreshStatusJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author zingo */ public class ActionRemove implements IWorkbenchWindowActionDelegate { private IWorkbenchWindow window; private IStructuredSelection selection; public ActionRemove() { super(); } /** * We can use this method to dispose of any system resources we previously * allocated. * * @see IWorkbenchWindowActionDelegate#dispose */ public void dispose() { selection = null; window = null; } /** * We will cache window object in order to be able to provide parent shell * for the message dialog. * * @see IWorkbenchWindowActionDelegate#init */ public void init(IWorkbenchWindow w) { this.window = w; } /** * The action has been activated. The argument of the method represents the * 'real' action sitting in the workbench UI. * * @see IWorkbenchWindowActionDelegate#run */ public void run(IAction action) { Shell shell = window != null ? window.getShell() : MercurialEclipsePlugin.getActiveShell(); if (!confirmRemove(shell)) { return; } List resources = ResourceUtils.getResources(selection); Map> byRoot = ResourceUtils.groupByRoot(resources); try { HgRemoveClient.removeResourcesLater(byRoot); } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } finally { for (Map.Entry> mapEntry : byRoot.entrySet()) { HgRoot hgRoot = mapEntry.getKey(); new RefreshStatusJob("Refreshing " + hgRoot.getName(), hgRoot).schedule(); } } } private boolean confirmRemove(Shell shell) { return MessageDialog.openConfirm(shell, Messages.getString("ActionRemove.removeFileTitle"), Messages.getString("ActionRemove.removeFileConfirmation")); } /** * Selection in the workbench has been changed. We can change the state of * the 'real' action here if we want, but this can only happen after the * delegate has been created. * * @see IWorkbenchWindowActionDelegate#selectionChanged */ public void selectionChanged(IAction action, ISelection newSelection) { if (newSelection instanceof IStructuredSelection) { selection = (IStructuredSelection) newSelection; } else { selection = null; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ActionResolve.java000066400000000000000000000033601173713500500327400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.lang.reflect.InvocationTargetException; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.operations.ResolveOperation; public class ActionResolve implements IWorkbenchWindowActionDelegate { private IStructuredSelection selection; public void dispose() { } public void init(IWorkbenchWindow arg0) { } public void run(IAction action) { IWorkbenchPart part = MercurialEclipsePlugin.getActivePage().getActivePart(); try { new ResolveOperation(part, selection.toArray(), true).run(); } catch (InvocationTargetException e) { MercurialEclipsePlugin.showError(e.getTargetException()); } catch (InterruptedException e) { MercurialEclipsePlugin.showError(e); } } public void selectionChanged(IAction action, ISelection inSelection) { if (inSelection instanceof IStructuredSelection) { selection = (IStructuredSelection) inSelection; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ActionRevert.java000066400000000000000000000376551173713500500326060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Software Balm Consulting Inc (Peter Hunnisett ) - some updates * StefanC - some updates * Charles O'Farrell - fix revert open file * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeWorkspaceJob; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.commands.HgRevertClient; import com.vectrace.MercurialEclipse.dialogs.RevertDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.UpdateHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class ActionRevert implements IWorkbenchWindowActionDelegate { private IWorkbenchWindow window; private IStructuredSelection selection; private ChangeSet changesetToRevert; public ActionRevert() { super(); } /** * We can use this method to dispose of any system resources we previously * allocated. * * @see IWorkbenchWindowActionDelegate#dispose */ public void dispose() { } /** * We will cache window object in order to be able to provide parent shell * for the message dialog. * * @see IWorkbenchWindowActionDelegate#init */ public void init(IWorkbenchWindow w) { this.window = w; } /** * The action has been activated. The argument of the method represents the * 'real' action sitting in the workbench UI. * * @see IWorkbenchWindowActionDelegate#run */ public void run(IAction action) { if(window == null){ window = MercurialEclipsePlugin.getActiveWindow(); } IResource singleSelection = getSingleSelection(); if(singleSelection != null) { if (changesetToRevert != null) { try { revertToGivenVersion(singleSelection, changesetToRevert, new NullProgressMonitor()); } catch (final HgException e) { handleWithDialog(e); } return; } if (action != null && "com.vectrace.MercurialEclipse.team.ReplaceWithParentAction".equals(action.getId())) { revertToParentVersion(singleSelection); return; } } List resources = new ArrayList(); boolean mergeIsRunning = collectResourcesToRevert(resources); if (resources.size() > 0 && !mergeIsRunning) { openRevertDialog(resources, false); } else { if(mergeIsRunning){ boolean doRevert = MessageDialog .openConfirm( getShell(), Messages.getString("ActionRevert.HgRevert"), //$NON-NLS-1$ Messages.getString("ActionRevert.mergeIsRunning")); //$NON-NLS-1$ if(doRevert){ openRevertDialog(resources, true); } } else { MessageDialog .openInformation( getShell(), Messages.getString("ActionRevert.HgRevert"), //$NON-NLS-1$ Messages.getString("ActionRevert.noFilesToRevert")); //$NON-NLS-1$ } } } private static void handleWithDialog(final HgException e) { MercurialEclipsePlugin.logError(e); // TODO use statushandler??? if(Display.getCurrent() != null) { MercurialEclipsePlugin.showError(e); } else { MercurialEclipsePlugin.getStandardDisplay().asyncExec(new Runnable() { public void run() { MercurialEclipsePlugin.showError(e); } }); } } private IResource getSingleSelection(){ if(selection == null || selection.size() != 1){ return null; } return ResourceUtils.getResource(selection.getFirstElement()); } private static ChangeSet getParentChangeset(IResource resource) throws HgException { String[] parents = HgParentClient.getParentNodeIds(resource); ChangeSet cs = LocalChangesetCache.getInstance().getOrFetchChangeSetById(resource, parents[0]); if(cs != null && cs.getChangesetIndex() != 0) { parents = cs.getParents(); if (parents == null || parents.length == 0) { if(MercurialStatusCache.getInstance().isClean(resource)){ parents = HgParentClient.getParentNodeIds(resource, cs); } } if (parents != null && parents.length > 0) { return LocalChangesetCache.getInstance().getOrFetchChangeSetById(resource, parents[0]); } } return null; } private static void revertToParentVersion(final IResource resource){ Job job = new Job("Reverting to parent revision: " + ResourceUtils.getPath(resource)){ @Override protected IStatus run(IProgressMonitor monitor) { ChangeSet cs; try { cs = getParentChangeset(resource); revertToGivenVersion(resource, cs, monitor); } catch (HgException e) { handleWithDialog(e); return e.getStatus(); } return Status.OK_STATUS; } }; job.schedule(); } private static void revertToGivenVersion(IResource resource, ChangeSet cs, IProgressMonitor monitor) throws HgException { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(resource); if(hgRoot == null) { throw new HgException("Hg root not found for: " + resource); } List list = new ArrayList(); list.add(resource); Set reverted = HgRevertClient.performRevert(monitor, hgRoot, list, cs); for (String path : reverted) { IFile fileHandle = ResourceUtils.getFileHandle(new Path(path)); if(fileHandle != null) { refreshResource(monitor, MercurialStatusCache.getInstance(), fileHandle); } } } private Shell getShell() { return window != null ? window.getShell() : MercurialEclipsePlugin.getActiveShell(); } private void openRevertDialog(List resources, final boolean cleanAfterMerge) { final List result; final List untracked; RevertDialog chooser = null; if(!cleanAfterMerge){ chooser = new RevertDialog(Display.getCurrent().getActiveShell(), resources); if (chooser.open() != Window.OK) { return; } result = chooser.getSelectionForHgRevert(); untracked = chooser.getUntrackedSelection(); } else { result = resources; // TODO allow to revert untracked files after the merge too untracked = new ArrayList(); } final ChangeSet cs = chooser != null ? chooser.getChangeset() : null; new SafeWorkspaceJob(Messages.getString("ActionRevert.revertFiles")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor) { try { doRevert(monitor, result, untracked, cleanAfterMerge, cs); } catch (HgException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } return Status.OK_STATUS; } }.schedule(); } private boolean collectResourcesToRevert(List resources) { boolean mergeIsRunning = false; for (Object obj : selection.toList()) { if (obj instanceof IResource) { IResource resource = (IResource) obj; boolean merging = MercurialStatusCache.getInstance().isMergeInProgress(resource); if(merging){ mergeIsRunning = true; } boolean supervised = MercurialTeamProvider.isHgTeamProviderFor(resource); if (supervised) { resources.add(resource); } } } return mergeIsRunning; } public void doRevert(IProgressMonitor monitor, List resources, List untracked, boolean cleanAfterMerge, ChangeSet cs) throws HgException { monitor.beginTask(Messages.getString("ActionRevert.revertingResources"), resources.size() * 2); //$NON-NLS-1$ Map> filesToRevert = ResourceUtils.groupByProject(resources); Set projects = filesToRevert.keySet(); // cleanup untracked files first deleteUntrackedFiles(untracked, monitor); // collect removed file state NOW MercurialStatusCache cache = MercurialStatusCache.getInstance(); Map> removedFilesBefore = getFiles(MercurialStatusCache.BIT_REMOVED, projects); Map> addedFilesBefore = getFiles(MercurialStatusCache.BIT_ADDED, removedFilesBefore.keySet()); // keep track only for projects where both add AND remove is reported removedFilesBefore.keySet().retainAll(addedFilesBefore.keySet()); // perform revert Map> rootToFiles = ResourceUtils.groupByRoot(resources); if(cleanAfterMerge) { for (Entry> entry : rootToFiles.entrySet()) { performRevertAfterMerge(monitor, entry.getKey(), entry.getValue()); } } else { for (Entry> entry : rootToFiles.entrySet()) { HgRevertClient.performRevert(monitor, entry.getKey(), entry.getValue(), cs); } } for (IResource resource : resources) { monitor.subTask(Messages.getString("ActionRevert.refreshing") + resource.getName() + "..."); //$NON-NLS-1$ //$NON-NLS-2$ refreshResource(monitor, cache, resource); monitor.worked(1); } for (Entry> entry : removedFilesBefore.entrySet()) { cache.refreshStatus(entry.getKey(), monitor); } // we are looking for files, which are NOT in the "reverted" files list // and which are NOT marked as deleted in the latest cached state // BUT which was marked as deleted before the revert operation. // These "deleted before, do not reverted and missing in the status now" files are // the source files recreated after the revert of a "move (rm + add)" operation. // We have to tell Eclipse, that the files are "living" again in the resources tree Map> filesToUpdate = new HashMap>(); Map> removedFilesAfter = getFiles( MercurialStatusCache.BIT_REMOVED, removedFilesBefore.keySet()); for (Entry> entry : removedFilesBefore.entrySet()) { IProject projBefore = entry.getKey(); Set removedBefore = entry.getValue(); Set removedAfter = removedFilesAfter.get(projBefore); if(removedAfter != null && !removedAfter.isEmpty()) { removedBefore.removeAll(removedAfter); } List reverted = filesToRevert.get(projBefore); if(reverted != null && !reverted.isEmpty()) { removedBefore.removeAll(reverted); } if(!removedBefore.isEmpty()){ filesToUpdate.put(projBefore, removedBefore); } } for (Entry> entry : filesToUpdate.entrySet()) { Set removed = entry.getValue(); for (IResource resource : removed) { refreshResource(monitor, cache, resource); } } monitor.done(); } /** * @param cache non null * @param resource non null */ private static void refreshResource(IProgressMonitor monitor, MercurialStatusCache cache, IResource resource) { try { if(cache.isAdded(ResourceUtils.getPath(resource))){ // added files didn't change content after we un-add them, so we have // give Eclipse a hint to start some extra refresh work. ResourceUtils.touch(resource); } // we still need to trigger a refresh to avoid confusing editors opened on // these files. Without refresh, they complain that the files are changed but not refreshed resource.refreshLocal(IResource.DEPTH_ONE, monitor); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } /** * Deletes given resources and cleans up the cache state for them */ private void deleteUntrackedFiles(List untracked, IProgressMonitor monitor) { MercurialStatusCache cache = MercurialStatusCache.getInstance(); for (IResource resource : untracked) { try { IContainer parent = null; if(resource instanceof IFile){ parent = resource.getParent(); if(parent instanceof IProject && ".project".equals(resource.getName())){ MercurialEclipsePlugin.logInfo( "Will NOT delete .project file from project " + parent.getName(), null); // do not revert .project file.... continue; } resource.delete(IResource.FORCE | IResource.KEEP_HISTORY, monitor); } else if(!(resource instanceof IProject)){ resource.delete(IResource.KEEP_HISTORY, monitor); } deleteEmptyDirs(parent, monitor); cache.clearStatusCache(resource); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } /** * Recursive deletes empty directories, starting with given one */ private void deleteEmptyDirs(IContainer dir, IProgressMonitor monitor) throws CoreException { int memberFlags = IContainer.INCLUDE_HIDDEN | IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS; if (dir != null && !(dir instanceof IProject) && dir.members(memberFlags).length == 0) { IContainer parent = dir.getParent(); dir.delete(false, monitor); deleteEmptyDirs(parent, monitor); } } /** * @param projects * @param statusBit one of {@link MercurialStatusCache} status bits * @return a map where the files with the specified state are grouped by the project. * Projects with no files of given state are not included into the map */ private static Map> getFiles(int statusBit, Set projects) { MercurialStatusCache cache = MercurialStatusCache.getInstance(); Map> resources = new HashMap>(); for (IProject project : projects) { Set removed = cache.getResources(statusBit, project); if(!removed.isEmpty()) { resources.put(project, removed); } } return resources; } private void performRevertAfterMerge(IProgressMonitor monitor, HgRoot hgRoot, List resources) { // see http://mercurial.selenic.com/wiki/FAQ#FAQ.2BAC8-CommonProblems.hg_status_shows_changed_files_but_hg_diff_doesn.27t.21 // To completely undo the uncommitted merge and discard all local modifications, // you will need to issue a hg update -C -r . (note the "dot" at the end of the command). try { UpdateHandler update = new UpdateHandler(false); update.setCleanEnabled(true); update.setRevision("."); update.setShell(getShell()); update.run(hgRoot); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } } /** * Selection in the workbench has been changed. We can change the state of * the 'real' action here if we want, but this can only happen after the * delegate has been created. * * @see IWorkbenchWindowActionDelegate#selectionChanged */ public void selectionChanged(IAction action, ISelection inSelection) { if (inSelection != null && inSelection instanceof IStructuredSelection) { selection = (IStructuredSelection) inSelection; } } public void setChangesetToRevert(ChangeSet changesetToRevert) { this.changesetToRevert = changesetToRevert; } } ActionShowRootHistory.java000066400000000000000000000036701173713500500344140ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Display; import org.eclipse.team.ui.TeamUI; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; public class ActionShowRootHistory implements IWorkbenchWindowActionDelegate { private IStructuredSelection selection; public ActionShowRootHistory() { super(); } public void dispose() { // noop } public void init(IWorkbenchWindow window) { } public void run(IAction action) { final IResource resource = (IResource) selection.getFirstElement(); final HgRoot hgRoot = MercurialTeamProvider.getHgRoot(resource); if (hgRoot == null) { MercurialEclipsePlugin.showError(new IllegalStateException("There is no hg root for: " + resource)); return; } Runnable r = new Runnable() { public void run() { TeamUI.getHistoryView().showHistoryFor(hgRoot); } }; Display.getDefault().asyncExec(r); } public void selectionChanged(IAction action, ISelection inSelection) { if (inSelection != null && inSelection instanceof IStructuredSelection) { selection = (IStructuredSelection) inSelection; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/CompareAction.java000066400000000000000000000164171173713500500327160ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.CompareUI; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.Display; import org.eclipse.team.core.TeamException; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.commands.HgResolveClient; import com.vectrace.MercurialEclipse.compare.RevisionNode; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgResource; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.CompareUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author zingo, Jerome Negre */ public class CompareAction extends SingleResourceAction { private boolean mergeEnabled; private ISynchronizePageConfiguration syncConfig; private boolean isUncommittedCompare = false; // constructors /** * Empty constructor must be here, otherwise Eclipse wouldn't be able to create the object via reflection */ public CompareAction() { super(); } public CompareAction(IResource res) { this(); this.selection = res; } // operations /** * @param file non null */ @Override protected void run(final IResource resource) throws TeamException { Job job = new Job("Diff for " + resource.getName()) { @Override protected IStatus run(IProgressMonitor monitor) { boolean workspaceUpdateConflict = isUncommittedCompare && resource instanceof IFile && MercurialStatusCache.getInstance().isWorkspaceUpdateConfict((IFile)resource); if (workspaceUpdateConflict) { // This job shouldn't run in the UI thread despite needing it a lot because it // invokes hg multiple times. final Boolean[] resultRef = { Boolean.FALSE }; getShell().getDisplay().syncExec(new Runnable() { public void run() { resultRef[0] = Boolean .valueOf(MessageDialog .openQuestion( getShell(), "Compare", "This file is in conflict. Would you like to use resolve to *RESTART* the merge with 3-way differences? Warning: if resolve fails this operations can potentially lose changes. If in doubt select 'No'.")); } }); workspaceUpdateConflict = resultRef[0].booleanValue(); } if (mergeEnabled || workspaceUpdateConflict) { openMergeEditor((IFile)resource, workspaceUpdateConflict); return Status.OK_STATUS; } boolean clean = MercurialStatusCache.getInstance().isClean(resource); if (!clean) { compareToLocal(resource); return Status.OK_STATUS; } try { String[] parents = HgParentClient.getParentNodeIds(resource); HgRoot root = MercurialRootCache.getInstance().getHgRoot(resource); ChangeSet cs = LocalChangesetCache.getInstance().getOrFetchChangeSetById(root, parents[0]); if (cs == null) { // refetch cache and try again LocalChangesetCache.getInstance().fetchRevisions(root, false, 0, 0, false); cs = LocalChangesetCache.getInstance().getOrFetchChangeSetById(root, parents[0]); } if (cs != null) { // TODO: compare with parent on a project? if (resource instanceof IFile) { CompareUtils.openEditor(resource, MercurialUtilities.getParentRevision(cs, (IFile)resource), false, null); } return Status.OK_STATUS; } } catch (TeamException e) { MercurialEclipsePlugin.logError(e); } // something went wrong. So compare to local compareToLocal(resource); return Status.OK_STATUS; } }; job.schedule(); } private void compareToLocal(IResource res) { IHgResource right = ResourceUtils.getCleanLocalHgResource(res); try { CompareUtils.openEditor(res, new RevisionNode(right), false, syncConfig); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } /** * @param file non null */ private static void openMergeEditor(final IFile file, boolean workspaceUpdateConflict){ try { MercurialRevisionStorage ancestorNode; MercurialRevisionStorage mergeNode; if (workspaceUpdateConflict) { String[] changeSets = HgResolveClient.restartMergeAndGetChangeSetsForCompare(file); String otherId = changeSets[1]; String ancestorId = changeSets[2]; if (otherId == null || ancestorId == null) { getShell().getDisplay().asyncExec(new Runnable() { public void run() { MessageDialog.openError(getShell(), "Merge error", "Couldn't retrieve merge info from Mercurial"); } }); MercurialEclipsePlugin.logError(new HgException("HgResolveClient returned null revision id")); return; } mergeNode = new MercurialRevisionStorage(file, otherId); ancestorNode = new MercurialRevisionStorage(file, ancestorId); } else { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(file); if(hgRoot == null) { MercurialEclipsePlugin.showError(new IllegalStateException( "Failed to find hg root for: " + file.getLocation())); return; } String mergeNodeId = MercurialStatusCache.getInstance().getMergeChangesetId(hgRoot); String[] parents = HgParentClient.getParentNodeIds(hgRoot); int ancestor = Integer.parseInt(HgParentClient.findCommonAncestor(hgRoot, parents[0], parents[1])[0]); mergeNode = new MercurialRevisionStorage(file, mergeNodeId); ancestorNode = (ancestor <= 0) ? null : new MercurialRevisionStorage(file, ancestor); } final CompareEditorInput compareInput = CompareUtils.getPrecomputedCompareInput(file, ancestorNode, mergeNode); Display.getDefault().asyncExec(new Runnable() { public void run() { CompareUI.openCompareEditor(compareInput); } }); } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } } public void setEnableMerge(boolean enable) { mergeEnabled = enable; } public void setUncommittedCompare(boolean enable) { isUncommittedCompare = enable; } public void setSynchronizePageConfiguration(ISynchronizePageConfiguration syncConfig){ this.syncConfig = syncConfig; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/CompareWithAction.java000066400000000000000000000030041173713500500335360ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.core.resources.IResource; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.team.core.TeamException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.dialogs.RevisionChooserDialog; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.utils.CompareUtils; /** * @author Jerome Negre * */ public class CompareWithAction extends CompareAction { @Override public void run(IResource resource) throws TeamException { RevisionChooserDialog dialog = new RevisionChooserDialog(MercurialEclipsePlugin.getActiveShell(), Messages.getString("CompareWithAction.compareWith"), MercurialRootCache.getInstance().getHgRoot(resource)); //$NON-NLS-1$ int result = dialog.open(); if (result == IDialogConstants.OK_ID) { CompareUtils.openEditor(resource, dialog.getChangeSet()); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/DecoratorImages.java000066400000000000000000000054421173713500500332360ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.jface.resource.ImageDescriptor; /** * Set of images that are used for decorating resources are maintained * here. This acts as a image registry and hence there is a single copy * of the image files floating around the project. */ public final class DecoratorImages { private DecoratorImages() { // hide constructor of utility class. } /** * Added Image Descriptor */ public static final ImageDescriptor ADDED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/added_ov.gif"); //$NON-NLS-1$ /** * Deleted but still tracked Image Descriptor */ public static final ImageDescriptor DELETED_STILL_TRACKED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/deleted_still_tracked_ov.gif"); //$NON-NLS-1$ /** * Ignored Image Descriptor */ public static final ImageDescriptor IGNORED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/ignored_ov.gif"); //$NON-NLS-1$ /** * Modified Image Descriptor */ public static final ImageDescriptor MODIFIED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/modified_ov.gif"); //$NON-NLS-1$ /** * Copied Image Descriptor */ public static final ImageDescriptor COPIED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/copied_ov.gif"); //$NON-NLS-1$ /** * Moved Image Descriptor */ public static final ImageDescriptor MOVED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/moved_ov.gif"); //$NON-NLS-1$ /** * Not tracked Image Descriptor */ public static final ImageDescriptor NOT_TRACKED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/not_tracked_ov.gif"); //$NON-NLS-1$ /** * Removed Image Descriptor */ public static final ImageDescriptor REMOVED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/removed_ov.gif"); //$NON-NLS-1$ /** * Managed Image Descriptor */ public static final ImageDescriptor MANAGED = ImageDescriptor.createFromFile(DecoratorImages.class, "images/managed_ov.gif"); //$NON-NLS-1$ /** * Conflict Image Descriptor */ public static final ImageDescriptor CONFLICT = ImageDescriptor.createFromFile(DecoratorImages.class, "images/confchg_ov.gif"); //$NON-NLS-1$ } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/HgMoveDeleteHook.java000066400000000000000000000515351173713500500333230ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Balm Consulting Inc (Peter Hunnisett ) - implementation * VecTrace (Zingo Andersen) - some updates * Stefan Groschupf - logError * Stefan C - Code cleanup * Bastian Doetsch - Code reformatting to code style and refreshes * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.internal.resources.ICoreConstants; import org.eclipse.core.internal.resources.Resource; import org.eclipse.core.internal.resources.ResourceInfo; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.team.IMoveDeleteHook; import org.eclipse.core.resources.team.IResourceTree; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Display; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.TeamException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgRemoveClient; import com.vectrace.MercurialEclipse.commands.HgRenameClient; import com.vectrace.MercurialEclipse.commands.HgRevertClient; import com.vectrace.MercurialEclipse.dialogs.CommitDialog.Options; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.CommitHandler; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.RefreshStatusJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Peter Hunnisett * * Hook into Eclipse rename and delete file operations so that the * appropriate changes can be tracked in Mercurial as well. */ public class HgMoveDeleteHook implements IMoveDeleteHook { private static final MercurialStatusCache CACHE = MercurialStatusCache.getInstance(); /** * @returns true if this file under this under Mercurial * control. */ private static boolean isInMercurialRepo(IResource file, IProgressMonitor monitor) { return CACHE.isSupervised(file); } /** * Determines if a folder has supervised files * * @returns true if there are files under this folder that are * under Mercurial control. */ private static boolean folderHasMercurialFiles(IFolder folder, IProgressMonitor monitor) { if (!isInMercurialRepo(folder, monitor)) { // Resource could be inside a link or something do nothing // in the future this could check is this is another repository return false; } try { IResource[] children = folder.members(); for (IResource resource : children) { if (resource.getType() == IResource.FILE) { if (resource.exists() && isInMercurialRepo(resource, monitor)) { return true; } } else { if(folderHasMercurialFiles((IFolder) resource, monitor)){ return true; } } } } catch (CoreException e) { /* * Let's assume that this means there are no resources under this * one as it probably doesn't properly exist. Let eclipse do * everything. */ return false; } return false; } public boolean deleteFile(IResourceTree tree, IFile file, int updateFlags, IProgressMonitor monitor) { /* * Returning false indicates that the caller should invoke * tree.standardDeleteFile to actually remove the resource from the file * system and eclipse. */ if (!isInMercurialRepo(file, monitor) || file.isDerived() || file.isLinked()) { return false; } boolean keepHistory = (updateFlags & IResource.KEEP_HISTORY) != 0; if (keepHistory) { tree.addToLocalHistory(file); } return deleteHgFiles(tree, file, monitor); } public boolean deleteFolder(IResourceTree tree, IFolder folder, int updateFlags, IProgressMonitor monitor) { /* * Mercurial doesn't control directories. However, as a short cut * performing an operation on a folder will affect all subtending files. * Check that there is at least 1 file and if so there is Mercurial work * to do, otherwise there is no Mercurial work to be done. */ if (!folderHasMercurialFiles(folder, monitor) || folder.isLinked()) { return false; } /* * NOTE: There are bugs with Mercurial 0.9.1 on Windows and folder * delete/rename operation. See: * http://www.selenic.com/mercurial/bts/issue343, * http://www.selenic.com/mercurial/bts/issue303, etc. Returning false * indicates that the caller should invoke tree.standardDeleteFile to * actually remove the resource from the file system and eclipse. */ return deleteHgFiles(tree, folder, monitor); } /** * Perform the file or folder (ie multiple file) delete. * * @returns false if the action succeeds, true * otherwise. This syntax is to match the desired return code for * deleteFile and deleteFolder. */ private static boolean deleteHgFiles(IResourceTree tree, IResource resource, IProgressMonitor monitor) { // TODO: Decide if we should have different Hg behaviour based on the // force flag provided in updateFlags. try { // Delete the file(s) from the Mercurial repository. if(!resource.isLinked()) { HgRemoveClient.removeResource(resource, monitor); } } catch (HgException e) { MercurialEclipsePlugin.logError(e); return false; } // We removed the file ourselves, need to tell. if(resource.getType() == IResource.FOLDER) { tree.deletedFolder((IFolder) resource); } else if(resource.getType() == IResource.PROJECT){ tree.deletedProject((IProject) resource); } else{ // hg deletes the parent folder too if the deleted file was the only one in the folder // we have to tell Eclipse that the folder (and probably all subsequent parents) // are deleted too... File dir = ResourceUtils.getFileHandle(resource).getParentFile(); IContainer parent = resource.getParent(); tree.deletedFile((IFile) resource); while(parent instanceof IFolder && dir != null && !dir.exists()){ IContainer backup = parent.getParent(); tree.deletedFolder((IFolder) parent); parent = backup; dir = dir.getParentFile(); } } // Returning true indicates that this method has removed resource in both // the file system and eclipse. return true; } public boolean deleteProject(IResourceTree tree, final IProject project, int updateFlags, IProgressMonitor monitor) { if ((updateFlags & IResource.ALWAYS_DELETE_PROJECT_CONTENT) == 0) { disconnect(project); tree.deletedProject(project); return true; } boolean isPartOfRepo = isContainedInRepository(project); if(isPartOfRepo){ final Set allFiles = ResourceUtils.getMembers(project, false); allFiles.remove(project); try { HgRemoveClient.removeResources(new ArrayList(allFiles)); } catch (HgException e1) { MercurialEclipsePlugin.logWarning("Warnings encountered removing resources from repository", e1); // Usually deleting untracked resource } finally { try { MercurialStatusCache.getInstance().refreshStatus(project, monitor); } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } } final boolean [] continueDelete = new boolean[]{ false }; Display.getDefault().syncExec(new Runnable(){ public void run() { MessageDialog.openInformation(MercurialEclipsePlugin.getActiveShell(), "Project removed", "All project files are now removed from Mercurial repository.\n" + "A commit is highly recommended if you wish to keep using this repository."); CommitHandler ch = new CommitHandler(); Options options = new Options(); options.defaultCommitMessage = "Removed project '" + project.getName() + "' from repository."; options.filesSelectable = false; options.showAmend = false; options.showCloseBranch = false; options.showDiff = false; options.showRevert = false; ch.setOptions(options); try { ch.run(new ArrayList(allFiles)); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } continueDelete[0] = ch.getResult() == Window.OK; } }); if(continueDelete[0]){ disconnect(project); // if user committed deleted files, mercurial part is done // now we must say Eclipse please delete the project tree.deletedProject(project); } // delete was NOT done by hg. Anyway, let the files and project there. return true; } IFolder folder = project.getFolder(".hg"); //$NON-NLS-1$ try { folder.delete(updateFlags, monitor); disconnect(project); // say Eclipse it should do the delete of now unmanaged project files for us return false; } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return true; } } /** * @param project non null * @return true only if the project is located inside a (bigger) repository, * false if the project location equals repository location or unknown */ private static boolean isContainedInRepository(final IProject project) { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(project); if(hgRoot == null){ return false; } return !hgRoot.getIPath().equals(project.getLocation()); } /** * @param project non null */ private static void disconnect(final IProject project) { if (RepositoryProvider.isShared(project)) { try { RepositoryProvider.unmap(project); } catch (TeamException e) { MercurialEclipsePlugin.logError(e); } } } /** * @see org.eclipse.core.resources.team.IMoveDeleteHook#moveFile(org.eclipse.core.resources.team.IResourceTree, org.eclipse.core.resources.IFile, org.eclipse.core.resources.IFile, int, org.eclipse.core.runtime.IProgressMonitor) */ public boolean moveFile(IResourceTree tree, IFile source, IFile destination, int updateFlags, IProgressMonitor monitor) { if (!isInMercurialRepo(source, monitor) || !isSameRoot(source, destination)) { return false; } boolean keepHistory = (updateFlags & IResource.KEEP_HISTORY) != 0; if (keepHistory) { tree.addToLocalHistory(source); } // Move the file in the Mercurial repository. if (!moveHgFiles(source, destination, monitor)) { return true; } // We moved the file ourselves, need to tell. tree.movedFile(source, destination); tree.updateMovedFileTimestamp(destination, tree.computeTimestamp(destination)); // Returning true indicates that this method has moved resource in both // the file system and eclipse. return true; } /** * @see org.eclipse.core.resources.team.IMoveDeleteHook#moveFolder(org.eclipse.core.resources.team.IResourceTree, org.eclipse.core.resources.IFolder, org.eclipse.core.resources.IFolder, int, org.eclipse.core.runtime.IProgressMonitor) */ public boolean moveFolder(IResourceTree tree, IFolder source, IFolder destination, int updateFlags, IProgressMonitor monitor) { /* * Mercurial doesn't control directories. However, as a short cut * performing an operation on a folder will affect all subtending files. * Check that there is at least 1 file and if so there is Mercurial work * to do, otherwise there is no Mercurial work to be done. */ if (!folderHasMercurialFiles(source, monitor) || source.isLinked() || !isSameRoot(source, destination)) { return false; } // Move the folder (ie all subtending files) in the Mercurial // repository. if (!moveHgFiles(source, destination, monitor)) { //the move could have been partially successful, so refresh to ensure we are in sync try { source.refreshLocal(IResource.DEPTH_INFINITE, null); destination.refreshLocal(IResource.DEPTH_INFINITE, null); } catch (CoreException e) { //ignore secondary failures -we have already logged main failure } return true; } // We moved the file ourselves, need to tell. tree.movedFolderSubtree(source, destination); boolean isDeep = (updateFlags & IResource.SHALLOW) == 0; updateTimestamps(destination, isDeep, tree); // Returning true indicates that this method has moved resource in both // the file system and eclipse. return true; } private static boolean isSameRoot(IResource source, IResource dest) { MercurialRootCache cache = MercurialRootCache.getInstance(); HgRoot root = cache.getHgRoot(source); return root != null && root.equals(cache.hasHgRoot(dest, true)); } /** * Move the file or folder (ie multiple file). * * @returns true if the action succeeds, false * otherwise. */ private static boolean moveHgFiles(IResource source, IResource destination, IProgressMonitor monitor) { // Rename the file in the Mercurial repository. // TODO: Decide if we should have different Hg behavior based on the // force flag provided in updateFlags. try { HgRoot hgRoot = MercurialRootCache.getInstance().getHgRoot(source); IPath from = ResourceUtils.getPath(source); IPath to = ResourceUtils.getPath(destination); HgRenameClient.renameResource(from, to, hgRoot, monitor); } catch (final HgException e) { MercurialEclipsePlugin.logError(e); if (MercurialUtilities.isWindows() && source.getName().equalsIgnoreCase(destination.getName())) { try { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(source); List res = new ArrayList(); res.add(source); HgRevertClient.performRevert(monitor, hgRoot, res, null); } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); } HgException ex = new HgException( "Mercurial does not support renaming of files on Windows," + " if file names differs only by the lower/upper case letters!", e); MercurialEclipsePlugin.showError(ex); } return false; } return true; } /** * @see org.eclipse.core.resources.team.IMoveDeleteHook#moveProject(org.eclipse.core.resources.team.IResourceTree, org.eclipse.core.resources.IProject, org.eclipse.core.resources.IProjectDescription, int, org.eclipse.core.runtime.IProgressMonitor) */ public boolean moveProject(IResourceTree tree, final IProject source, IProjectDescription description, int flags, IProgressMonitor monitor) { // two cases: 1) project containing the repo or 2) project contained in the repo // for 1) we need to clean the cache // for the 2) we need to move if the project is relocated (not just renamed) boolean isPartOfRepo = isContainedInRepository(source); if(!isPartOfRepo) { // Eclipse will simply move *entire* repository by itself and change project name in .project file MercurialStatusCache.getInstance().clear(source, false); MercurialRootCache.getInstance().projectDeletedOrClosed(source); return false; } // project is located inside a (bigger) repository boolean locationChanged = isLocationChanged(source, description); if(!locationChanged) { // Don't care - only .project file will be changed due the name change return false; } // move all project related files inside a bigger hg repository final HgRoot hgRoot = MercurialRootCache.getInstance().getHgRoot(source); IPath from = source.getLocation(); try { IPath to = computeDestination(description); HgRenameClient.renameResource(from, to, hgRoot, monitor); final boolean [] commitDone = new boolean[]{ false }; Display.getDefault().syncExec(new Runnable(){ public void run() { boolean commitNow = MessageDialog.openConfirm( MercurialEclipsePlugin.getActiveShell(), "Project moved", "All project files are now moved inside the Mercurial repository.\n" + "A commit NOW is highly recommended!\n" + "(otherwise you would need command line to commit removed files).\n\n" + "Commit ALL changed files NOW?"); if(commitNow) { CommitHandler ch = new CommitHandler(); Options options = new Options(); options.defaultCommitMessage = "Moved project '" + source.getName() + "'."; options.filesSelectable = false; options.showAmend = false; options.showCloseBranch = false; options.showDiff = false; options.showRevert = false; options.allowEmptyCommit = true; options.hgRoot = hgRoot; ch.setOptions(options); try { ch.run(new ArrayList()); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } commitDone[0] = ch.getResult() == Window.OK; } } }); if (tree.movedProjectSubtree(source, description)) { if (!commitDone[0]) { Display.getDefault().syncExec(new Runnable() { public void run() { MessageDialog.openInformation( MercurialEclipsePlugin.getActiveShell(), "Project moved", "Source files are marked for delete but still not committed.\n" + "As the Eclipse project doesn't exist anymore at the original location, " + "please consider to commit from the command line."); } }); } boolean isDeep = (flags & IResource.SHALLOW) == 0; IProject destination = source.getWorkspace().getRoot().getProject(description.getName()); updateTimestamps(destination, isDeep, tree); return true; } } catch (Exception e) { MercurialEclipsePlugin.logError(e); } finally { new RefreshStatusJob("Updating cache", hgRoot).schedule(300); } return false; } private static IPath computeDestination(IProjectDescription description) throws CoreException { URI destLocation = description.getLocationURI(); // Use the default area if necessary for the destination. if (destLocation == null) { IPath rootLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation(); destLocation = rootLocation.append(description.getName()).toFile().toURI(); } IFileStore store = EFS.getStore(destLocation); File localFile = store.toLocalFile(0, null); return new Path(localFile.getAbsolutePath()); } private static boolean isLocationChanged(IProject source, IProjectDescription description) { boolean locationChanged = false; try { URI srcURI = source.getDescription().getLocationURI(); URI targetURI = description.getLocationURI(); if(srcURI != null) { // easy: location was outside the workspace, so just compare with future location locationChanged = !srcURI.equals(targetURI); } else { if(targetURI != null) { // project was inside workspace now outside locationChanged = true; } else { // both uri's are null: means that project was and will be located at default // location (workspace), so the real OS location is changed // if the project name is changed locationChanged = !source.getName().equals(description.getName()); } } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } return locationChanged; } /** * Helper method to update all the timestamps in the tree to match * those in the file system. Used after a #move. */ private static void updateTimestamps(IResource root, final boolean isDeep, final IResourceTree tree) { IResourceVisitor visitor = new IResourceVisitor() { public boolean visit(IResource resource) { if (resource.isLinked()) { if (isDeep) { //clear the linked resource bit, if any ResourceInfo info = ((Resource) resource).getResourceInfo(false, true); info.clear(ICoreConstants.M_LINK); } return true; } //only needed if underlying file system does not preserve timestamps if (resource.getType() == IResource.FILE) { IFile file = (IFile) resource; tree.updateMovedFileTimestamp(file, tree.computeTimestamp(file)); } return true; } }; try { root.accept(visitor, IResource.DEPTH_INFINITE, IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS | IContainer.INCLUDE_HIDDEN); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } } MercurialConfigurationWizard.java000066400000000000000000000166251173713500500357500ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Software Balm Consulting Inc (Peter Hunnisett ) - some updates * Stefan Groschupf - logError * Stefan C - Code cleanup * Bastian Doetsch - make map operation asynchronous * Andrei Loskutov - bug fixes *******************************************************************************/ /** * Mercurial create Wizard * * This wizard will will create a mercurial repository if there is no one yet, or simply * map the project with the Mercurial team provider * * It will follow the dirictory chain to the bottom to se is * there is a .hg directory someware, is so it will suggest that you use it * instead of creating a new repository. */ package com.vectrace.MercurialEclipse.team; import java.io.File; import java.util.Properties; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.wizard.Wizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Text; import org.eclipse.team.ui.IConfigurationWizard; import org.eclipse.ui.IWorkbench; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgRootClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.InitOperation; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.wizards.ConfigurationWizardMainPage; import com.vectrace.MercurialEclipse.wizards.NewLocationWizard; /** * @author zingo */ public class MercurialConfigurationWizard extends Wizard implements IConfigurationWizard { private class NewWizardPage extends WizardPage implements SelectionListener { private Button restoreProjectDirButton; private Button restoreExistingDirButton; private final boolean newMercurialRoot; private Link link; NewWizardPage(boolean newMercurialRoot) { super(WizardPage.class.getName()); this.newMercurialRoot = newMercurialRoot; if (newMercurialRoot) { setTitle(Messages.getString("MercurialConfigurationWizard.titleNew")); //$NON-NLS-1$ setDescription(Messages.getString("MercurialConfigurationWizard.descriptionNew")); //$NON-NLS-1$ } else { setTitle(Messages.getString("MercurialConfigurationWizard.titleExisting")); //$NON-NLS-1$ setDescription("An existing Mercurial repository was found in the parent directory. " + "Please choose which repository should be connected with the project."); } setPageComplete(true); } public void createControl(final Composite parent) { Composite mainControl = new Composite(parent, SWT.NONE); mainControl.setLayout(new GridLayout(2, false)); Label label = new Label(mainControl, SWT.CENTER); label.setText(Messages.getString("MercurialConfigurationWizard.selectDirectory")); //$NON-NLS-1$ directoryText = new Text(mainControl, SWT.BORDER); directoryText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); directoryText.setText(hgPath); directoryText.setEditable(false); if (!newMercurialRoot) { Group buttonsPanel = new Group(mainControl, SWT.NONE); buttonsPanel.setText("Choose the Mercurial repository to connect the project with"); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); buttonsPanel.setLayout(new GridLayout(1, false)); gridData.horizontalSpan = 2; buttonsPanel.setLayoutData(gridData); restoreExistingDirButton = new Button(buttonsPanel, SWT.CENTER | SWT.RADIO); restoreExistingDirButton.setText(Messages.getString("MercurialConfigurationWizard.useExistingHgDir")); //$NON-NLS-1$ restoreProjectDirButton = new Button(buttonsPanel, SWT.CENTER | SWT.RADIO); restoreProjectDirButton.setText(Messages.getString("MercurialConfigurationWizard.useProjectRoot")); //$NON-NLS-1$ restoreExistingDirButton.setSelection(true); restoreProjectDirButton.addSelectionListener(this); restoreExistingDirButton.addSelectionListener(this); } link = new Link(mainControl, SWT.NONE); GridData gridData = new GridData(); gridData.horizontalSpan = 2; link.setLayoutData(gridData); link.setText("Create new Mercurial repository at another location..."); link.addSelectionListener(this); setControl(mainControl); setPageComplete(true); } public void widgetSelected(SelectionEvent e) { if (e.widget == link){ NewLocationWizard wizard = new NewLocationWizard(); Properties properties = new Properties(); properties.setProperty(ConfigurationWizardMainPage.PROP_URL, hgPath); wizard.setProperties(properties); getShell().close(); WizardDialog dialog = new WizardDialog(MercurialEclipsePlugin.getActiveShell(), wizard); dialog.open(); } else if (e.widget == restoreProjectDirButton){ hgPath = ResourceUtils.getPath(project).toOSString(); directoryText.setText(hgPath); }else if (e.widget == restoreExistingDirButton){ hgPath = foundhgPath.getAbsolutePath(); directoryText.setText(hgPath); } } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } } private IProject project; private String hgPath; private Text directoryText; private NewWizardPage page; private HgRoot foundhgPath; public MercurialConfigurationWizard() { setWindowTitle(Messages.getString("MercurialConfigurationWizard.wizardTitle")); //$NON-NLS-1$ setNeedsProgressMonitor(true); } @Override public void addPages() { foundhgPath = MercurialTeamProvider.hasHgRoot(project); IPath path = ResourceUtils.getPath(project); if(foundhgPath == null) { try { foundhgPath = HgRootClient.getHgRoot(path.toFile()); } catch (HgException e) { // ignore, we just looking for a *possible* root } } if (foundhgPath == null || foundhgPath.getIPath().equals(path)) { hgPath = path.toOSString(); page = new NewWizardPage(true); } else { hgPath = foundhgPath.getAbsolutePath(); page = new NewWizardPage(false); } addPage(page); } @Override public boolean performFinish() { if (directoryText != null) { hgPath = directoryText.getText(); } try { getContainer().run(true, true, new InitOperation(getContainer(), project, new File(hgPath))); } catch (Exception e) { MercurialEclipsePlugin.logError(e); page.setErrorMessage(e.getMessage()); return false; } return true; } public void init(IWorkbench workbench, IProject proj) { this.project = proj; if (!MercurialUtilities.isHgExecutableCallable()) { MercurialUtilities.configureHgExecutable(); } } } MercurialProjectSetCapability.java000066400000000000000000000124421173713500500360350ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/** * /******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - Implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.net.URI; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.team.core.ProjectSetCapability; import org.eclipse.team.core.ProjectSetSerializationContext; import org.eclipse.team.core.TeamException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.AddToWorkspaceAction; import com.vectrace.MercurialEclipse.commands.HgPathsClient; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * Defines ProjectSetCapabilities for MercurialEclipse * * @author Bastian Doetsch */ public class MercurialProjectSetCapability extends ProjectSetCapability { public static final String SEPARATOR = "|"; private static MercurialProjectSetCapability instance; @Override public String[] asReference(IProject[] providerProjects, ProjectSetSerializationContext context, IProgressMonitor monitor) throws TeamException { try { String[] references = new String[providerProjects.length]; monitor .beginTask( Messages .getString("MercurialProjectSetCapability.determiningProjectReferences"), //$NON-NLS-1$ providerProjects.length); for (int i = 0; i < providerProjects.length; i++) { String reference = asReference(null, providerProjects[i] .getName()); if (!(monitor.isCanceled() || reference == null)) { references[i] = reference; } else { String msg; if (monitor.isCanceled()) { msg = Messages .getString("MercurialProjectSetCapability.cancelled"); //$NON-NLS-1$ } else { msg = Messages .getString("MercurialProjectSetCapability.notDeterminable") //$NON-NLS-1$ + providerProjects[i]; } throw new TeamException(msg); } } return references; } finally { monitor.done(); } } @Override public IProject[] addToWorkspace(String[] referenceStrings, ProjectSetSerializationContext context, IProgressMonitor monitor) throws TeamException { // use AddToWorkspaceAction to decouple adding from other workspace // tasks. AddToWorkspaceAction action = new AddToWorkspaceAction(); // our beloved projects from the import file action.setReferenceStrings(referenceStrings); try { action.run(monitor); } catch (Exception e) { MessageDialog .openError( MercurialEclipsePlugin.getStandardDisplay().getActiveShell(), Messages.getString("MercurialProjectSetCapability.errorWhileImporting"), e.getMessage()); //$NON-NLS-1$ } return action.getProjectsCreated(); } @Override public String asReference(URI uri, String projectName) { String reference = null; try { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IProject project = workspace.getRoot().getProject(projectName); HgRoot hgRoot = MercurialTeamProvider.getHgRoot(project); String srcRepository = ""; //$NON-NLS-1$ Map locs = HgPathsClient.getPaths(hgRoot); if (locs.containsKey(HgPathsClient.DEFAULT_PULL)) { srcRepository = locs.get(HgPathsClient.DEFAULT_PULL); } else if (locs.containsKey(HgPathsClient.DEFAULT)) { srcRepository = locs.get(HgPathsClient.DEFAULT); } else { srcRepository = hgRoot.getAbsolutePath(); } if (srcRepository != null && srcRepository.length() > 0) { reference = "MercurialEclipseProjectSet" + SEPARATOR + project.getName() + SEPARATOR + srcRepository; IPath path = ResourceUtils.getPath(project); if(!hgRoot.getIPath().equals(path)){ reference += SEPARATOR + hgRoot.toRelative(path.toFile()); } } } catch (CoreException e) { // reference is null -> error condition } return reference; } @Override public String getProject(String referenceString) { String[] split = referenceString.split("\\" + SEPARATOR); if(split.length > 1){ return split[1]; } return null; } public String getPullRepo(String referenceString) { String[] split = referenceString.split("\\" + SEPARATOR); if(split.length > 2){ return split[2]; } return null; } public String getRootRelativePath(String referenceString) { String[] split = referenceString.split("\\" + SEPARATOR); if(split.length > 3){ return split[3]; } return null; } /** * Singleton accessor method. */ public static MercurialProjectSetCapability getInstance() { if (instance == null) { instance = new MercurialProjectSetCapability(); } return instance; } } MercurialRevisionStorage.java000066400000000000000000000264511173713500500351010ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/******************************************************************************* * Copyright (c) 2006-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan C - Code cleanup * Bastian Doetsch - additions for sync * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IStorage; import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgCatClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.model.HgFile; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; /** * @author zingo * * This is a IStorage subclass that can handle file revision * @deprecated due to lacking full support of representing file and folder structure in Hg revision. * Replaced by {@link HgFile}. * To convert to HgFile see ResourceUtils.convertToHgFile(MercurialRevisionStorage rev). */ @Deprecated public class MercurialRevisionStorage implements IStorage { private static final ByteArrayInputStream EMPTY_STREAM = new ByteArrayInputStream(new byte[0]); private int revision; private String global; private final IFile resource; protected ChangeSet changeSet; protected ContentHolder content; private File parent; protected class ContentHolder { private final byte[] bytes; private final Throwable error; private ContentHolder(byte [] b, Throwable t) { bytes = b; error = t; } public ContentHolder(byte [] bytes) { this(bytes, null); } public ContentHolder(Throwable t) { this(null, t); } public InputStream createStream() { if (bytes != null) { return new ByteArrayInputStream(bytes); } else { return EMPTY_STREAM; } } } /** * The recommended constructor to use is MercurialRevisionStorage(IResource res, String rev, String global, * ChangeSet cs) * */ public MercurialRevisionStorage(IFile res, String changeset) { super(); resource = res; try { if(changeset != null) { this.changeSet = LocalChangesetCache.getInstance().getOrFetchChangeSetById(res, changeset); } if(changeSet != null){ this.revision = changeSet.getChangesetIndex(); this.global = changeSet.getChangeset(); } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } /** * Constructs a new MercurialRevisionStorage with the given params. * * @param res * the resource for which we want an IStorage revision * @param rev * the changeset index as string * @param global * the global hash identifier * @param cs * the changeset object */ public MercurialRevisionStorage(IFile res, int rev, String global, ChangeSet cs) { super(); this.revision = rev; this.global = global; this.resource = res; this.changeSet = cs; } /** * Constructs an {@link MercurialRevisionStorage} with the newest local changeset available. * * @param res * the resource */ public MercurialRevisionStorage(IFile res) { super(); this.resource = res; ChangeSet cs = null; try { cs = LocalChangesetCache.getInstance().getChangesetByRootId(res); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } if(cs != null){ this.revision = cs.getChangesetIndex(); // should be fetched // from id this.global = cs.getChangeset(); } this.changeSet = cs; } /** * @param parent the parent (ancestor file name before rename/copy), might be null */ public void setParent(File parent) { this.parent = parent; } @SuppressWarnings("rawtypes") public Object getAdapter(Class adapter) { if (adapter.equals(IResource.class)) { return resource; } return null; } /** * Generate data content of the so called "file" in this case a revision, e.g. a hg cat --rev "rev" %file% *

* {@inheritDoc} */ public InputStream getContents() throws CoreException { if(content != null){ return content.createStream(); } try { IFile file = resource.getProject().getFile(resource.getProjectRelativePath()); content = fetchContent(file); } catch (CoreException e) { if(parent != null){ IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation( new Path(parent.getAbsolutePath())); try { content = fetchContent(file); return content.createStream(); } catch (CoreException e2) { e = e2; } } content = new ContentHolder(e); // core API ignores exceptions from this method, so we need to log them here MercurialEclipsePlugin.logWarning("Failed to get revision content for " + toString(), e); throw e; } return content.createStream(); } private ContentHolder fetchContent(IFile file) throws CoreException { if (changeSet == null) { // no changeset known return new ContentHolder(HgCatClient.getContent(file, null)); } byte[] result = null; // Setup and run command if (changeSet.getDirection() == Direction.INCOMING && changeSet.getBundleFile() != null) { // incoming: overlay repository with bundle and extract then via cat try { result = HgCatClient.getContentFromBundle(file, changeSet.getRevision().getChangeset(), changeSet.getBundleFile()); } catch (IOException e) { throw new HgException("Unable to determine canonical path for " + changeSet.getBundleFile(), e); } } else { // local: get the contents via cat if(file.exists() && MercurialStatusCache.getInstance().isUnknown(file)){ // for existing but unknown files, simply return dummy content return new ContentHolder((byte[]) null); } result = HgCatClient.getContent(file, Integer.valueOf(changeSet.getChangesetIndex()).toString()); } return new ContentHolder(result); } public IPath getFullPath() { return resource.getFullPath().append(revision != 0 ? (" [" + revision + "]") //$NON-NLS-1$ //$NON-NLS-2$ : Messages.getString("MercurialRevisionStorage.parentChangeset")); //$NON-NLS-1$ } public String getName() { // the getContents() call below is a workaround for the fact that the core API // seems to ignore the failures in getContents() and do not update the storage name // in this case. So we just call getContents (which result is buffered in any case) // here, and remember the possible error. try { getContents(); } catch (CoreException e) { content = new ContentHolder(e); } String name; if (changeSet != null) { name = resource.getName() + " [" + changeSet.toString() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } else { name = resource.getName(); } if(content.error != null){ String message = content.error.getMessage(); if (message.indexOf('\n') > 0) { // name = message + ", " + name; name = message.substring(0, message.indexOf('\n')); } else { name = message; } } return name; } public int getRevision() { return revision; } /** * You can't write to other revisions then the current selected e.g. ReadOnly */ public boolean isReadOnly() { if (revision != 0) { return true; } // if no revision resource is the current one e.g. editable :) ResourceAttributes attributes = resource.getResourceAttributes(); if (attributes != null) { return attributes.isReadOnly(); } return true; /* unknown state marked as read only for safety */ } public IFile getResource() { return resource; } public String getGlobal() { return global; } /** * @return the changeSet */ public ChangeSet getChangeSet() { return changeSet; } /** * This constructor is not recommended, as the revision index is not unique when working with other than the local * repository. * * @param res * @param rev */ public MercurialRevisionStorage(IFile res, int rev) { super(); resource = res; if(rev < 0){ return; } try { // hoping the cache is up-to-date!!! LocalChangesetCache cache = LocalChangesetCache.getInstance(); HgRoot hgRoot = MercurialTeamProvider.getHgRoot(res); if (hgRoot == null) { return; // TODO returning incompletely initialized object is not reliable! } ChangeSet tip = cache.getNewestChangeSet(hgRoot); boolean localKnown = tip.getChangesetIndex() >= rev; if (!localKnown) { return; } this.changeSet = cache.getOrFetchChangeSetById(res, String.valueOf(rev)); if (changeSet != null) { this.revision = changeSet.getChangesetIndex(); this.global = changeSet.getChangeset(); } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Hg revision ["); if (changeSet != null) { builder.append("changeSet="); builder.append(changeSet); builder.append(", "); } if (revision != 0) { builder.append("revision="); builder.append(revision); builder.append(", "); } if (global != null) { builder.append("global="); builder.append(global); builder.append(", "); } if (resource != null) { builder.append("resource="); builder.append(resource); builder.append(", "); } if (parent != null) { builder.append("parent="); builder.append(parent); builder.append(", "); } builder.append("]"); return builder.toString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((global == null) ? 0 : global.hashCode()); result = prime * result + ((parent == null) ? 0 : parent.hashCode()); result = prime * result + ((resource == null) ? 0 : resource.hashCode()); result = prime * result + revision; return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } MercurialRevisionStorage other = (MercurialRevisionStorage) obj; if (global == null) { if (other.global != null) { return false; } } else if (!global.equals(other.global)) { return false; } if (parent == null) { if (other.parent != null) { return false; } } else if (!parent.equals(other.parent)) { return false; } if (resource == null) { if (other.resource != null) { return false; } } else if (!resource.getFullPath().equals(other.resource.getFullPath())) { return false; } if (revision != other.revision) { return false; } return true; } } MercurialTeamProvider.java000066400000000000000000000375431173713500500343630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Software Balm Consulting Inc (Peter Hunnisett ) - some updates * StefanC - some updates * Bastian Doetsch - new qualified name for project sets * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - Fix encoding *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceRuleFactory; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.team.IMoveDeleteHook; import org.eclipse.core.resources.team.ResourceRuleFactory; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.Team; import org.eclipse.team.core.history.IFileHistoryProvider; import org.eclipse.ui.IPropertyListener; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgBranchClient; import com.vectrace.MercurialEclipse.commands.HgDebugInstallClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.MercurialHistoryProvider; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgResource; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.team.cache.HgRootRule; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.RefreshStatusJob; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author zingo */ public class MercurialTeamProvider extends RepositoryProvider { public static final String ID = "com.vectrace.MercurialEclipse.team.MercurialTeamProvider"; //$NON-NLS-1$ /** key is hg root, value is the *current* branch */ private static final Map BRANCH_MAP = new ConcurrentHashMap(); private MercurialHistoryProvider fileHistoryProvider; private static final ListenerList BRANCH_LISTENERS = new ListenerList(ListenerList.IDENTITY); /** @see #getRuleFactory() */ private IResourceRuleFactory resourceRuleFactory; public MercurialTeamProvider() { super(); } /** * * @return never null, list of all projects already known to be contained in a hg root and * managed by this team provider */ public static List getKnownHgProjects(){ List projects = new ArrayList(); IProject[] iProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject project : iProjects) { if(isHgTeamProviderFor(project)){ projects.add(project); } } return projects; } /** * * @return never null, list of all projects already known to be contained in the given hg root * and managed by this team provider */ public static List getKnownHgProjects(HgRoot hgRoot){ List hgProjects = getKnownHgProjects(); List projects = new ArrayList(); for (IProject project : hgProjects) { if(hgRoot.equals(hasHgRoot(project))){ projects.add(project); } } return projects; } @Override public void setProject(IProject project) { super.setProject(project); try { configureProject(); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } @Override public void configureProject() throws CoreException { IProject project = getProject(); HgRoot hgRoot = MercurialRootCache.getInstance().getHgRoot(project); if(hgRoot == null) { String msg = "No hg repository found for project '" + project.getName() + "', " + "located at: " + project.getLocation(); throw new CoreException(MercurialEclipsePlugin.createStatus( msg, 0, IStatus.ERROR, new IllegalStateException(msg))); } setRepositoryEncoding(project, hgRoot); // try to find .hg directory to set it as private member final IResource hgDir = project.getFolder(".hg"); //$NON-NLS-1$ if (hgDir != null) { setTeamPrivate(hgDir); } if(!MercurialStatusCache.getInstance().isStatusKnown(project)) { new RefreshStatusJob("Initializing hg cache for: " + hgRoot.getName(), project, hgRoot) .schedule(50); } if(MercurialEclipsePlugin.getRepoManager().getAllRepoLocations(hgRoot).isEmpty()){ loadRootRepos(hgRoot); } } private static void setTeamPrivate(final IResource hgDir) throws CoreException { if (!hgDir.exists()) { if (ResourceUtils.getFileHandle(hgDir).exists()) { Job refreshJob = new Job("Refreshing .hg folder") { @Override protected IStatus run(IProgressMonitor monitor) { try { hgDir.refreshLocal(IResource.DEPTH_ZERO, monitor); if (hgDir.exists() && !hgDir.isTeamPrivateMember()) { hgDir.setTeamPrivateMember(true); hgDir.setDerived(true); } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } return Status.OK_STATUS; } }; refreshJob.schedule(); } else { // Not a .hg repository - ignore } } else if (!hgDir.isTeamPrivateMember()) { hgDir.setTeamPrivateMember(true); hgDir.setDerived(true); } } /** * @param hgRoot non null */ private static void loadRootRepos(final HgRoot hgRoot) { Job job = new Job("Reading root repositories") { @Override protected IStatus run(IProgressMonitor monitor) { HgRepositoryLocationManager repoManager = MercurialEclipsePlugin.getRepoManager(); if(!repoManager.getAllRepoLocations(hgRoot).isEmpty()){ return Status.OK_STATUS; } try { repoManager.loadRepos(hgRoot); } catch (HgException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } return Status.OK_STATUS; } @Override public boolean shouldSchedule() { return MercurialEclipsePlugin.getRepoManager().getAllRepoLocations(hgRoot) .isEmpty(); } }; job.setSystem(true); job.setRule(new HgRootRule(hgRoot)); job.schedule(100); } public void deconfigure() throws CoreException { IProject project = getProject(); Assert.isNotNull(project); // cleanup MercurialStatusCache.getInstance().clear(project, false); MercurialRootCache.getInstance().projectDeletedOrClosed(project); } /** * Checks if the given project is already controlled by MercurialEclipse * as team provider. This method does not access any locks and so can be called * from synchronized code. * * @param project * non null * @return true, if MercurialEclipse provides team functions to this project, false otherwise * (if an error occurred or project is closed). */ public static boolean isHgTeamProviderFor(IProject project){ return project instanceof IHgResource || MercurialRootCache.isHgTeamProviderFor(project); } /** * Checks if the given resource is controlled by MercurialEclipse. If the given resource is * linked, it is possibly not controlled by MercurialEclipse and therefore false can be returned. A linked * file is followed only if it is contained inside the same hg root as the project. * * @return true, if MercurialEclipse provides team functions to this resource, false otherwise. */ public static boolean isHgTeamProviderFor(IResource resource) { // check, if we're team provider if (resource == null) { return false; } IProject project = resource.getProject(); if (project == null || !isHgTeamProviderFor(project)) { return false; } // if we are team provider, this project can't be linked :-). if (resource instanceof IProject || resource instanceof IHgResource) { return true; } // TODO: The .hg folder should always be team private, but support for this is not // implemented for repositories not at project root. if ((resource instanceof IFolder && ".hg".equals(resource.getName())) || resource.isTeamPrivateMember()) { return false; } // If the ignore/derived hints from Eclipse should be ignored: set to true // as Team.isIgnoredHint() assumes that every "derived" file is ignored. // Unfortunately this is not always true. It is not usual, but it may // happen that somebody committed some files under the "derived" path. // In this case it would be impossible to revert/commit delete of such files from Eclipse. boolean ignoreEclipseIgnoredAndDerived = true; if(!ignoreEclipseIgnoredAndDerived) { // Should not check ignored status for directories which may contain NOT ignored files... // http://code.google.com/a/eclipselabs.org/p/mercurialeclipse/issues/detail?id=28 if(resource instanceof IFile) { boolean ignored = Team.isIgnoredHint(resource); if(ignored) { return false; } } } // Check to se if resource is not in a link boolean isLinked = resource.isLinked(IResource.CHECK_ANCESTORS); if(!isLinked) { return true; } // Follow links and see if they point to another repository IResource realLocation = ResourceUtils.getRealLocation(resource); if(realLocation == null) { return false; } HgRoot hgRoot = hasHgRoot(realLocation.getProject()); return hgRoot != null; } public static void addBranchListener(IPropertyListener listener){ BRANCH_LISTENERS.add(listener); } public static void removeBranchListener(IPropertyListener listener){ BRANCH_LISTENERS.remove(listener); } private static void setRepositoryEncoding(IProject project, final HgRoot hgRoot) { // if a user EXPLICITLY states he wants a certain encoding // in a project, we should respect it (if its supported) final String defaultCharset; try { defaultCharset = project.getDefaultCharset(); if (!Charset.isSupported(defaultCharset)) { return; } } catch (CoreException ex) { MercurialEclipsePlugin.logError(ex); return; } // This code is running on very beginning of the eclipse startup. ALWAYS run // hg commands in a job, to avoid deadlocks of Eclipse at this point of time! // Deadlocks seen already: if running in UI thread, or if running inside the // lock acquired by the RepositoryProvider.mapExistingProvider Job job = new Job("Changeset detection") { @Override protected IStatus run(IProgressMonitor monitor) { if (HgDebugInstallClient.hgSupportsEncoding(defaultCharset)) { hgRoot.setEncoding(defaultCharset); } monitor.done(); return Status.OK_STATUS; } @Override public boolean shouldSchedule() { Boolean supports = HgDebugInstallClient.ENCODINGS.get(defaultCharset); if(supports != null && supports.booleanValue()){ hgRoot.setEncoding(defaultCharset); } return supports == null; } }; class CharsetRule implements ISchedulingRule { private final String cs; CharsetRule(String cs){ this.cs = cs; } public boolean isConflicting(ISchedulingRule rule) { return contains(rule); } public boolean contains(ISchedulingRule rule) { return rule instanceof CharsetRule && cs.equals(((CharsetRule) rule).cs); } } job.setRule(new CharsetRule(defaultCharset)); job.setSystem(true); job.schedule(); } /** * Gets the hg root of a resource as {@link java.io.File}. * * @param resource * the resource to get the hg root for, not null * @return the {@link java.io.File} referencing the hg root directory. May return null */ public static HgRoot getHgRoot(IResource resource) { if(resource == null){ return null; } return MercurialRootCache.getInstance().getHgRoot(resource); } /** * Gets the hg root of a resource as {@link java.io.File}. * * @param project * the project to get the hg root for, not null * @return the {@link java.io.File} referencing the hg root directory */ public static HgRoot getHgRoot(IProject project) { return MercurialRootCache.getInstance().getHgRoot(project); } /** * Gets the already known hg root of a resource as {@link java.io.File}. *

* Note: this method do NOT tries to find/configure not yet known hg roots. * * @param resource * the resource to get the hg root for, can be null * @return the {@link java.io.File} referencing the hg root directory, or null if no hg root * can't be found or the project is not configured yet with Mercurial team provider */ public static HgRoot hasHgRoot(IResource resource) { if(resource == null || resource instanceof IWorkspaceRoot){ return null; } return MercurialRootCache.getInstance().hasHgRoot(resource, true); } /** * @param hgRoot non null * @return current root branch, never null. */ public static String getCurrentBranch(HgRoot hgRoot){ Assert.isNotNull(hgRoot); String branch = BRANCH_MAP.get(hgRoot); if(branch == null){ try { branch = HgBranchClient.getActiveBranch(hgRoot); BRANCH_MAP.put(hgRoot, branch); } catch (HgException e) { MercurialEclipsePlugin.logError(e); return Branch.DEFAULT; } } return branch; } /** * @param res non null * @return current resource branch, never null. */ public static String getCurrentBranch(IResource res){ Assert.isNotNull(res); HgRoot hgRoot = getHgRoot(res); if(hgRoot == null){ return Branch.DEFAULT; } return getCurrentBranch(hgRoot); } /** * Set the root branch and notifies the branch listeners * @param branch current branch. If null is given, cache will be cleaned up * @param hgRoot non null */ public static void setCurrentBranch(String branch, HgRoot hgRoot){ Assert.isNotNull(hgRoot); String oldBranch = null; if(branch != null){ oldBranch = BRANCH_MAP.put(hgRoot, branch); } else { BRANCH_MAP.remove(hgRoot); } if(branch != null && !Branch.same(branch, oldBranch)){ Object[] listeners = BRANCH_LISTENERS.getListeners(); for (int i = 0; i < listeners.length; i++) { IPropertyListener listener = (IPropertyListener) listeners[i]; listener.propertyChanged(hgRoot, 0); } } } @Override public String getID() { return ID; } @Override public IMoveDeleteHook getMoveDeleteHook() { return new HgMoveDeleteHook(); } @Override public IFileHistoryProvider getFileHistoryProvider() { if (fileHistoryProvider == null) { fileHistoryProvider = new MercurialHistoryProvider(); } return fileHistoryProvider; } @Override public boolean canHandleLinkedResources() { return true; } @Override public boolean canHandleLinkedResourceURI() { return canHandleLinkedResources(); } /** * Overrides the default pessimistic resource rule factory which locks the workspace for all * operations. This causes problems when opening a project. This method returns the default * non-pessimistic resource rule factory which locks on a finer level. */ @Override public IResourceRuleFactory getRuleFactory() { if (resourceRuleFactory == null) { resourceRuleFactory = new ResourceRuleFactory() {}; } return resourceRuleFactory; } } MercurialTeamProviderType.java000066400000000000000000000017001173713500500352070ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - new qualified name for project sets *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.team.core.ProjectSetCapability; import org.eclipse.team.core.RepositoryProviderType; public class MercurialTeamProviderType extends RepositoryProviderType { public MercurialTeamProviderType() { } @Override public ProjectSetCapability getProjectSetCapability() { return MercurialProjectSetCapability.getInstance(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/MercurialUtilities.java000066400000000000000000000334501173713500500340050ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Software Balm Consulting Inc (Peter Hunnisett ) - some updates * StefanC - some updates * Stefan Groschupf - logError * Bastian Doetsch - updates, cleanup and documentation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.core.runtime.jobs.IJobManager; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.RGB; import org.eclipse.ui.dialogs.PreferencesUtil; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgConfigClient; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.utils.IniFile; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * Class that offers Utility methods for working with the plug-in. * * @author zingo * */ public final class MercurialUtilities { private static final boolean IS_WINDOWS = File.separatorChar == '\\'; private static final Map COLOR_MAP = new HashMap(); private static final Map FONT_MAP = new HashMap(); /** * This class is full of utilities metods, useful allover the place */ private MercurialUtilities() { // don't call me } public static boolean isWindows() { return IS_WINDOWS; } /** * Determines if the configured Mercurial executable can be called. * * @return true if no error occurred while calling the executable, false otherwise */ public static boolean isHgExecutableCallable() { try { Runtime.getRuntime().exec(getHGExecutable()); return true; } catch (IOException e) { return false; } } /** * Returns the hg executable stored in the plug-in preferences. If it's not defined, "hg" is * returned as default. * * @return the path to the executable or, if not defined "hg" * @deprecated Use {@link com.vectrace.MercurialEclipse.commands.HgClients#getExecutable()} */ @Deprecated public static String getHGExecutable() { return HgClients.getPreference(MercurialPreferenceConstants.MERCURIAL_EXECUTABLE, "hg"); //$NON-NLS-1$ } /** * Fetches a preference from the plug-in's preference store. If no preference could be found in * the store, the given default is returned. * * @param preferenceConstant * the string identifier for the constant. * @param defaultIfNotSet * the default to return if no preference was found. * @return the preference or the default */ public static String getPreference(String preferenceConstant, String defaultIfNotSet) { IPreferenceStore preferenceStore = MercurialEclipsePlugin.getDefault().getPreferenceStore(); // This returns "" if not defined String pref = preferenceStore.getString(preferenceConstant); if (pref.length() > 0) { return pref; } return defaultIfNotSet; } /** * Gets the configured executable if it's callable (@see * {@link MercurialUtilities#isHgExecutableCallable()}. * * If configureIfMissing is set to true, the configuration will be started and afterwards the * executable stored in the preferences will be checked if it is callable. If true, it is * returned, else "hg" will be returned. If the parameter is set to false, it will returns "hg" * if no preference is set. * * @param configureIfMissing * flag if configuration should be started if hg is not callable. * @return the hg executable path */ public static String getHGExecutable(boolean configureIfMissing) { if (isHgExecutableCallable()) { return getHGExecutable(); } if (configureIfMissing) { configureHgExecutable(); return getHGExecutable(); } return "hg"; //$NON-NLS-1$ } /** * Checks the GPG Executable is callable and returns it if it is. * * Otherwise, if configureIfMissing is set to true, configuration will be started and the new * command is tested for callability. If there's no preference found after configuration, "gpg" * will be returned as default. * * @param configureIfMissing * flag, if configuration should be started if gpg is not callable. * @return the gpg executable path */ public static String getGpgExecutable(boolean configureIfMissing) { if (isGpgExecutableCallable()) { return getGpgExecutable(); } if (configureIfMissing) { configureGpgExecutable(); return getGpgExecutable(); } return "gpg"; //$NON-NLS-1$ } /** * Starts configuration for Gpg executable by opening the preference page. */ public static void configureGpgExecutable() { configureHgExecutable(); } private static boolean isGpgExecutableCallable() { try { Runtime.getRuntime().exec(getGpgExecutable()); return true; } catch (Exception e) { return false; } } /** * Returns the executable for gpg. If it's not defined, false is returned * * @return gpg executable path or "gpg", if it's not set. */ public static String getGpgExecutable() { String executable = HgClients.getPreference(MercurialPreferenceConstants.GPG_EXECUTABLE, "gpg"); //$NON-NLS-1$ if (executable == null || executable.length() == 0) { return "false"; //$NON-NLS-1$ } return executable; } /** * Starts the configuration for Mercurial executable by opening the preference page. */ public static void configureHgExecutable() { final String jobName = Messages .getString("MercurialUtilities.openingPreferencesForConfiguringMercurialEclipse"); SafeUiJob job = new SafeUiJob(jobName) { @Override protected IStatus runSafe(IProgressMonitor monitor) { String pageId = "com.vectrace.MercurialEclipse.prefspage"; //$NON-NLS-1$ PreferenceDialog dlg = PreferencesUtil.createPreferenceDialogOn(getDisplay() .getActiveShell(), pageId, null, null); dlg.setErrorMessage(Messages .getString("MercurialUtilities.errorNotConfiguredCorrectly") //$NON-NLS-1$ + Messages.getString("MercurialUtilities.runDebugInstall")); //$NON-NLS-1$ dlg.open(); return super.runSafe(monitor); } @Override public boolean belongsTo(Object family) { return jobName.equals(family); } }; IJobManager jobManager = Job.getJobManager(); jobManager.cancel(jobName); Job[] jobs = jobManager.find(jobName); if (jobs.length == 0) { job.schedule(50); } } /** * Returns the username for hg as configured in preferences. If it's not defined in the * preference store, null is returned. *

* Note: Preferred way to access user commit name is to use * {@link HgCommitMessageManager#getDefaultCommitName(HgRoot)} * * @return hg username or empty string, never null */ public static String getDefaultUserName() { IPreferenceStore preferenceStore = MercurialEclipsePlugin.getDefault().getPreferenceStore(); // This returns "" if not defined String username = preferenceStore .getString(MercurialPreferenceConstants.MERCURIAL_USERNAME); // try to read username via hg showconfig if (StringUtils.isEmpty(username)) { try { username = HgConfigClient.getHgConfigLine("ui.username"); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } // try to read mercurial hgrc in default locations String home = System.getProperty("user.home"); if (StringUtils.isEmpty(username)) { username = readUsernameFromIni(home + "/.hgrc"); } if (isWindows()) { if (StringUtils.isEmpty(username)) { username = readUsernameFromIni(home + "/Mercurial.ini"); } if (StringUtils.isEmpty(username)) { username = readUsernameFromIni("C:/Mercurial/Mercurial.ini"); } } if (StringUtils.isEmpty(username)) { // use system username username = System.getProperty("user.name"); } // never return null! if (username == null) { username = ""; } return username; } private static String readUsernameFromIni(String filename) { String username; try { IniFile iniFile = new IniFile(filename); username = iniFile.getKeyValue("ui", "username"); } catch (FileNotFoundException e) { username = null; } return username; } public static boolean isCommandAvailable(String command, QualifiedName sessionPropertyName, String extensionEnabler) throws HgException { try { boolean returnValue; IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); Object prop = workspaceRoot.getSessionProperty(sessionPropertyName); if (prop != null) { returnValue = ((Boolean) prop).booleanValue(); } else { returnValue = AbstractClient.isCommandAvailable(command, extensionEnabler); workspaceRoot.setSessionProperty(sessionPropertyName, Boolean.valueOf(returnValue)); } return returnValue; } catch (CoreException e) { throw new HgException(e); } } public static Color getColorPreference(String pref) { RGB rgb = PreferenceConverter.getColor(MercurialEclipsePlugin.getDefault() .getPreferenceStore(), pref); return getColor(rgb); } public static Color getColor(RGB rgb) { Color color; synchronized (COLOR_MAP) { color = COLOR_MAP.get(rgb); if (color == null) { color = new Color(MercurialEclipsePlugin.getStandardDisplay(), rgb); COLOR_MAP.put(rgb, color); } } return color; } public static void disposeColorsAndFonts() { for (Color c : COLOR_MAP.values()) { c.dispose(); } COLOR_MAP.clear(); for (Font f : FONT_MAP.values()) { f.dispose(); } FONT_MAP.clear(); } public static Font getFont(FontData data) { Font font; synchronized (FONT_MAP) { font = FONT_MAP.get(data); if (font == null) { font = new Font(MercurialEclipsePlugin.getStandardDisplay(), data); FONT_MAP.put(data, font); } } return font; } public static Font getFontPreference(String pref) { FontData data = PreferenceConverter.getFontData(MercurialEclipsePlugin.getDefault() .getPreferenceStore(), pref); return getFont(data); } /** * Get the parent revision. Is aware of file renames. * * Note: May query and update the file status of cs. * * @param cs The changeset to query for * @param file The file as of cs's revision * @return Storage for the parent revision * @throws HgException */ public static MercurialRevisionStorage getParentRevision(ChangeSet cs, IFile file) throws HgException { String[] parents = cs.getParents(); if(cs.getRevision().getRevision() == 0){ return new NullRevision(file, cs); } else if (parents.length == 0) { // TODO for some reason, we do not always have right parent info in the changesets // If we are on the different branch then the changeset? or if the changeset // logs was created for a file, and not each version of a *file* has // direct version predecessor. So such tree 20 -> 21 -> 22 works fine, // but tree 20 -> 22 seems not to work per default // So simply enforce the parents resolving try { parents = HgParentClient.getParentNodeIds(file, cs); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } if (parents.length == 0) { return new NullRevision(file, cs); } } if (!cs.hasFileStatus()) { ChangeSet newCs = HgLogClient.getChangeset(cs.getHgRoot(), cs.getChangeset(), true); if (newCs != null) { assert newCs.hasFileStatus(); cs.setChangedFiles(newCs.getChangedFiles()); assert cs.hasFileStatus(); } } FileStatus stat = cs.getStatus(file); if (stat != null && stat.isCopied()) { file = ResourceUtils.getFileHandle(stat.getAbsoluteCopySourcePath()); } return new MercurialRevisionStorage(file, parents[0]); } public static void setOfferAutoCommitMerge(boolean offer) { try { ResourcesPlugin.getWorkspace().getRoot().setSessionProperty( ResourceProperties.MERGE_COMMIT_OFFERED, (offer ? null : "true")); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } public static boolean isOfferAutoCommitMerge() { try { return ResourcesPlugin.getWorkspace().getRoot() .getSessionProperty(ResourceProperties.MERGE_COMMIT_OFFERED) == null; } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return true; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/Messages.java000066400000000000000000000021211173713500500317240ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.team.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/NullRevision.java000066400000000000000000000022111173713500500326060ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.core.resources.IFile; import com.vectrace.MercurialEclipse.model.ChangeSet; /** * An empty (null) revision to be used for 0 (first/non existent) revisions in compare editor * @author Andrei */ public class NullRevision extends MercurialRevisionStorage { /** * @param res */ public NullRevision(IFile res, ChangeSet cs) { super(res, 0, null, null); content = new ContentHolder((byte[]) null); changeSet = cs; } @Override public String getName() { return super.getName() + ": no content"; } @Override public boolean isReadOnly() { return true; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ResourceDecorator.java000066400000000000000000000424501173713500500336200ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes * Adam Berkes (Intland) - bug fixes * Zsolt Kopany (Intland) - bug fixes * Philip Graf - bug fix *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import static com.vectrace.MercurialEclipse.preferences.HgDecoratorConstants.*; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import java.util.HashSet; import java.util.Observable; import java.util.Observer; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.themes.ITheme; import org.eclipse.ui.themes.IThemeManager; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.HgBisectClient; import com.vectrace.MercurialEclipse.commands.extensions.HgRebaseClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.IncomingChangesetCache; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.Bits; import com.vectrace.MercurialEclipse.utils.ChangeSetUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * @author zingo */ public class ResourceDecorator extends LabelProvider implements ILightweightLabelDecorator, Observer { private static final MercurialStatusCache STATUS_CACHE = MercurialStatusCache.getInstance(); private static final IncomingChangesetCache INCOMING_CACHE = IncomingChangesetCache.getInstance(); private static final LocalChangesetCache LOCAL_CACHE = LocalChangesetCache.getInstance(); private static final String[] FONTS = new String[] { ADDED_FONT, CONFLICT_FONT, DELETED_FONT, REMOVED_FONT, UNKNOWN_FONT, IGNORED_FONT, CHANGE_FONT }; private static final String[] COLORS = new String[] { ADDED_BACKGROUND_COLOR, ADDED_FOREGROUND_COLOR, CHANGE_BACKGROUND_COLOR, CHANGE_FOREGROUND_COLOR, CONFLICT_BACKGROUND_COLOR, CONFLICT_FOREGROUND_COLOR, IGNORED_BACKGROUND_COLOR, IGNORED_FOREGROUND_COLOR, DELETED_BACKGROUND_COLOR, DELETED_FOREGROUND_COLOR, REMOVED_BACKGROUND_COLOR, REMOVED_FOREGROUND_COLOR, UNKNOWN_BACKGROUND_COLOR, UNKNOWN_FOREGROUND_COLOR }; private static final Set INTERESTING_PREFS = new HashSet(); static { INTERESTING_PREFS.add(LABELDECORATOR_LOGIC_2MM); INTERESTING_PREFS.add(LABELDECORATOR_LOGIC); INTERESTING_PREFS.add(PREF_DECORATE_WITH_COLORS); INTERESTING_PREFS.add(RESOURCE_DECORATOR_SHOW_CHANGESET); INTERESTING_PREFS.add(RESOURCE_DECORATOR_SHOW_INCOMING_CHANGESET); INTERESTING_PREFS.add(PREF_ENABLE_SUBREPO_SUPPORT); } /** set to true when having 2 different statuses in a folder flags it has modified */ private boolean folderLogic2MM; private ITheme theme; private boolean colorise; private boolean showChangeset; private boolean showIncomingChangeset; private boolean enableSubrepos; private boolean disposed; private final IPropertyChangeListener themeListener; private final IPropertyChangeListener prefsListener; public ResourceDecorator() { configureFromPreferences(); STATUS_CACHE.addObserver(this); INCOMING_CACHE.addObserver(this); theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); ensureFontAndColorsCreated(FONTS, COLORS); themeListener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if(!IThemeManager.CHANGE_CURRENT_THEME.equals(event.getProperty())){ return; } theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); ensureFontAndColorsCreated(FONTS, COLORS); } }; PlatformUI.getWorkbench().getThemeManager().addPropertyChangeListener(themeListener); prefsListener = new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { if(INTERESTING_PREFS.contains(event.getProperty())){ configureFromPreferences(); fireLabelProviderChanged(new LabelProviderChangedEvent(ResourceDecorator.this)); } } }; MercurialEclipsePlugin.getDefault().getPreferenceStore().addPropertyChangeListener(prefsListener); } /** * This method will ensure that the fonts and colors used by the decorator * are cached in the registries. This avoids having to syncExec when * decorating since we ensure that the fonts and colors are pre-created. * * @param f * fonts ids to cache * @param c * color ids to cache */ private void ensureFontAndColorsCreated(final String[] f, final String[] c) { MercurialEclipsePlugin.getStandardDisplay().syncExec(new Runnable() { public void run() { for (int i = 0; i < c.length; i++) { theme.getColorRegistry().get(c[i]); } for (int i = 0; i < f.length; i++) { theme.getFontRegistry().get(f[i]); } } }); } @Override public void dispose() { if(disposed) { return; } disposed = true; STATUS_CACHE.deleteObserver(this); INCOMING_CACHE.deleteObserver(this); PlatformUI.getWorkbench().getThemeManager().removePropertyChangeListener(themeListener); MercurialEclipsePlugin.getDefault().getPreferenceStore().removePropertyChangeListener(prefsListener); super.dispose(); } /** * Init all the options we need from preferences to avoid doing this all the time */ private void configureFromPreferences() { IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); folderLogic2MM = LABELDECORATOR_LOGIC_2MM.equals(store.getString(LABELDECORATOR_LOGIC)); colorise = store.getBoolean(PREF_DECORATE_WITH_COLORS); showChangeset = store.getBoolean(RESOURCE_DECORATOR_SHOW_CHANGESET); showIncomingChangeset = store.getBoolean(RESOURCE_DECORATOR_SHOW_INCOMING_CHANGESET); enableSubrepos = store.getBoolean(MercurialPreferenceConstants.PREF_ENABLE_SUBREPO_SUPPORT); } public void decorate(Object element, IDecoration d) { IResource resource = (IResource) element; IProject project = resource.getProject(); if (project == null || !project.isAccessible()) { return; } try { if (!MercurialTeamProvider.isHgTeamProviderFor(project)) { return; } if (!STATUS_CACHE.isStatusKnown(project)) { // simply wait until the cache sends us an event d.addOverlay(DecoratorImages.NOT_TRACKED); if(resource == project){ d.addSuffix(" [Hg status pending...]"); } return; } ImageDescriptor overlay = null; StringBuilder prefix = new StringBuilder(2); Integer output = STATUS_CACHE.getStatus(resource); if (output != null) { overlay = decorate(output.intValue(), prefix, d, colorise); } else { // empty folder, do nothing } if (overlay != null) { d.addOverlay(overlay); } if (!showChangeset) { if (resource.getType() == IResource.PROJECT || shouldCheckSubrepo(resource)) { d.addSuffix(getSuffixForContainer((IContainer)resource)); } } else { addChangesetInfo(d, resource, project, prefix); } // we want a prefix, even if no changeset is displayed if (prefix.length() > 0) { d.addPrefix(prefix.toString()); } } catch (Exception e) { MercurialEclipsePlugin.logError(e); } } private boolean shouldCheckSubrepo(IResource resource) throws HgException { return enableSubrepos && resource.getType() == IResource.FOLDER && AbstractClient.isHgRoot(resource) != null; } /** * @param statusBits non null hg status bits from cache */ private ImageDescriptor decorate(int statusBits, StringBuilder prefix, IDecoration d, boolean coloriseLabels) { ImageDescriptor overlay = null; // BitSet output = fr.getStatus(); // "ignore" does not really count as modified if (folderLogic2MM && (Bits.cardinality(statusBits) > 2 || (Bits.cardinality(statusBits) == 2 && !Bits.contains(statusBits, MercurialStatusCache.BIT_IGNORE)))) { overlay = DecoratorImages.MODIFIED; if (coloriseLabels) { setBackground(d, CHANGE_BACKGROUND_COLOR); setForeground(d, CHANGE_FOREGROUND_COLOR); setFont(d, CHANGE_FONT); } else { prefix.append('>'); } } else { switch (Bits.highestBit(statusBits)) { case MercurialStatusCache.BIT_IGNORE: if (coloriseLabels) { setBackground(d, IGNORED_BACKGROUND_COLOR); setForeground(d, IGNORED_FOREGROUND_COLOR); setFont(d, IGNORED_FONT); } else { prefix.append('>'); } break; case MercurialStatusCache.BIT_MODIFIED: overlay = DecoratorImages.MODIFIED; if (coloriseLabels) { setBackground(d, CHANGE_BACKGROUND_COLOR); setForeground(d, CHANGE_FOREGROUND_COLOR); setFont(d, CHANGE_FONT); } else { prefix.append('>'); } break; case MercurialStatusCache.BIT_ADDED: overlay = DecoratorImages.ADDED; if (coloriseLabels) { setBackground(d, ADDED_BACKGROUND_COLOR); setForeground(d, ADDED_FOREGROUND_COLOR); setFont(d, ADDED_FONT); } else { prefix.append('>'); } break; case MercurialStatusCache.BIT_UNKNOWN: overlay = DecoratorImages.NOT_TRACKED; if (coloriseLabels) { setBackground(d, UNKNOWN_BACKGROUND_COLOR); setForeground(d, UNKNOWN_FOREGROUND_COLOR); setFont(d, UNKNOWN_FONT); } else { prefix.append('>'); } break; case MercurialStatusCache.BIT_CLEAN: overlay = DecoratorImages.MANAGED; break; // case BIT_IGNORE: // do nothing case MercurialStatusCache.BIT_REMOVED: overlay = DecoratorImages.REMOVED; if (coloriseLabels) { setBackground(d, REMOVED_BACKGROUND_COLOR); setForeground(d, REMOVED_FOREGROUND_COLOR); setFont(d, REMOVED_FONT); } else { prefix.append('>'); } break; case MercurialStatusCache.BIT_MISSING: overlay = DecoratorImages.DELETED_STILL_TRACKED; if (coloriseLabels) { setBackground(d, DELETED_BACKGROUND_COLOR); setForeground(d, DELETED_FOREGROUND_COLOR); setFont(d, DELETED_FONT); } else { prefix.append('>'); } break; case MercurialStatusCache.BIT_CONFLICT: overlay = DecoratorImages.CONFLICT; if (coloriseLabels) { setBackground(d, CONFLICT_BACKGROUND_COLOR); setForeground(d, CONFLICT_FOREGROUND_COLOR); setFont(d, CONFLICT_FONT); } else { prefix.append('>'); } break; } } return overlay; } private void addChangesetInfo(IDecoration d, IResource resource, IProject project, StringBuilder prefix) throws CoreException { // label info for incoming changesets ChangeSet newestIncomingChangeSet = null; if(showIncomingChangeset) { try { newestIncomingChangeSet = INCOMING_CACHE.getNewestChangeSet(resource); } catch (HgException e) { // if an error occurs we want the rest of the decoration to succeed nonetheless MercurialEclipsePlugin.logError(e); } } if (newestIncomingChangeSet != null) { if (prefix.length() == 0) { prefix.append('<').append(' '); } else { prefix.insert(0, '<'); } } // local changeset info try { // init suffix with project changeset information, or for folders that contain a subrepos String suffix = ""; //$NON-NLS-1$ if (resource.getType() == IResource.PROJECT || shouldCheckSubrepo(resource)) { suffix = getSuffixForContainer((IContainer)resource); } // overwrite suffix for files if (resource.getType() == IResource.FILE) { suffix = getSuffixForFiles(resource, newestIncomingChangeSet); } // only decorate files and project with suffix if ((resource.getType() != IResource.FOLDER || enableSubrepos) && suffix != null && suffix.length() > 0) { d.addSuffix(suffix); } } catch (HgException e) { MercurialEclipsePlugin.logWarning(Messages.getString("ResourceDecorator.couldntGetVersionOfResource") + resource, e); } } private void setBackground(IDecoration d, String id) { d.setBackgroundColor(theme.getColorRegistry().get(id)); } private void setForeground(IDecoration d, String id) { d.setForegroundColor(theme.getColorRegistry().get(id)); } private void setFont(IDecoration d, String id) { d.setFont(theme.getFontRegistry().get(id)); } private static String getSuffixForFiles(IResource resource, ChangeSet cs) throws HgException { String suffix = ""; //$NON-NLS-1$ // suffix for files if (!STATUS_CACHE.isAdded(ResourceUtils.getPath(resource))) { ChangeSet fileCs = LOCAL_CACHE.getNewestChangeSet(resource); if (fileCs != null) { suffix = " [" + fileCs.getChangesetIndex() + " - " //$NON-NLS-1$ //$NON-NLS-2$ + fileCs.getAgeDate() + " - " + fileCs.getAuthor() + "]"; if (cs != null) { suffix += " < [" + cs.getChangesetIndex() + ":" //$NON-NLS-1$ + cs.getNodeShort() + " - " + cs.getAgeDate() + " - " + cs.getAuthor() + "]"; } } } return suffix; } private static String getSuffixForContainer(IContainer container) throws CoreException { ChangeSet changeSet = null; HgRoot root; if(container instanceof IProject){ root = MercurialTeamProvider.getHgRoot(container); if(root == null) { return ""; } changeSet = LOCAL_CACHE.getChangesetByRootId(container); }else{ root = AbstractClient.isHgRoot(container); if(root == null) { return ""; } changeSet = LOCAL_CACHE.getChangesetForRoot(root); } StringBuilder suffix = new StringBuilder(); if (changeSet == null) { suffix.append(Messages.getString("ResourceDecorator.new")); } else { suffix.append(" ["); //$NON-NLS-1$ String hex = changeSet.getNodeShort(); String tags = ChangeSetUtils.getPrintableTagsString(changeSet); String merging = STATUS_CACHE.getMergeChangesetId(container); boolean bisecting = false; boolean rebasing = false; // XXX should use map, as there can be 100 projects under the same root if(HgRebaseClient.isRebasing(root)) { rebasing = true; } // XXX should use map, as there can be 100 projects under the same root if (HgBisectClient.isBisecting(root)) { bisecting = true; } // rev info suffix.append(changeSet.getChangesetIndex()).append(':').append(hex); // branch String branch = MercurialTeamProvider.getCurrentBranch(root); if (branch.length() == 0) { branch = Branch.DEFAULT; } suffix.append('@').append(branch); // tags if (tags.length() > 0) { suffix.append('(').append(tags).append(')'); } // merge flag if (!rebasing && !StringUtils.isEmpty(merging)) { suffix.append(Messages.getString("ResourceDecorator.merging")); } if(rebasing) { suffix.append(Messages.getString("ResourceDecorator.rebasing")); } // bisect information if (bisecting) { suffix.append(" BISECTING"); } suffix.append(']'); } return suffix.toString(); } public static String getDecoratorId() { String decoratorId = ResourceDecorator.class.getName(); return decoratorId; } @SuppressWarnings("unchecked") public void update(Observable o, Object updatedObject) { if (updatedObject instanceof Set) { Set changed = (Set) updatedObject; if(changed.isEmpty()){ return; } if (changed.size() < 10) { fireNotification(changed); } else { // if we have a lot of updates, it's easier (faster) to ask clients to update themselves // otherwise unneeded decorator updates may cause Eclipse to be busy for minutes, see issue #11928 updateClientDecorations(); } } } private void fireNotification(Set notification) { LabelProviderChangedEvent event = new LabelProviderChangedEvent(this, notification.toArray()); fireLabelProviderChanged(event); notification.clear(); } /** * Fire a LabelProviderChangedEvent for this decorator if it is enabled, otherwise do nothing. *

* This method can be called from any thread as it will asynchroniously run a job in the user * interface thread as widget updates may result. *

*/ public static void updateClientDecorations() { Runnable decoratorUpdate = new Runnable() { public void run() { PlatformUI.getWorkbench().getDecoratorManager().update(getDecoratorId()); } }; Display.getDefault().asyncExec(decoratorUpdate); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/ResourceProperties.java000066400000000000000000000072741173713500500340370ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch - javadocs and new qualified name MERGE_COMMIT_OFFERED * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.QualifiedName; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.menu.CommitMergeHandler; import com.vectrace.MercurialEclipse.views.MergeView; /** * Contains the name of the properties set on IResources. * * @see IResource#setPersistentProperty(QualifiedName, String) * @see IResource#setSessionProperty(QualifiedName, Object) * @author Jerome Negre */ public final class ResourceProperties { private ResourceProperties() { // hide constructor of utility class } /** * Qualified name for a session property on a project that signifies that * the commit dialog has already been shown by the merge view for either * a merge or rebase. * * @see MergeView * @see CommitMergeHandler */ public static final QualifiedName MERGE_COMMIT_OFFERED = new QualifiedName( MercurialEclipsePlugin.ID, MergeView.ID + ".commitOffered"); //$NON-NLS-1$ /** * Qualified name for a workspace session property that signifies whether to * use Imerge extension or hg resolve for merging. Makes MercurialEclipse * check exactly once for hg resolve and remember it until Eclipse is * restarted. */ public static final QualifiedName RESOLVE_AVAILABLE = new QualifiedName( MercurialEclipsePlugin.ID, MergeView.ID + ".useResolve"); //$NON-NLS-1$ /** * Qualified name for a workspace session property that signifies whether * rebase is available. */ public static final QualifiedName REBASE_AVAILABLE = new QualifiedName( MercurialEclipsePlugin.ID, "hgext.rebase="); //$NON-NLS-1$ /** * Qualified name for a project session property that stores the canonical * path of a hg root. To create a {@link java.io.File} use the constructor * new File(project.getPersistentProperty(ResourceProperties.HG_ROOT)) */ public static final QualifiedName HG_ROOT = new QualifiedName( MercurialEclipsePlugin.ID, "hgRoot"); //$NON-NLS-1$ /** * Qualified name for a workspace session property that signifies whether * the bookmarks extension is available. */ public static final QualifiedName EXT_BOOKMARKS_AVAILABLE = new QualifiedName( MercurialEclipsePlugin.ID, "hgext.bookmarks="); //$NON-NLS-1$ /** * Qualified name for a workspace session property that signifies whether * the forest extension is available. */ public static final QualifiedName EXT_FOREST_AVAILABLE = new QualifiedName( MercurialEclipsePlugin.ID, "hgforest"); //$NON-NLS-1$ /** * Qualified name for a workspace session property that signifies whether * the HgSubversion extension is available. */ public static final QualifiedName EXT_HGSUBVERSION_AVAILABLE = new QualifiedName( MercurialEclipsePlugin.ID, "hgsubversion"); //$NON-NLS-1$ /** * Qualified name for a workspace session property that signifies whether * the HgAttic extension is available. */ public static final QualifiedName EXT_HGATTIC_AVAILABLE = new QualifiedName( MercurialEclipsePlugin.ID, "hgattic"); //$NON-NLS-1$ } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/SingleFileAction.java000066400000000000000000000037261173713500500333500ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * @author Jerome Negre */ public abstract class SingleFileAction implements IActionDelegate { protected IFile selection; public SingleFileAction() { super(); } public void selectionChanged(IAction action, ISelection sel) { if (sel instanceof IStructuredSelection) { //the xml enables this action only for a selection of a single file this.selection = (IFile) ((IStructuredSelection) sel).getFirstElement(); } } protected Shell getShell() { return MercurialEclipsePlugin.getActiveShell(); } protected IFile getSelectedFile() { return selection; } public void run(IAction action) { try { run(getSelectedFile()); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); MessageDialog.openError(getShell(), Messages.getString("SingleFileAction.hgSays"), e.getMessage() + Messages.getString("SingleFileAction.seeErrorLog")); } } protected abstract void run(IFile file) throws CoreException; }SingleResourceAction.java000066400000000000000000000026771173713500500342050ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/teampackage com.vectrace.MercurialEclipse.team; import org.eclipse.core.resources.IResource; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IActionDelegate; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * * @author Jerome Negre * */ public abstract class SingleResourceAction implements IActionDelegate { protected IResource selection; public SingleResourceAction() { super(); } public void selectionChanged(IAction action, ISelection sel) { if (sel instanceof IStructuredSelection) { //the xml enables this action only for a selection of a single resource this.selection = (IResource) ((IStructuredSelection) sel).getFirstElement(); } } protected static Shell getShell() { return MercurialEclipsePlugin.getActiveShell(); } protected IResource getSelectedResource() { return selection; } public void run(IAction action) { try { run(getSelectedResource()); } catch (Exception e) { MercurialEclipsePlugin.logError(e); MessageDialog.openError(getShell(), Messages.getString("SingleResourceAction.hgSays"), e.getMessage()+Messages.getString("SingleResourceAction.seeErrorLog")); //$NON-NLS-1$ //$NON-NLS-2$ } } protected abstract void run(IResource resource) throws Exception; }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/000077500000000000000000000000001173713500500303615ustar00rootroot00000000000000AbstractCache.java000066400000000000000000000134611173713500500336410ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.Collections; import java.util.HashSet; import java.util.Observable; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * This is the base class for 4 different caches we have in the current code: *

* Caches for local resources, do not maintain their state and has to be managed by clients: *

    *
  • {@link MercurialStatusCache} - maintains the Eclipse {@link IResource} states
  • *
  • {@link LocalChangesetCache} - maintains the known changesets in the local hg repository
  • *
*

* Caches for remote resources and semi-automatically maintain their state: *

    *
  • {@link OutgoingChangesetCache} - maintains new changesets in the local hg repository
  • *
  • {@link IncomingChangesetCache} - maintains new changesets in the remote hg repository
  • *
* @author bastian * @author Andrei Loskutov */ public abstract class AbstractCache extends Observable { protected static final SortedSet EMPTY_SET = Collections.unmodifiableSortedSet(new TreeSet()); protected final boolean debug; public AbstractCache() { super(); debug = MercurialEclipsePlugin.getDefault().isDebugging(); final IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); configureFromPreferences(store); store.addPropertyChangeListener(new IPropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { configureFromPreferences(store); } }); ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() { public void resourceChanged(IResourceChangeEvent event) { if (event.getType() != IResourceChangeEvent.POST_CHANGE) { return; } try { ProjectDeltaVisitor visitor = new ProjectDeltaVisitor(); event.getDelta().accept(visitor); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } }, IResourceChangeEvent.POST_CHANGE); } private class ProjectDeltaVisitor implements IResourceDeltaVisitor { public boolean visit(IResourceDelta delta) throws CoreException { IResource res = delta.getResource(); if (res.getType() == IResource.ROOT) { return true; } if (res.getType() != IResource.PROJECT) { return false; } IProject project = (IProject) res; if (delta.getKind() == IResourceDelta.REMOVED || ((delta.getFlags() & IResourceDelta.OPEN) != 0 && !project.isOpen())) { projectDeletedOrClosed(project); } return false; } } /** * Clients has cleanup all caches related to given project. */ protected abstract void projectDeletedOrClosed(IProject project); /** * does nothing, clients has to override and update preferences */ protected abstract void configureFromPreferences(IPreferenceStore store); /** * Spawns an update job to notify all the clients about given resource changes * @param resource non null */ protected void notifyChanged(final IResource resource, boolean expandMembers) { final Set resources = new HashSet(); if(!expandMembers) { resources.add(resource); } notifyChanged(resources, expandMembers); } /** * Spawns an update job to notify all the clients about given resource changes * @param resources non null */ protected void notifyChanged(final Set resources, final boolean expandMembers) { class ExclusiveRule implements ISchedulingRule { public boolean contains(ISchedulingRule rule) { return isConflicting(rule) || rule instanceof IResource || rule instanceof HgRootRule; } public boolean isConflicting(ISchedulingRule rule) { return rule instanceof ExclusiveRule; } } Job job = new Job("hg cache clients update..."){ @Override protected IStatus run(IProgressMonitor monitor) { Set set; if(!expandMembers){ set = resources; } else { set = new HashSet(resources); for (IResource r : resources) { if(monitor.isCanceled()){ return Status.CANCEL_STATUS; } set.addAll(ResourceUtils.getMembers(r)); } } setChanged(); notifyObservers(set); return Status.OK_STATUS; } }; job.setRule(new ExclusiveRule()); job.setSystem(true); job.schedule(); } @Override public String toString() { return getClass().getSimpleName(); } } AbstractRemoteCache.java000066400000000000000000000315571173713500500350230ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.preference.IPreferenceStore; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgIncomingClient; import com.vectrace.MercurialEclipse.commands.HgOutgoingClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * A base class for remote caches (caching changesets which are either not present * locally but existing on the server, or existing locally, but not present on the server). *

* The cache keeps the state automatically (and fetches the data on client request only), to avoid * unneeded client-server communication. *

* There is no guarantee that the data in the cache is up-to-date with the server. To get the * latest data, clients have explicitely refresh or clean the cache before using it. *

* The cache has empty ("invalid" state) before the first client request and automatically * retrieves the data on first client request. So it becames "valid" state and does not refresh the * data until some operation "clears" or explicitely requests a "refresh" of the cache. After the * "clear" operation the cache is going to the initial "invalid" state again. After "clear" and * "refresh", a notification is sent to the observing clients. *

* Implementation note 1 this cache automatically keeps the "valid" state for given * project/repository pair. Before each "get" request the cache validates itself. If the cached * value is NULL, then the cache state is invalid, and new data is fetched. If the cached value is * an object (even empty set), then the cache is "valid" (there is simply no data on the server). *

* Implementation note 2 the cache sends different notifications depending on what kind of * "state change" happened. After "clear", a set with only one "project" object is sent. After * "refresh", a set with all changed elements is sent, which may also include a project. * * @author bastian * @author Andrei Loskutov * @author Adam Berkes */ public abstract class AbstractRemoteCache extends AbstractCache { /** * Map hg root -> branch -> repo -> projects -> changeset */ protected final Map> repoDatas; protected final Map fastRepoMap; protected final Direction direction; /** * @param direction non null */ public AbstractRemoteCache(Direction direction) { this.direction = direction; repoDatas = new HashMap>(); fastRepoMap = new HashMap(); } /** * does nothing, clients has to override and update preferences */ @Override protected void configureFromPreferences(IPreferenceStore store) { // does nothing } public void clear(IHgRepositoryLocation repo) { synchronized (repoDatas) { Collection> values = repoDatas.values(); for (Set set : values) { Iterator iterator = set.iterator(); while (iterator.hasNext()) { RemoteData data = iterator.next(); if(repo.equals(data.getRepo())){ iterator.remove(); fastRepoMap.remove(data.getKey()); } } } notifyChanged(repo, false); } } public void clear(HgRoot root, boolean notify) { synchronized (repoDatas) { Set set = repoDatas.get(root); if(set == null){ return; } for (RemoteData data : set) { fastRepoMap.remove(data.getKey()); } set.clear(); } if(notify) { notifyChanged(root, false); } } @SuppressWarnings("unchecked") private void notifyChanged(HgRoot root, boolean expandMembers) { Set projects = ResourceUtils.getProjects(root); notifyChanged((Set) projects, expandMembers); } /** * @param notify true to send a notification if the cache state changes after this operation, * false to supress the event notification */ public void clear(IHgRepositoryLocation repo, IProject project, boolean notify) { synchronized (repoDatas) { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(project); Set set = repoDatas.get(hgRoot); if(set == null){ return; } Iterator iterator = set.iterator(); while(iterator.hasNext()) { RemoteData data = iterator.next(); if(repo.equals(data.getRepo())){ iterator.remove(); fastRepoMap.remove(data.getKey()); } } } if(notify) { notifyChanged(repo, false); } } @SuppressWarnings("unchecked") protected void notifyChanged(IHgRepositoryLocation repo, boolean expandMembers){ Set projects = MercurialEclipsePlugin.getRepoManager().getAllRepoLocationProjects(repo); notifyChanged((Set) projects, expandMembers); } @Override protected void projectDeletedOrClosed(IProject project) { synchronized (repoDatas) { for (RemoteData data : fastRepoMap.values()) { data.clear(project); } } } /** * Gets all (in or out) changesets of the given location for the given * IResource. * * @param branch name of branch (default or "" for unnamed) or null if branch unaware * @return never null */ public SortedSet getChangeSets(IResource resource, IHgRepositoryLocation repository, String branch) throws HgException { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(resource); if (hgRoot == null){ // if mercurial is not team provider or if we're working on a closed project return EMPTY_SET; } RemoteKey key = new RemoteKey(hgRoot, repository, branch); synchronized (repoDatas){ RemoteData data = fastRepoMap.get(key); if(data == null){ // lazy loading: refresh cache on demand only. // lock the cache till update is complete addResourcesToCache(key); // XXX not sure if the full repo refresh event need to be sent here // notifyChanged(key.getRepo(), true); notifyChanged(hgRoot, true); } RemoteData remoteData = fastRepoMap.get(key); if(remoteData != null) { return remoteData.getChangeSets(resource); } } return EMPTY_SET; } /** * Gets all (in or out) changesets of the given location for the given * IResource. * * @param branch name of branch (default or "" for unnamed) or null if branch unaware * @return never null */ public SortedSet hasChangeSets(IResource resource, IHgRepositoryLocation repository, String branch) { // also checks if mercurial is team provider and if we're working on an open project HgRoot hgRoot = MercurialTeamProvider.getHgRoot(resource); if (hgRoot == null){ // if mercurial is not team provider or if we're working on a closed project return EMPTY_SET; } RemoteKey key = new RemoteKey(hgRoot, repository, branch); synchronized (repoDatas){ RemoteData data = fastRepoMap.get(key); if(data == null){ return EMPTY_SET; } return data.getChangeSets(resource); } } /** * Gets all (in or out) changesets of the given hg root * * @param branch name of branch (default or "" for unnamed) or null if branch unaware * @return never null */ public SortedSet getChangeSets(HgRoot hgRoot, IHgRepositoryLocation repository, String branch) throws HgException { return getChangeSets(hgRoot, repository, branch, false); } /** * Gets all (in or out) changesets of the given hg root * * @param branch name of branch (default or "" for unnamed) or null if branch unaware * @param allowUnrelated True if unrelated repositories are acceptable * @return never null */ public SortedSet getChangeSets(HgRoot hgRoot, IHgRepositoryLocation repository, String branch, boolean allowUnrelated) throws HgException { RemoteKey key = new RemoteKey(hgRoot, repository, branch, allowUnrelated); synchronized (repoDatas){ RemoteData data = fastRepoMap.get(key); if(data == null){ // lazy loading: refresh cache on demand only. // lock the cache till update is complete addResourcesToCache(key); notifyChanged(hgRoot, true); } RemoteData remoteData = fastRepoMap.get(key); if(remoteData != null) { return remoteData.getChangeSets(); } } return EMPTY_SET; } /** * Gets all (in or out) changesets for given hg root, which doesn't have any relationship to the * projects inside Eclipse workspace (e.g. changesets with no files or with files which are * unknown in terms of Eclipse workspace). Specifying an optional 'canIgnore' argument * may help to optimize the work on huge amount of changesets or files inside. * * @param canIgnore * (may be null) changesets which are already known to be mapped and can be ignored. * * @param branch * name of branch (default or "" for unnamed) or null if branch unaware * @return never null */ public SortedSet getUnmappedChangeSets(HgRoot hgRoot, IHgRepositoryLocation repository, String branch, Set canIgnore) throws HgException { SortedSet all = getChangeSets(hgRoot, repository, branch); if(all.isEmpty()){ return all; } if(canIgnore != null && !canIgnore.isEmpty()) { // 'all' was unmodifiable set, so create a copy here for filtering all = new TreeSet(all); all.removeAll(canIgnore); if(all.isEmpty()){ return all; } } TreeSet sorted = new TreeSet(); for (ChangeSet cs : all) { if(cs.isEmpty()){ sorted.add(cs); continue; } Set files = cs.getFiles(); if(files.isEmpty()){ sorted.add(cs); } } return sorted; } /** * Gets all resources that are changed in (in or out) changesets of given * repository, even resources not known in local workspace. * * @return never null */ public Set getMembers(IResource resource, IHgRepositoryLocation repository, String branch) throws HgException { SortedSet changeSets; synchronized (repoDatas){ // make sure data is there: will refresh (in or out) changesets if needed changeSets = getChangeSets(resource, repository, branch); return getMembers(resource, changeSets); } } /** * @return never null */ private static Set getMembers(IResource resource, SortedSet changeSets) { Set members = new HashSet(); if (changeSets == null) { return members; } for (ChangeSet cs : changeSets) { members.addAll(cs.getFiles()); } return members; } private void addResourcesToCache(RemoteKey key) throws HgException { if(debug) { System.out.println("!fetch " + direction + " for " + key); } fastRepoMap.remove(key); // get changesets from hg RemoteData data = null; if (direction == Direction.OUTGOING) { data = HgOutgoingClient.getOutgoing(key); } else { data = HgIncomingClient.getHgIncoming(key); } if(debug) { System.out.println("!got " + data.getChangeSets().size() + " " + direction + " changesets"); } fastRepoMap.put(key, data); Set set = repoDatas.get(key.getRoot()); if(set == null){ set = new HashSet(); repoDatas.put(key.getRoot(), set); } set.add(data); } /** * Get newest revision of resource on given branch * @param resource Eclipse resource (e.g. a file) to find latest changeset for * @param branch name of branch (default or "" for unnamed) or null if branch unaware */ public ChangeSet getNewestChangeSet(IResource resource, IHgRepositoryLocation repository, String branch) throws HgException { if (MercurialStatusCache.getInstance().isSupervised(resource) || !resource.exists()) { synchronized (repoDatas){ // make sure data is there: will refresh (in or out) changesets if needed SortedSet changeSets = getChangeSets(resource, repository, branch); if (changeSets != null && changeSets.size() > 0) { return changeSets.last(); } } } return null; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/HgRootRule.java000066400000000000000000000057001173713500500332600ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.io.IOException; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.jobs.ISchedulingRule; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; /** * Exclusive rule for locking access to the resources related to same hg root. * * @author Andrei */ public class HgRootRule implements ISchedulingRule { private final HgRoot hgRoot; /** * @param hgRoot non null */ public HgRootRule(HgRoot hgRoot) { Assert.isNotNull(hgRoot, "Trying to create HgRootRule without a hgRoot object"); this.hgRoot = hgRoot; } public boolean contains(ISchedulingRule rule) { if (rule instanceof IResource) { IResource resource = (IResource) rule; IPath location = resource.getLocation(); if (location != null) { boolean isPrefix = hgRoot.getIPath().isPrefixOf(location); if (!isPrefix) { try { IPath canonicalLocation = new Path(location.toFile().getCanonicalPath()); isPrefix = hgRoot.getIPath().isPrefixOf(canonicalLocation); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } return isPrefix; } } return isConflicting(rule); } /** * Note: this method (used by Job API to detect deadlocks) should avoid made locking calls to * avoid deadlocks, see issues 13474, 13497 */ public boolean isConflicting(ISchedulingRule rule) { if(!(rule instanceof HgRootRule)){ if(rule instanceof IWorkspaceRoot){ return false; } if (rule instanceof IResource) { // hasHgRoot() returns cached value, if any (see issue 13474, 13497) // if the value is not yet cached, we don't care HgRoot resourceRoot = MercurialRootCache.getInstance().hasHgRoot((IResource) rule, false, false); if(resourceRoot == null) { return false; } return getHgRoot().equals(resourceRoot); } return false; } HgRootRule rootRule = (HgRootRule) rule; return getHgRoot().equals(rootRule.getHgRoot()); } public HgRoot getHgRoot() { return hgRoot; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("HgRootRule ["); builder.append("hgRoot="); builder.append(hgRoot); builder.append("]"); return builder.toString(); } } IncomingChangesetCache.java000066400000000000000000000054611173713500500354640ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * Cache for all changesets existing locally, but not present on the server */ public final class IncomingChangesetCache extends AbstractRemoteCache { private static IncomingChangesetCache instance; private IncomingChangesetCache() { super(Direction.INCOMING); } public static synchronized IncomingChangesetCache getInstance() { if (instance == null) { instance = new IncomingChangesetCache(); } return instance; } /** * Gets the newest incoming changeset of the default repository. In case no default * repository is set, all repositories are considered. * * @param resource * the resource to get the changeset for */ public ChangeSet getNewestChangeSet(IResource resource) throws HgException { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(resource); if(hgRoot == null) { return null; } HgRepositoryLocationManager repoManager = MercurialEclipsePlugin.getRepoManager(); IHgRepositoryLocation defaultRepo = repoManager.getDefaultRepoLocation(hgRoot); SortedSet changeSets1 = new TreeSet(); if(defaultRepo != null) { ChangeSet candidate = getNewestChangeSet(resource, defaultRepo, null); if (candidate != null) { changeSets1.add(candidate); } } else { Set locs = repoManager.getAllRepoLocations(hgRoot); for (IHgRepositoryLocation repository : locs) { ChangeSet candidate = getNewestChangeSet(resource, repository, null); if (candidate != null) { changeSets1.add(candidate); } } } if (changeSets1.size() > 0) { return changeSets1.last(); } return null; } } LocalChangesetCache.java000066400000000000000000000466761173713500500347700ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Observer; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.preference.IPreferenceStore; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgIdentClient; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * The cache does NOT keeps the state automatically. Clients have explicitely request and manage * cache updates. *

* There is no guarantee that the data in the cache is up-to-date with the server. To get the latest * data, clients have explicitely refresh the cache before using it. *

* The cache does not maintain any states. If client "clear" this cache, it must make sure that they * request an explicit cache update. After "clear" and "refresh", a notification is sent to the * observing clients. *

* Implementation note 1 the cache does not send any notifications... * * @author bastian * @author Andrei Loskutov */ public final class LocalChangesetCache extends AbstractCache { private static final MercurialStatusCache STATUS_CACHE = MercurialStatusCache.getInstance(); private static LocalChangesetCache instance; /** * Contains all the loaded changesets for each of the paths (resources) */ private final Map> localChangeSets; /** * Stores all changesets for each project. changesets can be retreived by its rev:node or rev:shortnode strings. Only actually used for reading in * getChangesetById(Project, String) which is private. This can probably be removed without adverse effect. */ private final Map> changesets; /** * Stores the latest changeset for each root */ private final Map latestChangesets; private int logBatchSize; private boolean isGetFileInformationForChangesets; private LocalChangesetCache() { super(); localChangeSets = new HashMap>(); changesets = new HashMap>(); latestChangesets = new HashMap(); } private boolean isGetFileInformationForChangesets() { return isGetFileInformationForChangesets; } public static synchronized LocalChangesetCache getInstance() { if (instance == null) { instance = new LocalChangesetCache(); } return instance; } public void clear(HgRoot root, boolean notify) { synchronized (latestChangesets) { latestChangesets.remove(root); } synchronized (localChangeSets) { localChangeSets.remove(root.getIPath()); } Set projects = ResourceUtils.getProjects(root); for (IProject project : projects) { clear(project, notify); } } /** * * @param resource * @param notify * @deprecated {@link #clear(HgRoot, boolean)} should be used in most cases */ @Deprecated public void clear(IResource resource, boolean notify) { Set members = ResourceUtils.getMembers(resource); if(resource instanceof IProject && !resource.exists()) { members.remove(resource); } synchronized(localChangeSets){ for (IResource member : members) { localChangeSets.remove(ResourceUtils.getPath(member)); } } if(resource instanceof IProject){ synchronized (changesets){ changesets.remove(resource.getProject()); } } } @Override protected void projectDeletedOrClosed(IProject project) { clear(project, false); } /** * @param resource non null * @return never null, but possibly empty set */ public SortedSet getOrFetchChangeSets(IResource resource) throws HgException { IPath location = ResourceUtils.getPath(resource); if(location.isEmpty()) { return EMPTY_SET; } SortedSet revisions; synchronized(localChangeSets){ revisions = localChangeSets.get(location); if (revisions == null) { if (resource.getType() == IResource.FILE || resource.getType() == IResource.PROJECT && STATUS_CACHE.isSupervised(resource) && !STATUS_CACHE.isAdded(location)) { refreshAllLocalRevisions(resource, true); revisions = localChangeSets.get(location); } } } if (revisions != null) { return Collections.unmodifiableSortedSet(revisions); } return EMPTY_SET; } /** * @param hgRoot non null * @return never null, but possibly empty set */ public SortedSet getOrFetchChangeSets(HgRoot hgRoot) throws HgException { IPath location = hgRoot.getIPath(); SortedSet revisions; synchronized(localChangeSets){ revisions = localChangeSets.get(location); if (revisions == null) { refreshAllLocalRevisions(hgRoot, true); revisions = localChangeSets.get(location); } } if (revisions != null) { return Collections.unmodifiableSortedSet(revisions); } return EMPTY_SET; } /** * Gets changeset for given resource. * * @param resource * the resource to get status for. * @return may return null * @throws HgException */ public ChangeSet getNewestChangeSet(IResource resource) throws HgException { SortedSet revisions = getOrFetchChangeSets(resource); if (revisions.size() > 0) { return revisions.last(); } return null; } public ChangeSet getNewestChangeSet(HgRoot hgRoot) throws HgException { SortedSet revisions = getOrFetchChangeSets(hgRoot); if (revisions.size() > 0) { return revisions.last(); } return null; } /** * Refreshes all local revisions. If limit is set, it looks up the default * number of revisions to get and fetches the topmost till limit is reached. * * If preference is set to display changeset information on label decorator, * and a resource version can't be found in the topmost revisions, * the last revision of this file is obtained via additional * calls. * * @param res non null * @param limit whether to limit or to have full project log * @throws HgException * * @see #refreshAllLocalRevisions(IResource, boolean, boolean) */ public void refreshAllLocalRevisions(IResource res, boolean limit) throws HgException { refreshAllLocalRevisions(res, limit, isGetFileInformationForChangesets()); } /** * Refreshes all local revisions. If limit is set, it looks up the default * number of revisions to get and fetches the topmost till limit is reached. *

* A clear of all existing data for the given resource is triggered. *

* If withFiles is true and a resource version can't be found in the topmost * revisions, the last revision of this file is obtained via additional * calls. * * @param res non null * @param limit * whether to limit or to have full project log * @param withFiles * true = include file in changeset * @throws HgException */ public void refreshAllLocalRevisions(IResource res, boolean limit, boolean withFiles) throws HgException { Assert.isNotNull(res); IProject project = res.getProject(); if (MercurialTeamProvider.isHgTeamProviderFor(project)) { clear(res, false); int versionLimit = getLogBatchSize(); if(withFiles && versionLimit > 1) { versionLimit = 1; } fetchRevisions(res, limit, versionLimit, -1, withFiles); } } public Set refreshAllLocalRevisions(HgRoot hgRoot, boolean limit) throws HgException { return refreshAllLocalRevisions(hgRoot, limit, isGetFileInformationForChangesets()); } /** * Refreshes all local revisions. If limit is set, it looks up the default * number of revisions to get and fetches the topmost till limit is reached. *

* A clear of all existing data for the given resource is triggered. *

* If withFiles is true and a resource version can't be found in the topmost * revisions, the last revision of this file is obtained via additional * calls. * * @param hgRoot non null * @param limit * whether to limit or to have full project log * @param withFiles * true = include file in changeset * @throws HgException */ public Set refreshAllLocalRevisions(HgRoot hgRoot, boolean limit, boolean withFiles) throws HgException { Assert.isNotNull(hgRoot); clear(hgRoot, false); int versionLimit = getLogBatchSize(); if(withFiles && versionLimit > 1) { versionLimit = 1; } return fetchRevisions(hgRoot, limit, versionLimit, -1, withFiles); } @Override protected void configureFromPreferences(IPreferenceStore store){ logBatchSize = store.getInt(MercurialPreferenceConstants.LOG_BATCH_SIZE); if (logBatchSize < 0) { logBatchSize = 2000; MercurialEclipsePlugin.logWarning(Messages.localChangesetCache_LogLimitNotCorrectlyConfigured, null); } isGetFileInformationForChangesets = store.getBoolean( MercurialPreferenceConstants.RESOURCE_DECORATOR_SHOW_CHANGESET); } /** * Gets the configured log batch size. */ public int getLogBatchSize() { return logBatchSize; } /** * Gets changeset by its identifier * * @param changesetId * string in format rev:nodeshort or rev:node * @return may return null, if changeset is not known */ private ChangeSet getChangesetById(IProject project, String changesetId) { Map map; synchronized (changesets) { map = changesets.get(project); } if(map != null) { return map.get(changesetId); } return null; } public ChangeSet getOrFetchChangeSetById(HgRoot hgRoot, String nodeId) throws HgException { Assert.isNotNull(hgRoot); Assert.isNotNull(nodeId); SortedSet sets = getOrFetchChangeSets(hgRoot); for (ChangeSet changeSet : sets) { if(nodeId.equals(changeSet.getChangeset()) || nodeId.equals(changeSet.toString()) || nodeId.equals(changeSet.getName())){ return changeSet; } } return null; } public ChangeSet getOrFetchChangeSetById(IResource res, String nodeId) throws HgException { Assert.isNotNull(res); Assert.isNotNull(nodeId); ChangeSet changeSet = getChangesetById(res.getProject(), nodeId); if (changeSet != null) { return changeSet; } synchronized (localChangeSets){ changeSet = HgLogClient.getChangeset(res, nodeId, isGetFileInformationForChangesets()); if (changeSet == null) { return changeSet; } // ok, the map has to be updated with the new info if(!res.exists() || STATUS_CACHE.isSupervised(res)){ // !res.exists() is the case for renamed (moved) or copied files which does not exist anymore HashSet set = new HashSet(); set.add(changeSet); addChangesets(res.getProject(), set); } } return changeSet; } /** * @return may return null */ public ChangeSet getChangesetByRootId(IResource res) throws HgException { HgRoot root = MercurialTeamProvider.getHgRoot(res); if(root == null) { return null; } return getChangesetForRoot(root); } /** * @return may return null */ public ChangeSet getChangesetForRoot(HgRoot root) throws HgException { // for projects in the same root try to use root cache synchronized (latestChangesets) { ChangeSet changeSet = latestChangesets.get(root); if(changeSet != null) { return changeSet; } String nodeId = HgIdentClient.getCurrentChangesetId(root); if (!HgIdentClient.VERSION_ZERO.equals(nodeId)) { ChangeSet lastSet = HgLogClient.getChangeset(root, nodeId); if (lastSet != null) { latestChangesets.put(root, lastSet); } return lastSet; } } return null; } /** * Checks if the cache contains an old changeset. If this is the case, simply removes the cached * value (new value will be retrieved later) * * @param root * working dir * @param nodeId * latest working dir (full) changeset id */ public void checkLatestChangeset(HgRoot root, String nodeId) { if (nodeId == null || root == null) { return; } if (!HgIdentClient.VERSION_ZERO.equals(nodeId)) { synchronized (latestChangesets) { ChangeSet lastSet = latestChangesets.get(root); if (lastSet != null && !nodeId.equals(lastSet.getChangeset())) { latestChangesets.remove(root); } } } } /** * Fetches local revisions. If limit is set, it looks up the default * number of revisions to get and fetches the topmost till limit is reached. * * If a resource version can't be found in the topmost revisions, the last * revisions of this file (10% of limit number) are obtained via additional * calls. * * @param res non null * @param limit * whether to limit or to have full project log * @param limitNumber * if limit is set, how many revisions should be fetched * @param startRev * the revision to start with * @throws HgException */ public void fetchRevisions(IResource res, boolean limit, int limitNumber, int startRev, boolean withFiles) throws HgException { Assert.isNotNull(res); IProject project = res.getProject(); if (!project.isOpen() || !STATUS_CACHE.isSupervised(res)) { return; } HgRoot root = MercurialTeamProvider.getHgRoot(res); Assert.isNotNull(root); Map> revisions; // now we may change cache state, so lock synchronized(localChangeSets){ if (limit) { revisions = HgLogClient.getProjectLog(res, limitNumber, startRev, withFiles); } else { revisions = HgLogClient.getCompleteProjectLog(res, withFiles); } if (revisions.size() == 0) { return; } if (res.getType() != IResource.PROJECT) { IPath location = ResourceUtils.getPath(res); if(location.isEmpty()) { return; } Set csets = revisions.get(location); if(csets != null) { localChangeSets.put(location, new TreeSet(csets)); } else { localChangeSets.put(location, new TreeSet()); } } for (Map.Entry> mapEntry : revisions.entrySet()) { IPath path = mapEntry.getKey(); Set changes = mapEntry.getValue(); // if changes for resource not in cache, get at least 1 revision if (changes == null && limit && withFiles && STATUS_CACHE.isSupervised(project, path) && !STATUS_CACHE.isAdded(path)) { IResource myResource = ResourceUtils.convertRepoRelPath(root, project, root.toRelative(path.toFile())); if (myResource != null) { changes = HgLogClient.getRecentProjectLog(myResource, 1, withFiles).get(path); } } // add changes to cache addChangesToLocalCache(project, path, changes); } } } /** * Fetches local revisions. If limit is set, it looks up the default * number of revisions to get and fetches the topmost till limit is reached. * * If a resource version can't be found in the topmost revisions, the last * revisions of this file (10% of limit number) are obtained via additional * calls. * * @param hgRoot non null * @param limit * whether to limit or to have full project log * @param limitNumber * if limit is set, how many revisions should be fetched * @param startRev * the revision to start with * @throws HgException */ public Set fetchRevisions(HgRoot hgRoot, boolean limit, int limitNumber, int startRev, boolean withFiles) throws HgException { Assert.isNotNull(hgRoot); Map> revisions; // now we may change cache state, so lock synchronized(localChangeSets){ if (limit) { revisions = HgLogClient.getRootLog(hgRoot, limitNumber, startRev, withFiles); } else { revisions = HgLogClient.getCompleteRootLog(hgRoot, withFiles); } if (revisions.size() == 0) { return EMPTY_SET; } Set changes = revisions.get(hgRoot.getIPath()); // XXX should we distribute/remember changesets by project? addChangesToLocalCache(null, hgRoot.getIPath(), changes); return changes; } } @Override public synchronized void addObserver(Observer o) { // last implementation was very inefficient: the only listener was // the decorator, and this one has generated NEW cache updates each time // he was notified about changes, so it is an endless loop. // So temporary do not allow to observe this cache, until the code is improved // has no effect MercurialEclipsePlugin.logError(new UnsupportedOperationException("Observer not supported: " + o)); } @Override public synchronized void deleteObserver(Observer o) { // has no effect } /** * Spawns an update job to notify all the clients about given resource changes * @param resource non null */ @Override protected void notifyChanged(final IResource resource, boolean expandMembers) { // has no effect MercurialEclipsePlugin.logError(new UnsupportedOperationException("notifyChanged not supported")); } /** * Spawns an update job to notify all the clients about given resource changes * @param resources non null */ @Override protected void notifyChanged(final Set resources, final boolean expandMembers) { // has no effect MercurialEclipsePlugin.logError(new UnsupportedOperationException("notifyChanged not supported")); } private void addChangesets(IProject project, Set changes) { synchronized (changesets) { Map map = changesets.get(project); if(map == null){ map = new ConcurrentHashMap(); changesets.put(project, map); } for (ChangeSet changeSet : changes) { map.put(changeSet.toString(), changeSet); map.put(changeSet.getChangeset(), changeSet); map.put(changeSet.getName(), changeSet); } } } /** * @param path absolute file path * @param changes may be null */ private void addChangesToLocalCache(IProject project, IPath path, Set changes) { if (changes != null && changes.size() > 0) { SortedSet existing = localChangeSets.get(path); if (existing == null) { existing = new TreeSet(); localChangeSets.put(path, existing); } existing.addAll(changes); if(project != null) { addChangesets(project, changes); } } } public SortedSet getOrFetchChangeSetsByBranch(HgRoot hgRoot, String branchName) throws HgException { SortedSet changes = getOrFetchChangeSets(hgRoot); SortedSet branchChangeSets = new TreeSet(); for (ChangeSet changeSet : changes) { String changesetBranch = changeSet.getBranch(); if (Branch.same(branchName, changesetBranch)) { branchChangeSets.add(changeSet); } } return branchChangeSets; } } MercurialRootCache.java000066400000000000000000000374771173713500500347020ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * npiguet - implementation * John Peberdy - refactoring * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.QualifiedName; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.internal.core.TeamPlugin; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgRootClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgResource; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * This handles the known roots cache. The caching for an individual resources is handled as a * session property on the resource. * * @author npiguet */ public class MercurialRootCache extends AbstractCache { private static final QualifiedName SESSION_KEY = new QualifiedName(MercurialEclipsePlugin.ID, "MercurialRootCacheKey"); /** * The current sentinel for no root */ private String noRoot = "No Mercurial root"; private final ConcurrentHashMap knownRoots = new ConcurrentHashMap( 16, 0.75f, 4); /** * Tracks known non-canonical forms of paths. * * There is a concurrent tree map in Java 1.6+ only. */ private final TreeMap> canonicalMap = new TreeMap>( new Comparator() { public int compare(IPath o1, IPath o2) { for (int i = 0, n = Math.max(o1.segmentCount(), o2.segmentCount()); i < n; i++) { String a = o1.segment(i), b = o2.segment(i); int res; if (a == null) { res = b == null ? 0 : -1; } else if (b == null) { res = 1; } else { res = a.compareTo(b); } if (res != 0) { return res; } } return 0; } }); private MercurialRootCache() { } public HgRoot calculateHgRoot(IResource resource) { File fileHandle = ResourceUtils.getFileHandle(resource); if(fileHandle.getPath().length() == 0) { return null; } return calculateHgRoot(fileHandle, false); } private HgRoot calculateHgRoot(File file, boolean reportNotFoundRoot) { if (file instanceof HgRoot) { return (HgRoot) file; } // TODO: possible optimization: try to look for the parent in the cache, or load the whole hierarchy in cache // or something else like that, so we don't need to call HgRootClient for each file in a directory HgRoot root; try { root = HgRootClient.getHgRoot(file); } catch (HgException e) { if(reportNotFoundRoot) { MercurialEclipsePlugin.logError(e); } // no root found at all root = null; } if (root != null) { HgRoot prev = knownRoots.putIfAbsent(root, root); if (prev != null) { root = prev; } } return root; } /** * Find the hg root for the given resource. If the root could not be found, no error would be * reported. * * @param resource * The resource, not null. * @param resolveIfNotKnown * true to trigger hg root search or/and also possible team provider configuration * operation, which may lead to locking * * @return The hg root, or null if an error occurred or enclosing project is closed or project * team provider is not Mercurial or hg root is not found */ public HgRoot hasHgRoot(IResource resource, boolean resolveIfNotKnown) { return hasHgRoot(resource, resolveIfNotKnown, false); } /** * Find the hg root for the given resource. If the root could not be found, an error will be * reported. * * @param resource * The resource, not null. * @param resolveIfNotKnown * true to trigger hg root search or/and also possible team provider configuration * operation, which may lead to locking * @param reportNotFoundRoot * true to report an error if the root is not found * * @return The hg root, or null if an error occurred or enclosing project is closed or project * team provider is not Mercurial or hg root is not found */ public HgRoot hasHgRoot(IResource resource, boolean resolveIfNotKnown, boolean reportNotFoundRoot) { return getHgRoot(resource, resolveIfNotKnown, reportNotFoundRoot); } /** * Find the hg root for the given resource. * * @param resource * The resource, not null. * @param resolveIfNotKnown * true to trigger hg root search or/and also possible team provider configuration * operation, which may lead to locking * @param reportNotFoundRoot * true to report an error if the root is not found * @return The hg root, or null if an error occurred or enclosing project is closed or project * team provider is not Mercurial or hg root is not found */ private HgRoot getHgRoot(IResource resource, boolean resolveIfNotKnown, boolean reportNotFoundRoot) { if (resource instanceof IHgResource) { // special case for HgRootContainers, they already know their HgRoot return ((IHgResource) resource).getHgRoot(); } IProject project = resource.getProject(); if(project == null) { return null; } // The call to RepositoryProvider is needed to trigger configure(project) on // MercurialTeamProvider if it doesn't happen before. Additionally, we avoid the // case if the hg root is there but project is NOT configured for MercurialEclipse // as team provider. See issue 13448. if(resolveIfNotKnown) { boolean projectIsOpen = project.isOpen(); if(!projectIsOpen) { IPath path = ResourceUtils.getPath(project); if(canonicalMap.containsKey(path)) { return knownRoots.get(path.toFile()); } else if(path.segmentCount() > 1) { // last try: the root directory of the project? path = path.removeLastSegments(1); if(canonicalMap.containsKey(path)) { return knownRoots.get(path.toFile()); } } } RepositoryProvider provider = RepositoryProvider.getProvider(project, MercurialTeamProvider.ID); if (!(provider instanceof MercurialTeamProvider)) { if(provider == null && projectIsOpen && project.isHidden()) { Object cachedRoot; try { cachedRoot = project.getSessionProperty(SESSION_KEY); if(cachedRoot instanceof HgRoot) { return (HgRoot) cachedRoot; } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } return null; } } else { if(!isHgTeamProviderFor(project)){ return null; } } // As an optimization only cache for containers not files if (resource instanceof IFile && !resource.isLinked()) { resource = resource.getParent(); } boolean cacheResult = true; try { Object cachedRoot = resource.getSessionProperty(SESSION_KEY); if(cachedRoot instanceof HgRoot) { return (HgRoot) cachedRoot; } if (cachedRoot == noRoot) { return null; } } catch (CoreException e) { // Possible reasons: // - This resource does not exist. // - This resource is not local. cacheResult = false; } if(!resolveIfNotKnown) { return null; } // cachedRoot can be only null or an obsolete noRoot object File fileHandle = ResourceUtils.getFileHandle(resource); if(fileHandle.getPath().length() == 0) { return null; } HgRoot root = calculateHgRoot(fileHandle, reportNotFoundRoot); if (cacheResult) { try { markAsCached(resource, root); if (root != null) { synchronized (canonicalMap) { Set s = canonicalMap.get(root.getIPath()); if (s == null) { canonicalMap.put(root.getIPath(), s = new HashSet()); } IPath projectPath = project.getLocation(); if (!resource.isLinked(IResource.CHECK_ANCESTORS) && !root.getIPath().equals(projectPath) && !root.getIPath().isPrefixOf(projectPath)) { // only add paths which are *different* and NOT children of the root s.add(projectPath); } } } } catch (CoreException e) { // Possible reasons: // - 2 reasons above, or // - Resource changes are disallowed during certain types of resource change event // notification. See IResourceChangeEvent for more details. if(reportNotFoundRoot) { MercurialEclipsePlugin.logError(e); } } } return root; } public static void markAsCached(IResource resource, HgRoot root) throws CoreException { Object value = root == null ? getInstance().noRoot : root; resource.setSessionProperty(SESSION_KEY, value); if(root == null) { // mark all parents up to project as NOT in Mercurial while(!(resource.getParent() instanceof IWorkspaceRoot) && !resource.isLinked()){ resource = resource.getParent(); if(value.equals(resource.getSessionProperty(SESSION_KEY))) { return; } resource.setSessionProperty(SESSION_KEY, value); } } else { // only process if there are no links etc, means the root location // can be properly detected by simple path compare if(root.getIPath().isPrefixOf(resource.getLocation())){ // mark all parents up to the root location as IN Mercurial while(!(resource.getParent() instanceof IWorkspaceRoot) && !resource.isLinked() && !root.getIPath().equals(resource.getLocation())){ resource = resource.getParent(); if(value.equals(resource.getSessionProperty(SESSION_KEY))) { return; } resource.setSessionProperty(SESSION_KEY, value); } } } } /** * Checks if the given project is controlled by MercurialEclipse * as team provider. This method does not access any locks and so can be called * from synchronized code. * * @param project * non null * @return true, if MercurialEclipse provides team functions to this project, false otherwise * (if an error occurred or project is closed). */ @SuppressWarnings("restriction") public static boolean isHgTeamProviderFor(IProject project){ Assert.isNotNull(project); try { if(!project.isAccessible()) { return false; } Object provider = project.getSessionProperty(TeamPlugin.PROVIDER_PROP_KEY); return provider instanceof MercurialTeamProvider; } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return false; } } /** * Find the hgroot for the given resource. * * @param resource The resource, not null. * @return The hgroot, or null if an error occurred or not found */ public HgRoot getHgRoot(IResource resource) { return getHgRoot(resource, true, true); } public Collection getKnownHgRoots(){ return new ArrayList(this.knownRoots.values()); } @Override protected void configureFromPreferences(IPreferenceStore store) { // nothing to do } @Override public void projectDeletedOrClosed(IProject project) { if(!project.exists()) { return; } HgRoot hgRoot = getHgRoot(project, false, false); if(hgRoot == null) { return; } List projects = MercurialTeamProvider.getKnownHgProjects(hgRoot); // Fix for issue 14094: Refactor->Rename project throws lots of errors uncache(project); if(projects.size() > 1 && hgRoot.getIPath().equals(project.getLocation())) { // See 14113: various actions fail for recursive projects if the root project is closed // do not remove root as there are more then one project inside return; } IPath projPath = ResourceUtils.getPath(project); if (!projPath.isEmpty()) { Iterator it = knownRoots.values().iterator(); while (it.hasNext()) { HgRoot root = it.next(); if (projPath.isPrefixOf(root.getIPath())) { it.remove(); } } } } /** * When there are changes done outside of eclipse the root of a resource may go away or change. * * @param resource * The resource to evict. */ public static void uncache(IResource resource) { // A different more efficient approach would be to mark all contained hgroots (or just all // known root) as obsolete and then when a resource is queried we can detect this and // discard the cached result thereby making the invalidation lazy. But that would make // things more complex so use brute force for now: try { resource.accept(new IResourceVisitor() { public boolean visit(IResource res) throws CoreException { res.setSessionProperty(SESSION_KEY, null); return true; } }); } catch (CoreException e) { // CoreException - if this method fails. Reasons include: // - This resource does not exist. // - The visitor failed with this exception. MercurialEclipsePlugin.logError(e); } } /** * When a new repository is created previous negative cached results should be discarded. */ public void uncacheAllNegative() { noRoot = new String(noRoot); // equals but not == } /** * Return any paths other than the given path for which path is canonical of. * * @param path * The path to query * @return Non null possibly empty list of paths */ public IPath[] uncanonicalize(IPath path) { Set candidates = null; IPath bestKey = null; // Search for key that is a prefix of path synchronized (canonicalMap) { int matchingSegments = 1; SortedMap> map = canonicalMap; loop: for (int n = path.segmentCount(); matchingSegments < n && !map.isEmpty(); matchingSegments++) { IPath curPrefix = path.removeLastSegments(n - matchingSegments - 1); IPath curKey = map.firstKey(); if (curPrefix.isPrefixOf(curKey)) { bestKey = curKey; map = map.subMap(curPrefix, map.lastKey()); } else { break loop; } } if (bestKey != null && matchingSegments == bestKey.segmentCount()) { candidates = map.get(bestKey); assert bestKey.isPrefixOf(path); } } // Build results by switching one prefix for the other if (candidates != null && /* redundant */ bestKey != null) { IPath pathRel = path.removeFirstSegments(bestKey.segmentCount()); List result = null; for (IPath candidate : candidates) { // The documentation says the path is canonicalized, but in fact symbolic links // aren't normalized. candidate = candidate.append(pathRel); if (!candidate.equals(path)) { if (result == null) { result = new ArrayList(candidates.size()); } result.add(candidate); } } if (result != null) { return result.toArray(new IPath[result.size()]); } } return ResourceUtils.NO_PATHS; } public static MercurialRootCache getInstance(){ return MercurialRootCacheHolder.INSTANCE; } /** * Initialization On Demand Holder idiom, thread-safe and instance will not be created until getInstance is called * in the outer class. */ private static final class MercurialRootCacheHolder { private static final MercurialRootCache INSTANCE = new MercurialRootCache(); private MercurialRootCacheHolder(){} } } MercurialStatusCache.java000066400000000000000000001525001173713500500352230ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Software Balm Consulting Inc (Peter Hunnisett ) - some updates * StefanC - large contribution * Jerome Negre - fixing folders' state * Bastian Doetsch - extraction from DecoratorStatus + additional methods * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import java.util.regex.Pattern; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.osgi.util.NLS; import org.eclipse.team.core.Team; import com.vectrace.MercurialEclipse.HgFeatures; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgResolveClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.commands.HgSubreposClient; import com.vectrace.MercurialEclipse.commands.extensions.HgRebaseClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.FlaggedAdaptable; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.Bits; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * Caches the Mercurial Status of each file and offers methods for retrieving, clearing and * refreshing repository state. * * @author Bastian Doetsch */ public final class MercurialStatusCache extends AbstractCache implements IResourceChangeListener { private static final int STATUS_BATCH_SIZE = 10; static final int NUM_CHANGED_FOR_COMPLETE_STATUS = 50; /** * @author Andrei */ private final class ProjectUpdateJob extends Job { private final IProject project; private final RootResourceSet resources; private ProjectUpdateJob(RootResourceSet removedSet, RootResourceSet changedSet, IProject project, RootResourceSet addedSet) { super(Messages.mercurialStatusCache_RefreshStatus); this.project = project; resources = new RootResourceSet(); if(removedSet != null) { resources.addAll(removedSet); } if(changedSet != null) { resources.addAll(changedSet); } if(addedSet != null) { resources.addAll(addedSet); } if(resources.contains(project) || resources.size() > NUM_CHANGED_FOR_COMPLETE_STATUS){ // refreshing the status of too many files, just refresh the whole project HgRoot projectRoot = resources.rootOf(project); if(projectRoot == null){ projectRoot = MercurialTeamProvider.getHgRoot(project); } if(projectRoot != null) { resources.clear(); resources.add(projectRoot, project); } } } @Override protected IStatus run(IProgressMonitor monitor) { // now process gathered changes (they are in the lists) if(monitor.isCanceled()){ return Status.CANCEL_STATUS; } try { updateProject(monitor); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } finally { monitor.done(); } return Status.OK_STATUS; } private void updateProject(IProgressMonitor monitor) throws HgException { if (resources.size() == 1 && resources.contains(project)) { monitor.beginTask(NLS.bind(Messages.mercurialStatusCache_RefreshingProject, project.getName()), 1); // do not need to call notifyChanged(resources): refreshStatus() does it already refreshStatus(project, monitor); } else if(!resources.isEmpty()) { monitor.beginTask(Messages.mercurialStatusCache_RefreshingResources, 1); // do not need to call notifyChanged(resources): refreshStatus() does it already refreshStatus(resources, project); } monitor.worked(1); } @Override public boolean belongsTo(Object family) { return ProjectUpdateJob.class.equals(family); } @Override public boolean equals(Object obj) { if(!(obj instanceof ProjectUpdateJob)){ return false; } ProjectUpdateJob job = (ProjectUpdateJob) obj; if(resources.size() != job.resources.size()){ return false; } if(!project.equals(job.project)){ return false; } return resources.equals(job.resources); } @Override public int hashCode() { return super.hashCode(); } } private final class MemberStatusVisitor { int bitSet; public MemberStatusVisitor(IPath parentLocation, int bitSet) { this.bitSet = bitSet; } public boolean visit(IPath childLocation) { Integer memberBitSet = statusMap.get(childLocation); if (memberBitSet != null) { if(Bits.contains(memberBitSet.intValue(), MODIFIED_MASK)){ bitSet |= BIT_MODIFIED; // now we are dirty, so we can stop return false; } } return true; } } /** * Initialization On Demand Holder idiom, thread-safe and instance will not be created until getInstance is called * in the outer class. */ private static final class MercurialStatusCacheHolder { private MercurialStatusCacheHolder() { /* hide constructor of utility class. */ } public static final MercurialStatusCache INSTANCE = new MercurialStatusCache(); } public static final int BIT_IGNORE = 1 << 1; public static final int BIT_CLEAN = 1 << 2; /** file is tracked by hg, but it is missing on a disk (probably deleted by external command) */ public static final int BIT_MISSING = 1 << 3; public static final int BIT_REMOVED = 1 << 4; public static final int BIT_UNKNOWN = 1 << 5; public static final int BIT_ADDED = 1 << 6; public static final int BIT_MODIFIED = 1 << 7; public static final int BIT_IMPOSSIBLE = 1 << 8; public static final int BIT_CONFLICT = 1 << 9; /** directory bit */ public static final int BIT_DIR = 1 << 10; private static final Integer IGNORE = Integer.valueOf(BIT_IGNORE); private static final Integer CLEAN = Integer.valueOf(BIT_CLEAN); // private final static Integer _MISSING = Integer.valueOf(BIT_MISSING); // private final static Integer _REMOVED = Integer.valueOf(BIT_REMOVED); // private final static Integer _UNKNOWN = Integer.valueOf(BIT_UNKNOWN); // private final static Integer _ADDED = Integer.valueOf(BIT_ADDED); // private final static Integer _MODIFIED = Integer.valueOf(BIT_MODIFIED); // private final static Integer _IMPOSSIBLE = Integer.valueOf(BIT_IMPOSSIBLE); private static final Integer CONFLICT = Integer.valueOf(BIT_CONFLICT); /** maximum bits count used in the cache */ // private final static int MAX_BITS_COUNT = 9; public static final char CHAR_IGNORED = 'I'; public static final char CHAR_CLEAN = 'C'; public static final char CHAR_MISSING = '!'; public static final char CHAR_REMOVED = 'R'; public static final char CHAR_UNKNOWN = '?'; public static final char CHAR_ADDED = 'A'; public static final char CHAR_MODIFIED = 'M'; public static final char CHAR_UNRESOLVED = 'U'; public static final char CHAR_RESOLVED = 'R'; /** * If the child file has any of the bits set: BIT_IGNORE | BIT_CLEAN | * BIT_MISSING | BIT_REMOVED | BIT_UNKNOWN | BIT_ADDED, * we do not propagate this bits to the parent directory directly, * but propagate only {@link #BIT_MODIFIED} or {@link #BIT_CONFLICT} */ private static final int IGNORED_MASK = BIT_IGNORE | BIT_CLEAN | BIT_MISSING | BIT_REMOVED | BIT_UNKNOWN | BIT_ADDED; /** * We propagate only {@link #BIT_MODIFIED} bit to the parent directory, if any from bits: * BIT_MISSING | BIT_REMOVED | BIT_UNKNOWN | BIT_ADDED | BIT_MODIFIED is set on the child file. */ public static final int MODIFIED_MASK = BIT_MISSING | BIT_REMOVED | BIT_UNKNOWN | BIT_ADDED | BIT_MODIFIED; /** a directory is still supervised if one of the following bits is set */ private static final int DIR_SUPERVISED_MASK = BIT_ADDED | BIT_CLEAN | BIT_MISSING | BIT_MODIFIED | BIT_REMOVED | BIT_CONFLICT; /** an "added" directory is only added if NONE of the following bits is set */ private static final int DIR_NOT_ADDED_MASK = BIT_CLEAN | BIT_MISSING | BIT_MODIFIED | BIT_REMOVED | BIT_CONFLICT | BIT_IGNORE; protected static final int MASK_CHANGED = IResourceDelta.OPEN | IResourceDelta.CONTENT | IResourceDelta.MOVED_FROM | IResourceDelta.REPLACED | IResourceDelta.TYPE; protected static final int MASK_DELTA = MASK_CHANGED | IResourceDelta.MOVED_TO | IResourceDelta.ADDED | IResourceDelta.COPIED_FROM | IResourceDelta.REMOVED; /** Used to store the last known status of a resource */ /* private */final ConcurrentHashMap statusMap = new ConcurrentHashMap( 10000, 0.75f, 4); private final BitMap bitMap; private final Object statusUpdateLock = new byte[0]; /** Used to store which projects have already been parsed */ private final CopyOnWriteArraySet knownStatus = new CopyOnWriteArraySet(); private final ConcurrentHashMap mergeChangesetIds = new ConcurrentHashMap( 100, 0.75f, 4); private int statusBatchSize; private boolean enableSubrepos; static class BitMap { private final PathsSet ignore = new PathsSet(1000, 0.75f); // don't waste space with most popular state // private final Set clean = new HashSet(); private final PathsSet missing = new PathsSet(1000, 0.75f); private final PathsSet removed = new PathsSet(1000, 0.75f); private final PathsSet unknown = new PathsSet(1000, 0.75f); private final PathsSet added = new PathsSet(1000, 0.75f); private final PathsSet modified = new PathsSet(1000, 0.75f); private final PathsSet conflict = new PathsSet(1000, 0.75f); /** directories */ private final PathsSet dir = new PathsSet(1000, 0.75f); // we do not cache impossible values // private final Set impossible = new HashSet(); public BitMap() { super(); } synchronized void put(IPath path, Integer set){ // removed is the first one for speed int mask = set.intValue(); if((mask & BIT_REMOVED) != 0){ removed.add(path); } if((mask & BIT_MISSING) != 0){ missing.add(path); } if((mask & BIT_UNKNOWN) != 0){ unknown.add(path); } if((mask & BIT_ADDED) != 0){ added.add(path); } if((mask & BIT_MODIFIED) != 0){ modified.add(path); } if((mask & BIT_CONFLICT) != 0){ conflict.add(path); } if((mask & BIT_IGNORE) != 0){ ignore.add(path); } if((mask & BIT_DIR) != 0){ dir.add(path); } } synchronized PathsSet get(int bit){ switch (bit) { case BIT_REMOVED: return removed; case BIT_MISSING: return missing; case BIT_UNKNOWN: return unknown; case BIT_ADDED: return added; case BIT_MODIFIED: return modified; case BIT_CONFLICT: return conflict; case BIT_IGNORE: return ignore; case BIT_DIR: return dir; default: return null; } } synchronized void remove(IPath path) { remove(path, removed); remove(path, missing); remove(path, unknown); remove(path, added); remove(path, modified); remove(path, conflict); remove(path, ignore); remove(path, dir); } static void remove(IPath path, PathsSet set) { if(!set.isEmpty()) { set.remove(path); } } } private MercurialStatusCache() { super(); bitMap = new BitMap(); ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE); } public static MercurialStatusCache getInstance() { return MercurialStatusCacheHolder.INSTANCE; } /** * Checks if status for given project is known. * * @param project * the project to be checked * @return true if known, false if not. */ public boolean isStatusKnown(IProject project) { return project != null && knownStatus.contains(project); } /** * Gets the status of the given resource from cache. The returned BitSet contains a BitSet of the status flags set. * * The flags correspond to the BIT_* constants in this class. * * @param resource * the resource to get status for. * @return the BitSet with status flags, MAY RETURN NULL, if status is unknown yet */ public Integer getStatus(IResource resource) { IPath location = resource.getLocation(); return getStatus(location); } /** * Gets the status of the given path from cache. The returned BitSet contains a BitSet of the status flags set. * * The flags correspond to the BIT_* constants in this class. * * @param location * the absolute file system path to get status for (can be null). * @return the BitSet with status flags, MAY RETURN NULL, if status is unknown yet */ private Integer getStatus(IPath location) { return location != null? statusMap.get(location) : null; } public boolean isSupervised(IResource resource) { return isSupervised(resource, resource.getLocation()); } public boolean isSupervised(IResource resource, IPath path) { if(path == null){ return false; } Integer statusInt = statusMap.get(path); if(statusInt == null){ return false; } Assert.isNotNull(resource); IProject project = resource.getProject(); if (path.equals(project.getLocation())) { return MercurialTeamProvider.isHgTeamProviderFor(project); } int status = statusInt.intValue(); int highestBit = Bits.highestBit(status); switch (highestBit) { case BIT_IGNORE: case BIT_UNKNOWN: if (resource.getType() != IResource.FILE && highestBit != BIT_IGNORE) { // check for Eclipse ignore settings if (Team.isIgnoredHint(resource)) { return false; } // a directory is still supervised if one of the lower bits set return Bits.contains(status, DIR_SUPERVISED_MASK); } return false; } return true; } public boolean isAdded(IPath path) { Assert.isNotNull(path); Integer statusInt = statusMap.get(path); if(statusInt == null){ return false; } int status = statusInt.intValue(); if (Bits.highestBit(status) == BIT_ADDED) { File fileSystemResource = path.toFile(); if (fileSystemResource.isDirectory()) { return Bits.contains(status, DIR_NOT_ADDED_MASK); } return true; } return false; } public boolean isDirectory(IPath location) { if(location == null){ return false; } return bitMap.get(BIT_DIR).contains(location); } public boolean isRemoved(IResource resource) { Assert.isNotNull(resource); Integer status = getStatus(resource); if(status == null){ return false; } return Bits.contains(status.intValue(), BIT_REMOVED); } public boolean isUnknown(IResource resource) { Assert.isNotNull(resource); Integer status = getStatus(resource); if(status == null){ // since we track everything now, all "unknown" files are really unknown return true; } return Bits.contains(status.intValue(), BIT_UNKNOWN); } public boolean isIgnored(IResource resource) { Assert.isNotNull(resource); Integer status = getStatus(resource); if(status == null) { if (isStatusKnown(resource.getProject())) { // it seems that original autors intentionally do not tracked status for // ignored files. I guess the reason was performance: for a java project, // including "ignored" class files would double the cache size... return true; } return false; } return Bits.contains(status.intValue(), BIT_IGNORE); } /** * @param location * the absolute file system path to get status for (can be null). * @return true if the cache knows that the given path should be ignored by Mercurial */ public boolean isIgnored(IPath location) { Integer status = getStatus(location); if(status == null) { return false; } return Bits.contains(status.intValue(), BIT_IGNORE); } /** * @see #BIT_CLEAN */ public boolean isClean(IResource resource) { return isStatus(resource, BIT_CLEAN); } /** * @see #BIT_CONFLICT */ public boolean isConflict(IResource resource) { return isStatus(resource, BIT_CONFLICT); } private boolean isStatus(IResource resource, int flag) { Assert.isNotNull(resource); Integer status = getStatus(resource); if(status == null){ return false; } return Bits.contains(status.intValue(), flag); } /** * * @param statusBit * @param parent * @return may return null, if no paths for given parent and bitset are known */ private List getPaths(int statusBit, IPath parent){ boolean isMappedState = statusBit != BIT_CLEAN && statusBit != BIT_IMPOSSIBLE; if(!isMappedState) { return null; } PathsSet all = bitMap.get(statusBit); if(all.isEmpty()){ return null; } return all.getChildren(parent); } /** * * @param statusBit * @param parent * @return may return null, if no paths for given parent and bitset are known */ private List getDirectChildren(int statusBit, IPath parent){ boolean isMappedState = statusBit != BIT_CLEAN && statusBit != BIT_IMPOSSIBLE; if(!isMappedState) { return null; } PathsSet all = bitMap.get(statusBit); if(all.isEmpty()){ return null; } return all.getDirectChildren(parent); } public Set getFiles(int statusBits, IContainer folder){ Set resources = getResources(statusBits, folder); Set files = new HashSet(); for (IResource resource : resources) { IPath location = resource.getLocation(); if(resource instanceof IFile && location != null && !location.toFile().isDirectory()){ files.add((IFile) resource); } } return files; } public Set getResources(int statusBits, IContainer folder){ // Possible optimization: don't walk the entry set. Call folder.accept() and query statusMap // individually for each. Set resources; HgRoot hgRoot = MercurialTeamProvider.getHgRoot(folder); if(hgRoot == null) { return Collections.emptySet(); } boolean isMappedState = statusBits != BIT_CLEAN && statusBits != BIT_IMPOSSIBLE && Bits.cardinality(statusBits) == 1; if(isMappedState){ PathsSet set = bitMap.get(statusBits); if(set == null || set.isEmpty()){ return Collections.emptySet(); } IPath parentPath = ResourceUtils.getPath(folder); if(parentPath.isEmpty()) { return Collections.emptySet(); } resources = new HashSet(); List children = set.getChildren(parentPath); if(children != null) { for (IPath path : children) { // TODO try to use container.getFile (performance?) // we don't know if it is a file or folder... IResource tmp; if(isDirectory(path)) { tmp = hgRoot.getResource().getFolder(hgRoot.toRelative(path)); } else { tmp = hgRoot.getResource().getFile(hgRoot.toRelative(path)); } if(tmp != null) { resources.add(tmp); } } } } else { resources = new HashSet(); Set> entrySet = statusMap.entrySet(); IPath parentPath = ResourceUtils.getPath(folder); if(parentPath.isEmpty()) { return Collections.emptySet(); } IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); for (Entry entry : entrySet) { Integer status = entry.getValue(); if(status != null && Bits.contains(status.intValue(), statusBits)){ IPath path = entry.getKey(); if(!ResourceUtils.isPrefixOf(parentPath, path)) { continue; } // we don't know if it is a file or folder... IPath relative = hgRoot.toRelative(path); if(relative.isEmpty()) { resources.add(hgRoot.getResource()); continue; } IResource tmp; if(isDirectory(path)) { tmp = hgRoot.getResource().getFolder(relative); } else { tmp = root.getFileForLocation(path); if(tmp != null) { if(!ResourceUtils.isPrefixOf(parentPath, path)) { tmp = null; } } else { tmp = root.getContainerForLocation(path); if(tmp != null) { if(!ResourceUtils.isPrefixOf(parentPath, path)) { tmp = null; } else { setStatus(path, status, true); } } } if(tmp == null) { if(path.toFile().isDirectory()) { setStatus(path, status, true); tmp = hgRoot.getResource().getFolder(relative); } else { tmp = hgRoot.getResource().getFile(relative); } } } if(tmp != null) { resources.add(tmp); } } } } return resources; } private static IProgressMonitor checkMonitor(IProgressMonitor monitor){ if(monitor == null){ return new NullProgressMonitor(); } return monitor; } /** * Refreshes the local repository status for all projects under the given hg root * and notifies the listeners about changes. No refresh of changesets. */ public void refreshStatus(HgRoot root, IProgressMonitor monitor) throws HgException { Assert.isNotNull(root); monitor = checkMonitor(monitor); monitor.subTask(NLS.bind(Messages.mercurialStatusCache_Refreshing, root.getName())); // find all subrepos under the specified root // in general we can have several projects under the same root // but due to subrepositories we can also have several roots under the same project Set repos; if(enableSubrepos){ repos = HgSubreposClient.findSubrepositoriesRecursively(root); } else { repos = new HashSet(); } repos.add(root); // find all projects that are under the root and any of its subrepos. Each project can only // be under one HgRoot (it can contain more roots, but that's not relevant at this point) RootResourceSet projects = new RootResourceSet(); for(HgRoot repo : repos){ // fix for issue #19998 - call possibly blocking code outside the lock on statusUpdateLock Assert.isNotNull(repo.getResource()); for(IProject proj : ResourceUtils.getProjects(repo)){ projects.add(repo, proj); } } Set changed = new HashSet(); synchronized (statusUpdateLock) { // build a map of project->projectPath for all projects under the specified root // as well as projects under the subrepos of the specified root Map pathMap = new HashMap(); Iterator iterator = projects.resourceIterator(); while (iterator.hasNext()) { IProject project = iterator.next(); if (!project.isOpen() || !MercurialTeamProvider.isHgTeamProviderFor(project)) { iterator.remove(); continue; } // clear status for project if(knownStatus.contains(project)) { clear(project, false); } monitor.worked(1); if(monitor.isCanceled()){ return; } IPath location = project.getLocation(); if(location == null) { iterator.remove(); continue; } pathMap.put(project, location); } // for the Root and all its subrepos // we have to iterate over repos instead of projects.getRoot(), because there may be a single project with lot of subrepos inside for(HgRoot repo : repos){ // get status and branch for hg root String output = HgStatusClient.getStatusWithoutIgnored(repo); String[] mergeStatus = HgStatusClient.getIdMergeAndBranch(repo); String currentChangeSetId = mergeStatus[0]; LocalChangesetCache.getInstance().checkLatestChangeset(repo, currentChangeSetId); String mergeNode = mergeStatus[1]; String branch = mergeStatus[2]; // update status of all files in the root that are also contained in projects inside pathMap String[] lines = NEWLINE.split(output); changed.addAll(parseStatus(repo, pathMap, lines, false)); MercurialTeamProvider.setCurrentBranch(branch, repo); // Set the merge status of the root itself setMergeStatus(repo, mergeNode); // set the projects status information // this will happen exactly once for each project (since each project is only under one root) Set repoProjects = projects.getResources(repo); if(repoProjects != null){ for (IProject project : repoProjects) { knownStatus.add(project); setMergeStatus(project, mergeNode); } } changed.addAll(checkForConflict(repo)); monitor.worked(1); if(monitor.isCanceled()){ return; } } knownStatus.add(root.getResource()); } notifyChanged(changed, false); monitor.worked(1); } /** * Refreshes local repository status and notifies the listeners about changes. No refresh of changesets. */ public void refreshStatus(IResource res, IProgressMonitor monitor) throws HgException { Assert.isNotNull(res); monitor = checkMonitor(monitor); monitor.subTask(NLS.bind(Messages.mercurialStatusCache_Refreshing, res.getName())); IProject project = res.getProject(); if (!project.isOpen() || !MercurialTeamProvider.isHgTeamProviderFor(res)) { return; } // find all the subrepos that are inside the resource Set repos; HgRoot root = MercurialTeamProvider.getHgRoot(res); if(enableSubrepos && root != null){ // find the reposoritory in which the resource is repos = HgSubreposClient.findSubrepositoriesRecursivelyWithin(root, res); } else { repos = new HashSet(); } if(root != null) { repos.add(root); } Set changed = new HashSet(); IPath projectLocation = project.getLocation(); if(projectLocation == null) { return; } for(HgRoot repo : repos){ // fix for issue #19998 - call possibly blocking code outside the lock on statusUpdateLock Assert.isNotNull(repo.getResource()); } synchronized (statusUpdateLock) { // clear status for files, folders or project if(res instanceof IProject && knownStatus.contains(project)){ clear(project, false); } else { clearStatusCache(res); } monitor.worked(1); if(monitor.isCanceled()){ return; } for (HgRoot repo : repos) { // Call hg to get the status of the repository String output = HgStatusClient.getStatusWithoutIgnored(repo, res); monitor.worked(1); if(monitor.isCanceled()){ return; } // parse the hg result String[] lines = NEWLINE.split(output); Map pathMap = new HashMap(); pathMap.put(project, projectLocation); changed.addAll(parseStatus(repo, pathMap, lines, !(res instanceof IProject))); if( !(res instanceof IProject) && !changed.contains(res)){ // fix for issue 10155: No status update after reverting changes on .hgignore changed.add(res); if(res instanceof IFolder){ IFolder folder = (IFolder) res; ResourceUtils.collectAllResources(folder, changed); } } // refresh the status of the HgRoot we are processing try { if(res instanceof IProject || repo != root){ String[] mergeStatus = HgStatusClient.getIdMergeAndBranch(repo); String id = mergeStatus[0]; LocalChangesetCache.getInstance().checkLatestChangeset(repo, id); String mergeNode = mergeStatus[1]; String branch = mergeStatus[2]; setMergeStatus(repo, mergeNode); MercurialTeamProvider.setCurrentBranch(branch, repo); if(repo == root){ // the project is under the current HgRoot, update its status as well setMergeStatus((IProject)res, mergeNode); } } } catch (HgException e) { throw new HgException(Messages.mercurialStatusCache_FailedToRefreshMergeStatus, e); } } if(res instanceof IProject){ knownStatus.add(project); } } if(monitor.isCanceled()){ return; } monitor.worked(1); // TODO shouldn't this go in the block above? changed.addAll(checkForConflict(project)); if(monitor.isCanceled()){ return; } monitor.worked(1); notifyChanged(changed, false); monitor.worked(1); } /** * @param res * @return true if a change of given file can trigger a project status update * @throws HgException */ public static boolean canTriggerFullCacheUpdate(IResource res) throws HgException { if(!(res instanceof IFile)){ return false; } return ".hgignore".equals(res.getName()); } /** * @param folder non null resource * @return non null set of all child entries managed by this cache */ private Set getChildrenFromCache(IContainer folder) { IPath parentPath = ResourceUtils.getPath(folder); return getPathChildrenFromCache(parentPath); } /** * @param parentPath * @return non null set of all child entries managed by this cache */ private Set getPathChildrenFromCache(IPath parentPath) { Set children = new HashSet(); // empty or root paths shouldn't be tracked. if(parentPath.isEmpty()) { return children; } Set keySet = statusMap.keySet(); for (IPath path : keySet) { if(path != null && ResourceUtils.isPrefixOf(parentPath, path)) { children.add(path); } } children.remove(parentPath); return children; } private Set checkForConflict(final IProject project) throws HgException { List status = HgResolveClient.list(project); Set changed = new HashSet(); Set members = getLocalMembers(project); for (IResource res : members) { if(removeConflict(res.getLocation())){ changed.add(res); } } if(removeConflict(project.getLocation())){ changed.add(project); } for (FlaggedAdaptable flaggedAdaptable : status) { IFile file = (IFile) flaggedAdaptable.getAdapter(IFile.class); if (flaggedAdaptable.getFlag() == CHAR_UNRESOLVED && file != null) { changed.addAll(addConflict(file)); } } return changed; } private Set checkForConflict(final HgRoot hgRoot) throws HgException { List status = HgResolveClient.list(hgRoot); Set changed = new HashSet(); IPath parentPath = new Path(hgRoot.getAbsolutePath()); List members = getPaths(BIT_CONFLICT, parentPath); if(members != null){ for (int i = 0; i < members.size(); i++) { IPath childPath = members.get(i); if(removeConflict(childPath)){ IFile fileHandle = ResourceUtils.getFileHandle(childPath); if(fileHandle != null) { changed.add(fileHandle); } } } } for (FlaggedAdaptable flaggedAdaptable : status) { IFile file = (IFile) flaggedAdaptable.getAdapter(IFile.class); if (flaggedAdaptable.getFlag() == CHAR_UNRESOLVED && file != null) { changed.addAll(addConflict(file)); } } return changed; } private static final Pattern NEWLINE = Pattern.compile("\n"); /** * @param lines must contain file paths as paths relative to the hg root * @param pathMap multiple projects (from this hg root) as input * @param propagateAllStates true to propagate all changes in children states to parents, * e.g. both transition from clean to dirty state and from dirty to clean state. * If false, then only dirty state is propagated to parents. * * @return set with resources to refresh */ private Set parseStatus(HgRoot root, Map pathMap, String[] lines, boolean propagateAllStates) { long start = 0; if(debug){ start = System.currentTimeMillis(); } // we need the project for performance reasons - gotta hand it to // addToProjectResources Set changed = new HashSet(); List strangeStates = new ArrayList(); // Make values in the path map canonical try { for (Iterator it = pathMap.keySet().iterator(); it.hasNext();) { IProject key = it.next(); pathMap.put(key, Path.fromOSString(pathMap.get(key).toFile().getCanonicalPath())); } } catch(IOException e) { MercurialEclipsePlugin.logError("Unexpected error - paths should be canonicalizable", e); } for (String line : lines) { if(line.length() <= 2){ strangeStates.add(line); continue; } char space = line.charAt(1); int bit = getBit(line.charAt(0)); if(bit == BIT_IMPOSSIBLE || space != ' '){ strangeStates.add(line); continue; } String localName = line.substring(2); IResource member = findMember(pathMap, root, localName, bit == BIT_REMOVED || bit == BIT_MISSING); // doesn't belong to our project (can happen if root is above project level) // or simply deleted, so can't be found... if (member == null) { continue; } Integer bitSet; if (bit == BIT_UNKNOWN && Team.isIgnoredHint(member)) { bitSet = IGNORE; } else { bitSet = Integer.valueOf(bit); changed.add(member); } if(!member.isLinked(IResource.CHECK_ANCESTORS)) { setStatus(member.getLocation(), bitSet, member.getType() == IResource.FOLDER); changed.addAll(setStatusToAncestors(member, bitSet, propagateAllStates)); } } if(debug && strangeStates.size() > 0){ IStatus [] states = new IStatus[strangeStates.size()]; for (int i = 0; i < states.length; i++) { states[i] = MercurialEclipsePlugin.createStatus(strangeStates.get(i), IStatus.OK, IStatus.INFO, null); } String message = "Strange status received from hg"; MultiStatus st = new MultiStatus(MercurialEclipsePlugin.ID, IStatus.OK, states, message, new Exception(message)); MercurialEclipsePlugin.getDefault().getLog().log(st); } if(debug){ System.out.println("Parse status took: " + (System.currentTimeMillis() - start)); } return changed; } /** * Parse status output. Future: merge with above method? * * @param status * Status output * @param hgRoot * The root to use for the {@link FileStatus} * @return A non-null list. */ public static List parseStatus(String status, HgRoot hgRoot) { List list = new ArrayList(); for (String line : NEWLINE.split(status)) { if (line.length() <= 2 || line.charAt(1) != ' ') { continue; } char c = line.charAt(0); FileStatus.Action action; if (c == CHAR_ADDED) { action = FileStatus.Action.ADDED; } else if (c == CHAR_REMOVED) { action = FileStatus.Action.REMOVED; } else if (c == CHAR_MODIFIED) { action = FileStatus.Action.MODIFIED; } else { continue; } list.add(new FileStatus(action, line.substring(2), hgRoot)); } return list; } /** * @return return null if resource is not known or linked and not under the same root */ private static IResource findMember(Map pathMap, final HgRoot hgRoot, final String repoRelPath, final boolean allowForce) { IPath hgRootPath = hgRoot.getIPath(); // determine absolute path IPath path = hgRootPath.append(repoRelPath); Set> set = pathMap.entrySet(); for (Entry entry : set) { IPath projectLocation = entry.getValue(); // determine project relative path int equalSegments = path.matchingFirstSegments(projectLocation); if(equalSegments == projectLocation.segmentCount() || hgRootPath.equals(projectLocation)) { IProject project = entry.getKey(); IPath segments = path.removeFirstSegments(equalSegments); IResource result = project.findMember(segments); if (result == null && allowForce) { result = project.getFile(segments); } return result; } } IPath rel = new Path(repoRelPath); if(allowForce) { return hgRoot.getResource().getFile(rel); } return hgRoot.getResource().findMember(rel); } private void setStatus(IPath location, Integer status, boolean isDir) { if(location == null || location.isEmpty()){ return; } statusMap.put(location, status); bitMap.put(location, status); if(isDir){ bitMap.put(location, Integer.valueOf(BIT_DIR)); } } /** * * @param child * @param childState * @param propagateAllStates true to propagate all changes in children states to parents, * e.g. both transition from clean to dirty state and from dirty to clean state. * If false, then only dirty state is propagated to parents. * @return */ private Set setStatusToAncestors(IResource child, Integer childState, boolean propagateAllStates) { Set ancestors = new HashSet(); IContainer parent = child.getParent(); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); for (; parent != null && parent != root; parent = parent.getParent()) { IPath parentLocation = parent.getLocation(); if(parentLocation == null){ continue; } int parentBitSet = BIT_CLEAN; Integer parentBits = statusMap.get(parentLocation); if(parentBits != null){ parentBitSet = parentBits.intValue(); } int childBitSet = childState.intValue(); // should not propagate ignores states to parents // TODO issue 237: "two status feature" boolean childIsDirty = Bits.contains(childBitSet, MODIFIED_MASK); childBitSet = Bits.clear(childBitSet, IGNORED_MASK); if(childIsDirty) { childBitSet |= BIT_MODIFIED; } else { childBitSet |= BIT_CLEAN; } if (child.getType() == IResource.PROJECT) { childBitSet |= parentBitSet; } else if (!childIsDirty) { // child is clean, and we have "usual" files and folders if (!propagateAllStates) { if(parentBits != null){ // parent status known: just exit here. Saves us A LOT of time return ancestors; } } else { // propagate clean state back to parents - e.g. if file was reverted, // and there are NO OTHER dirty children, parent state should change to "clean" if (parent.isAccessible() && !parent.isTeamPrivateMember()) { MemberStatusVisitor visitor = new MemberStatusVisitor(parentLocation, childBitSet); // we have to traverse all possible "dirty" children and change // parent state from "dirty" to "clean"... boolean visit = checkChildrenFor(parentLocation, visitor, BIT_MODIFIED); if (visit) { visit = checkChildrenFor(parentLocation, visitor, BIT_UNKNOWN); } if (visit) { visit = checkChildrenFor(parentLocation, visitor, BIT_ADDED); } if (visit) { visit = checkChildrenFor(parentLocation, visitor, BIT_REMOVED); } if (visit) { visit = checkChildrenFor(parentLocation, visitor, BIT_MISSING); } childBitSet = visitor.bitSet; } } } setStatus(parentLocation, Integer.valueOf(childBitSet), parent.getType() == IResource.FOLDER); ancestors.add(parent); } return ancestors; } private boolean checkChildrenFor(IPath location, MemberStatusVisitor visitor, int stateBit) { List resources = getDirectChildren(stateBit, location); if(resources == null){ return true; } for (int i = 0; i < resources.size(); i++) { IPath child = resources.get(i); boolean continueVisit = visitor.visit(child); if(!continueVisit){ return false; } } return true; } private static int getBit(char status) { switch (status) { case CHAR_MISSING: return BIT_MISSING; case CHAR_REMOVED: return BIT_REMOVED; case CHAR_IGNORED: return BIT_IGNORE; case CHAR_CLEAN: return BIT_CLEAN; case CHAR_UNKNOWN: return BIT_UNKNOWN; case CHAR_ADDED: return BIT_ADDED; case CHAR_MODIFIED: return BIT_MODIFIED; default: return BIT_IMPOSSIBLE; } } public void resourceChanged(IResourceChangeEvent event) { if (event.getType() != IResourceChangeEvent.POST_CHANGE) { return; } IResourceDelta delta = event.getDelta(); final Map> changed = new HashMap>(); final Map> added = new HashMap>(); final Map> removed = new HashMap>(); IResourceDeltaVisitor visitor = new ResourceDeltaVisitor(removed, changed, added); try { // walk tree delta.accept(visitor); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return; } final Set changedProjects = new HashSet(changed.keySet()); changedProjects.addAll(added.keySet()); changedProjects.addAll(removed.keySet()); for (IProject project : changedProjects) { RootResourceSet addedSet = added.get(project); RootResourceSet removedSet = removed.get(project); RootResourceSet changedSet = changed.get(project); projectChanged(project, addedSet, removedSet, changedSet); } } private void projectChanged(final IProject project, final RootResourceSet addedSet, final RootResourceSet removedSet, final RootResourceSet changedSet) { ProjectUpdateJob updateJob = new ProjectUpdateJob(removedSet, changedSet, project, addedSet); Job[] jobs = Job.getJobManager().find(ProjectUpdateJob.class); for (Job job : jobs) { if(updateJob.equals(job)){ job.cancel(); if(debug){ System.out.println("Status cache update cancelled for: " + ((ProjectUpdateJob) job).project.getName()); } } } // schedule async and with delay to avoid multiple refreshes on the same subject // do not join in the resource notification loop updateJob.schedule(300); } /** * Refreshes Status of resources in batches and notifies the listeners about changes * * @param resources * may be null. If not null, then all elements must be from the given project. If null, no refresh will * happen. If the set contains a project, it is ignored * @param project * not null. The project which resources state has to be updated */ private void refreshStatus(final RootResourceSet resources, IProject project) throws HgException { if (resources == null || resources.isEmpty()) { return; } // project status wanted, no batching needed if(resources.remove(project) && resources.isEmpty()){ return; } Set changed = new HashSet(); for(Map.Entry> entry : resources.entrySet()){ changed.addAll(updateStatusInRoot(project, entry.getKey(), entry.getValue())); } if(!resources.isEmpty()) { changed.addAll(checkForConflict(project)); } notifyChanged(changed, false); return; } private Set updateStatusInRoot(IProject project, HgRoot root, Set resources) throws HgException { int batchSize = getStatusBatchSize(); List currentBatch = new ArrayList(); Set changed = new HashSet(); boolean listFileEnabled = HgFeatures.LISTFILE.isEnabled(); for (Iterator iterator = resources.iterator(); iterator.hasNext();) { IResource resource = iterator.next(); // status for single resource is batched if (!resource.isTeamPrivateMember()) { currentBatch.add(resource); } if(!listFileEnabled) { if (currentBatch.size() % batchSize == 0 || !iterator.hasNext()) { // call hg with batch updateStatusBatched(project, root, currentBatch, changed); currentBatch.clear(); } } } if(listFileEnabled) { updateStatusBatched(project, root, currentBatch, changed); } return changed; } private void updateStatusBatched(IProject project, HgRoot root, List currentBatch, Set changed) throws HgException { // fix for issue #19998 - call possibly blocking code outside the lock on statusUpdateLock Assert.isNotNull(root.getResource()); synchronized (statusUpdateLock) { for (IResource curr : currentBatch) { boolean unknown = (curr instanceof IContainer) || isUnknown(curr); clearStatusCache(curr); if (unknown && !curr.exists()) { // remember parents of deleted files: we must update their state IContainer directory = ResourceUtils.getFirstExistingDirectory(curr); while(directory != null) { changed.add(directory); IPath parentPath = directory.getLocation(); if(parentPath != null) { bitMap.remove(parentPath); statusMap.remove(parentPath); } directory = ResourceUtils.getFirstExistingDirectory(directory.getParent()); } // recursive recalculate parents state // TODO better to combine it with parse status below... setStatusToAncestors(curr, CLEAN, true); } } String output = HgStatusClient.getStatusWithoutIgnored(root, currentBatch); String[] lines = NEWLINE.split(output); Map pathMap = new HashMap(); IPath projectLocation = project.getLocation(); if(projectLocation != null) { pathMap.put(project, projectLocation); } changed.addAll(parseStatus(root, pathMap, lines, true)); } } public void clearStatusCache(IResource resource) { if(resource instanceof IProject && !resource.exists()) { return; } IPath parentPath = ResourceUtils.getPath(resource); synchronized (statusUpdateLock) { if(resource instanceof IContainer && !parentPath.isEmpty()){ // same can be done via getChildrenFromCache(resource), but we // iterating/removing over keyset directly to reduce memory consumption Set entrySet = statusMap.keySet(); Iterator it = entrySet.iterator(); while (it.hasNext()) { IPath path = it.next(); if(path != null && ResourceUtils.isPrefixOf(parentPath, path)) { it.remove(); bitMap.remove(path); } } } else { bitMap.remove(parentPath); statusMap.remove(parentPath); } } } private int getStatusBatchSize() { return statusBatchSize; } /** * @param resource * @return never null. Set will contain all known files under the given directory, * or the file itself if given resource is not a directory */ public Set getLocalMembers(IResource resource) { Set members = new HashSet(); if(resource instanceof IContainer){ IContainer container = (IContainer) resource; IPath location = container.getLocation(); if(location == null) { return members; } int segmentCount = location.segmentCount(); Set children = getChildrenFromCache(container); for (IPath path : children) { IFile iFile = container.getFile(path.removeFirstSegments(segmentCount)); if(iFile != null) { members.add(iFile); } } } else { members.add(resource); } return members; } @Override protected void projectDeletedOrClosed(IProject project) { clear(project, false); // dirty fix for issue 14113: various actions fail for recursive projects // if the root project is closed: we simply refresh the state for remaining projects IPath path = project.getLocation(); if(path == null) { return; } Collection hgRoots = MercurialRootCache.getInstance().getKnownHgRoots(); for (HgRoot hgRoot : hgRoots) { // only start refresh for projects located at the repository root if(!hgRoot.getIPath().equals(path)) { continue; } List projects = MercurialTeamProvider.getKnownHgProjects(hgRoot); projects.remove(project); // only start refresh if there is at least one project more in the repo if(projects.size() > 0) { new RefreshStatusJob("Status update", hgRoot).schedule(); } } } public void clear(HgRoot root, boolean notify) { Set projects = ResourceUtils.getProjects(root); clearMergeStatus(root.getIPath()); for (IProject project : projects) { clear(project, false); if(notify) { notifyChanged(project, false); } } } public void clear(IProject project, boolean notify) { clearMergeStatus(project); clearStatusCache(project); knownStatus.remove(project); if(notify) { notifyChanged(project, false); } } /** * Sets conflict marker on resource status */ private Set addConflict(IResource local) { IPath location = local.getLocation(); if(location == null){ return Collections.emptySet(); } Integer status = statusMap.get(location); boolean isDir = local.getType() == IResource.FOLDER; if(status == null){ status = CONFLICT; setStatus(location, CONFLICT, isDir); } else { status = Integer.valueOf(status.intValue() | BIT_CONFLICT); setStatus(location, status, isDir); } Set changed = setStatusToAncestors(local, status, false); changed.add(local); return changed; } /** * Removes conflict marker on resource status * * @param local non null * @return true if there was a conflict and now it is removed */ private boolean removeConflict(IPath local) { if(local == null){ return false; } Integer statusInt = statusMap.get(local); if(statusInt == null){ return false; } int status = statusInt.intValue(); if(Bits.contains(status, BIT_CONFLICT)) { status = Bits.clear(status, BIT_CONFLICT); setStatus(local, Integer.valueOf(status), false); return true; } return false; } @Override protected void configureFromPreferences(IPreferenceStore store){ enableSubrepos = store.getBoolean(MercurialPreferenceConstants.PREF_ENABLE_SUBREPO_SUPPORT); // TODO: group batches by repo root statusBatchSize = store.getInt(MercurialPreferenceConstants.STATUS_BATCH_SIZE); // STATUS_BATCH_SIZE; if (statusBatchSize <= 0) { store.setValue(MercurialPreferenceConstants.STATUS_BATCH_SIZE, STATUS_BATCH_SIZE); statusBatchSize = STATUS_BATCH_SIZE; MercurialEclipsePlugin.logWarning(Messages.mercurialStatusCache_BatchSizeForStatusCommandNotCorrect, null); } } private void clearMergeStatus(IPath path) { mergeChangesetIds.remove(path); } public void clearMergeStatus(IProject res) { // clear merge status in Eclipse IPath location = res.getLocation(); if(location != null) { mergeChangesetIds.remove(location); } } public void setMergeStatus(HgRoot hgRoot, String mergeChangesetId) { Set projects = ResourceUtils.getProjects(hgRoot); for (IProject project : projects) { // clear merge status in Eclipse setMergeStatus(project, mergeChangesetId); } setMergeStatus(hgRoot.getIPath(), mergeChangesetId); } private void setMergeStatus(IPath path, String mergeChangesetId) { if(mergeChangesetId != null){ mergeChangesetIds.put(path, mergeChangesetId); } else{ // ConcurrentHashMap doesn't support null values, but removing is the same a putting a null value mergeChangesetIds.remove(path); } } private void setMergeStatus(IProject project, String mergeChangesetId) { // set merge status in Eclipse IPath location = project.getLocation(); if(location == null) { return; } if(mergeChangesetId != null){ mergeChangesetIds.put(location, mergeChangesetId); }else{ // ConcurrentHashMap doesn't support null values, but removing is the same a putting a null value mergeChangesetIds.remove(location); } } public boolean isMergeInProgress(IResource res) { return getMergeChangesetId(res.getProject()) != null; } public boolean isMergeInProgress(HgRoot hgRoot) { return getMergeChangesetId(hgRoot) != null; } /** * @param path A full, absolute path relative to the workspace. non null * @return the version:short_changeset_id OR full_changeset_id string if the root is being merged, otherwise null */ public String getMergeChangesetId(IPath path){ return mergeChangesetIds.get(path); } /** * @param project non null * @return the version:short_changeset_id OR full_changeset_id string if the root is being merged, otherwise null */ public String getMergeChangesetId(IResource project) { IPath location = project.getLocation(); if(location == null) { return null; } return getMergeChangesetId(location); } /** * @param hgRoot non null * @return the version:short_changeset_id OR full_changeset_id string if the root is being merged, otherwise null */ public String getMergeChangesetId(HgRoot hgRoot) { Set projects = ResourceUtils.getProjects(hgRoot); if(!projects.isEmpty()) { return getMergeChangesetId(projects.iterator().next()); } return null; } /** * Determine if the given file is currently in conflict because of a workspace update, ie * not a normal merge or rebase. * * @param file * The file to check * @return True if the file is in conflict and neither a rebase or merge is in progress. */ public boolean isWorkspaceUpdateConfict(IFile file) { if (isConflict(file)) { // Ideally we would save more state so we know what mode we are actually in. For now // just check we're not merging or rebasing. Transplant conflicts don't set files in // conflict mode. Are there other modes? HgRoot root = MercurialTeamProvider.getHgRoot(file); if (root != null && !isMergeInProgress(root) && !HgRebaseClient.isRebasing(root)) { return true; } } return false; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/Messages.java000066400000000000000000000035271173713500500330020ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import org.eclipse.osgi.util.NLS; /** * @author bastian * */ public final class Messages extends NLS { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.team.cache.messages"; //$NON-NLS-1$ private Messages() { } public static String localChangesetCache_LogLimitLessThanZero; public static String localChangesetCache_LogLimitNotCorrectlyConfigured; public static String mercurialStatusCache_autoshare; public static String mercurialStatusCache_BatchSizeForStatusCommandNotCorrect; public static String mercurialStatusCache_FailedToRefreshMergeStatus; public static String mercurialStatusCache_Refreshing; public static String mercurialStatusCache_RefreshingProject; public static String mercurialStatusCache_RefreshingResources; public static String mercurialStatusCache_RefreshStatus; public static String mercurialStatusCache_UnknownStatus; public static String refreshJob_LoadingIncomingRevisions; public static String refreshJob_LoadingLocalRevisions; public static String refreshJob_LoadingOutgoingRevisionsFor; public static String refreshJob_UpdatingStatusAndVersionCache; public static String refreshStatusJob_OptainingMercurialStatusInformation; static { NLS.initializeMessages(BUNDLE_NAME, Messages.class); } } OutgoingChangesetCache.java000066400000000000000000000021411173713500500355040ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; /** * Cache for all changesets not present locally but existing on the server */ public final class OutgoingChangesetCache extends AbstractRemoteCache { private static OutgoingChangesetCache instance; private OutgoingChangesetCache() { super(Direction.OUTGOING); } public static synchronized OutgoingChangesetCache getInstance() { if (instance == null) { instance = new OutgoingChangesetCache(); } return instance; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/PathsSet.java000066400000000000000000000107711173713500500327650ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Andrei */ public class PathsSet { private static final int MAX_SEGMENTS = 20; private static final int MAX_NAME = 60; /** * first index is the (truncated) segments size, * second index is the (truncated) file name size */ private final Set [][] pathsMap; private final int initialSize; private final float initialLoad; private int size; @SuppressWarnings("unchecked") public PathsSet(int initialSize, float initialLoad) { this.initialSize = initialSize; this.initialLoad = initialLoad; pathsMap = new Set[MAX_SEGMENTS][MAX_NAME]; } public int size(){ return size; } public boolean isEmpty() { return size == 0; } public List getChildren(IPath parent){ List result = null; int segmentCount = parent.segmentCount(); // empty or root paths shouldn't be tracked. if(segmentCount == 0) { return null; } int pathKey = categorize(parent.lastSegment()); int startSegment = categorize(segmentCount) + 1; if(startSegment == MAX_SEGMENTS){ startSegment --; } synchronized (pathsMap) { for (int i = startSegment; i < MAX_SEGMENTS; i++) { for (int j = 0; j < MAX_NAME; j++) { Set possibleChildren = pathsMap[i][j]; if (possibleChildren == null) { continue; } for (IPath path : possibleChildren) { if (pathKey == categorize(path.segment(segmentCount - 1)) && (ResourceUtils.isPrefixOf(parent, path))) { if (result == null) { result = new ArrayList(); } result.add(path); } } } } } return result; } public List getDirectChildren(IPath parent) { List result = null; int segmentCount = parent.segmentCount(); // empty or root paths shouldn't be tracked. if(segmentCount == 0) { return null; } int pathKey = categorize(parent.lastSegment()); int startSegment = categorize(segmentCount) + 1; if(startSegment == MAX_SEGMENTS){ startSegment --; } synchronized (pathsMap) { for (int j = 0; j < MAX_NAME; j++) { Set possibleChildren = pathsMap[startSegment][j]; if (possibleChildren == null) { continue; } for (IPath path : possibleChildren) { if (pathKey == categorize(path.segment(segmentCount - 1)) && (ResourceUtils.isPrefixOf(parent, path))) { if (result == null) { result = new ArrayList(); } result.add(path); } } } } return result; } public void add(IPath path){ int sizeKey = categorize(path.segmentCount()); int pathKey = categorize(path.lastSegment()); synchronized (pathsMap){ Set paths = pathsMap[sizeKey][pathKey]; if(paths == null){ paths = new LinkedHashSet(initialSize, initialLoad); pathsMap[sizeKey][pathKey] = paths; } paths.add(path); size ++; } } public boolean contains(IPath path){ int sizeKey = categorize(path.segmentCount()); int pathKey = categorize(path.lastSegment()); synchronized (pathsMap){ Set paths = pathsMap[sizeKey][pathKey]; if(paths == null){ return false; } return paths.contains(path); } } public void remove(IPath path){ int sizeKey = categorize(path.segmentCount()); int pathKey = categorize(path.lastSegment()); synchronized (pathsMap){ Set paths = pathsMap[sizeKey][pathKey]; if(paths == null){ return; } paths.remove(path); if(paths.isEmpty()){ pathsMap[sizeKey][pathKey] = null; } size --; } } private static int categorize(int segmentsCount){ if(segmentsCount < MAX_SEGMENTS){ return segmentsCount; } return MAX_SEGMENTS - 1; } private static int categorize(String pathSegment){ if(pathSegment == null){ return 0; } int length = pathSegment.length(); if(length < MAX_NAME){ return length; } return 0; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/ProjectCache.java000066400000000000000000000070451173713500500335640ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.io.File; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * A collection of changesets for the given project - branch pair * @author Andrei */ public class ProjectCache { private final IProject project; private final SortedSet changesets; private final String branch; /** * @param project non null * @param branch null if no branch info is given (all branches) * @param changesets non null */ public ProjectCache(IProject project, String branch, SortedSet changesets) { this.project = project; this.branch = branch; this.changesets = changesets; } /** * @return never null */ public SortedSet getChangesets() { return changesets; } /** * @param resource * non null * @return a subset of known changesets where each changeset has a relationship with given * resource (e.g. resource was added/modified/removed). In case given resource cannot be * resolved to a file, or represents the hg root itself, return all known changesets. If * there is no matching related changeset, an empty set is returned. */ public SortedSet getChangesets(IResource resource) { SortedSet filtered = new TreeSet(); IPath rootRelative = null; mainLoop: for (ChangeSet cs : changesets) { if (rootRelative == null) { File path = ResourceUtils.getFileHandle(resource); if (path == null || path.getPath().length() == 0) { return changesets; } rootRelative = new Path(cs.getHgRoot().toRelative(path)); if (rootRelative.isEmpty()) { // hg root: return everything return changesets; } } List files = cs.getChangedFiles(); for (FileStatus fs : files) { if (rootRelative.equals(fs.getRootRelativePath())) { filtered.add(cs); continue mainLoop; } } } return filtered; } /** * @return null if no branch info is given (all branches) */ public String getBranch() { return branch; } /** * @return never null */ public IProject getProject() { return project; } public boolean isEmpty(){ return changesets.isEmpty(); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("ProjectCache ["); if (branch != null) { builder.append("branch="); builder.append(branch); builder.append(", "); } if (project != null) { builder.append("project="); builder.append(project); builder.append(", "); } if (changesets != null) { builder.append("changesets="); builder.append(changesets); } builder.append("]"); return builder.toString(); } } RefreshRootJob.java000066400000000000000000000140241173713500500340430ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - init * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; import org.eclipse.team.ui.history.IHistoryPage; import org.eclipse.team.ui.history.IHistoryView; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.MercurialHistoryPage; import com.vectrace.MercurialEclipse.model.HgRoot; /** * Refreshes working directory status, local changesets, incoming changesets and outgoing * changesets. If you only want to refresh the working directory status use {@link RefreshStatusJob}. * If you want additionally refresh Eclipse workspace data, use {@link RefreshWorkspaceStatusJob}. * *

* This job uses exclusive rule based on given hg root (see {@link HgRootRule}). It means, this job * never runs in parallel with any other job using the same rule on given hg root. * * @author Andrei Loskutov * @author Bastian Doetsch */ public class RefreshRootJob extends Job { public static final int LOCAL = 1 << 0; public static final int INCOMING = 1 << 1; public static final int OUTGOING = 1 << 2; /** right now only used by {@link RefreshWorkspaceStatusJob} */ public static final int WORKSPACE = 1 << 3; public static final int LOCAL_AND_INCOMING = LOCAL | INCOMING; public static final int LOCAL_AND_OUTGOING = LOCAL | OUTGOING; /** refresh local, incoming and outgoing cache. Does not include workspace refresh */ public static final int ALL = LOCAL | INCOMING | OUTGOING; protected final HgRoot hgRoot; private final int type; /** * If the flags are non zero, refreshes different mercurial caches for the given root. * @param hgRoot non null * @param flags one of RefreshRootJob flags */ public RefreshRootJob(HgRoot hgRoot, int flags) { this("Refreshing " + hgRoot.getName(), hgRoot, flags); } /** * If the flags are non zero, refreshes different mercurial caches for the given root. * @param name non null job name, shown to user * @param hgRoot non null * @param flags one of RefreshRootJob flags */ public RefreshRootJob(String name, HgRoot hgRoot, int flags) { super(name); Assert.isNotNull(hgRoot); this.hgRoot = hgRoot; this.type = flags; setRule(new HgRootRule(hgRoot)); } @Override protected IStatus run(IProgressMonitor monitor) { if((type & LOCAL) != 0){ if(monitor.isCanceled()){ return Status.CANCEL_STATUS; } trace("LOCAL"); monitor.subTask(Messages.refreshJob_LoadingLocalRevisions); LocalChangesetCache.getInstance().clear(hgRoot, true); monitor.worked(1); monitor.subTask(Messages.refreshJob_UpdatingStatusAndVersionCache); MercurialStatusCache statusCache = MercurialStatusCache.getInstance(); statusCache.clear(hgRoot, false); try { statusCache.refreshStatus(hgRoot, monitor); monitor.worked(1); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } updateHistoryView(); } if((type & INCOMING) != 0){ if(monitor.isCanceled()){ return Status.CANCEL_STATUS; } trace("INCOMING"); monitor.subTask(NLS.bind(Messages.refreshJob_LoadingIncomingRevisions, hgRoot.getName())); IncomingChangesetCache.getInstance().clear(hgRoot, true); monitor.worked(1); } if((type & OUTGOING) != 0){ if(monitor.isCanceled()){ return Status.CANCEL_STATUS; } trace("OUTGOING"); monitor.subTask(NLS.bind(Messages.refreshJob_LoadingOutgoingRevisionsFor, hgRoot.getName())); OutgoingChangesetCache.getInstance().clear(hgRoot, true); monitor.worked(1); } monitor.done(); return Status.OK_STATUS; } /** * Running in UI thread asynchronously */ private void updateHistoryView() { Display.getDefault().asyncExec(new Runnable() { public void run() { IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); for (IWorkbenchWindow ww : windows) { IViewPart view = ww.getActivePage().findView(IHistoryView.VIEW_ID); if(!(view instanceof IHistoryView)) { continue; } IHistoryView hview = (IHistoryView) view; IHistoryPage page = hview.getHistoryPage(); if(!(page instanceof MercurialHistoryPage)) { continue; } MercurialHistoryPage mhp = (MercurialHistoryPage) page; mhp.refresh(); } } }); } /** * @param step current job task, non null */ protected void trace(String step) { if(MercurialEclipsePlugin.getDefault().isDebugging()) { System.out.println("Refresh " + step + " for: " + hgRoot.getName()); } } @Override public boolean belongsTo(Object family) { return RefreshRootJob.class == family; } @Override public boolean shouldSchedule() { Job[] jobs = Job.getJobManager().find(RefreshRootJob.class); for (Job job : jobs) { if(isSimilar(job)){ // do not schedule me because exactly the same job is waiting to be started! return false; } } return true; } protected boolean isSimilar(Job job) { if(!(job instanceof RefreshRootJob)){ return false; } RefreshRootJob rootJob = (RefreshRootJob) job; int state = rootJob.getState(); return type == rootJob.type && (state == WAITING || state == SLEEPING) && hgRoot.equals(rootJob.hgRoot); } }RefreshStatusJob.java000066400000000000000000000071661173713500500344140ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - init * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.team.core.TeamException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * @author bastian * */ public class RefreshStatusJob extends Job { private static final MercurialStatusCache MERCURIAL_STATUS_CACHE = MercurialStatusCache .getInstance(); private final IProject project; private final HgRoot hgRoot; /** * true to re-check the project state before starting the job and if the project * state is known, cancel the job */ private boolean updateRootIfProjectUnknown; /** * Special constructor for job which ONLY then will be started, if the status of given * project is unknown at the time the jobs starts. * @param name non null * @param project non null * @param root non null */ public RefreshStatusJob(String name, IProject project, HgRoot root) { super(name); this.project = project; this.hgRoot = root; setRule(new HgRootRule(hgRoot)); updateRootIfProjectUnknown = true; } public RefreshStatusJob(String name, IProject project) { super(name); this.project = project; this.hgRoot = MercurialTeamProvider.getHgRoot(project); if(hgRoot != null) { setRule(new HgRootRule(hgRoot)); } } public RefreshStatusJob(String name, HgRoot root) { super(name); this.hgRoot = root; this.project = null; setRule(new HgRootRule(root)); } @Override protected IStatus run(IProgressMonitor monitor) { if(monitor.isCanceled()){ return Status.CANCEL_STATUS; } try { monitor.beginTask(Messages.refreshStatusJob_OptainingMercurialStatusInformation, 5); if(project != null && !updateRootIfProjectUnknown) { MERCURIAL_STATUS_CACHE.refreshStatus(project, monitor); } else { if(updateRootIfProjectUnknown){ if(MercurialStatusCache.getInstance().isStatusKnown(project)){ return Status.OK_STATUS; } } MERCURIAL_STATUS_CACHE.refreshStatus(hgRoot, monitor); } } catch (TeamException e) { MercurialEclipsePlugin.logError(e); } finally { monitor.done(); } return Status.OK_STATUS; } @Override public boolean belongsTo(Object family) { return RefreshStatusJob.class == family; } @Override public boolean shouldSchedule() { if(hgRoot == null){ // probably should never happen except if we are running on a project // which was just created or just removed return true; } Job[] jobs = Job.getJobManager().find(RefreshStatusJob.class); for (Job job : jobs) { HgRootRule rule = (HgRootRule) job.getRule(); if(hgRoot.equals(rule.getHgRoot()) && (job.getState() == WAITING || job.getState() == SLEEPING)){ return false; } } if(updateRootIfProjectUnknown){ return !MercurialStatusCache.getInstance().isStatusKnown(project); } return true; } }RefreshWorkspaceStatusJob.java000066400000000000000000000070631173713500500362670ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgBranchClient; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public final class RefreshWorkspaceStatusJob extends RefreshRootJob { private final boolean refreshWorkspaceOnly; /** * Refreshes all the projects of given root in the workspace. Does NOT refresh any * cache * @param root non null */ public RefreshWorkspaceStatusJob(HgRoot root) { this(root, WORKSPACE); } /** * Refreshes all the projects of given root in the workspace. If the flags are non zero, * additionally refreshes different mercurial caches for the root. * @param root non null * @param flags see {@link RefreshRootJob} flags. Zero flag value does nothing. */ public RefreshWorkspaceStatusJob(HgRoot root, int flags) { super(root, flags); this.refreshWorkspaceOnly = flags == WORKSPACE; } @Override protected IStatus run(IProgressMonitor monitor) { try { String branch = null; if(!refreshWorkspaceOnly) { trace("BRANCH"); branch = HgBranchClient.getActiveBranch(hgRoot); // update branch name MercurialTeamProvider.setCurrentBranch(branch, hgRoot); } Set projects = ResourceUtils.getProjects(hgRoot); if(!projects.isEmpty()){ trace(projects.size() + " WORKSPACE projects"); } for (IProject project : projects) { if(monitor.isCanceled()){ return Status.CANCEL_STATUS; } refreshProject(monitor, project); } if(!refreshWorkspaceOnly){ return super.run(monitor); } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } return Status.OK_STATUS; } private void refreshProject(IProgressMonitor monitor, IProject project) throws CoreException { if(!refreshWorkspaceOnly){ // reset merge properties MercurialStatusCache.getInstance().clearMergeStatus(project); } // refresh resources project.refreshLocal(IResource.DEPTH_INFINITE, monitor); } @Override public boolean belongsTo(Object family) { return RefreshWorkspaceStatusJob.class == family || super.belongsTo(family); } @Override public boolean shouldSchedule() { Job[] jobs = Job.getJobManager().find(RefreshWorkspaceStatusJob.class); for (Job job : jobs) { if(isSimilar(job)){ // do not schedule me because exactly the same job is waiting to be started! return false; } } return true; } @Override protected boolean isSimilar(Job job) { if(!(job instanceof RefreshWorkspaceStatusJob)){ return false; } return super.isSimilar(job); } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/RemoteData.java000066400000000000000000000142561173713500500332610ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.ChangeSet.Direction; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * Branch specific collection of remote data (changesets) for one remote repository. * This data can be queried by project. *

* Additionally, we should think if it may contain project unbound repository data (e.g. * files which are not located under any Eclipse project area). * @author Andrei */ public class RemoteData { private static final SortedSet EMPTY_SETS = Collections .unmodifiableSortedSet(new TreeSet()); private final Map projectMap; private final Direction direction; private final Map> changesets; private final RemoteKey key; public RemoteData(RemoteKey key, Direction direction) { this(key.getRepo(), key.getRoot(), key.getBranch(), direction, new HashMap>()); } public RemoteData(IHgRepositoryLocation repo, HgRoot root, String branch, Direction direction) { this(repo, root, branch, direction, new HashMap>()); } /** * @param changesets this map contains AT LEAST a key corresponding to the hgroot of * this data, and may also contain additional keys for one or more projects under * the given hgroot. * @param branch can be null (means all branches) */ public RemoteData(IHgRepositoryLocation repo, HgRoot root, String branch, Direction direction, Map> changesets) { super(); this.direction = direction; this.changesets = changesets; key = new RemoteKey(root, repo, branch); projectMap = new HashMap(); } public SortedSet getChangeSets(IResource resource){ if(resource == null || changesets.isEmpty()){ return EMPTY_SETS; } IProject project = resource.getProject(); if(project == null){ return EMPTY_SETS; } ProjectCache cache = projectMap.get(project); if(cache == null) { synchronized (projectMap) { populateCache(resource.getProject()); } return getChangeSets(resource); } if (cache.isEmpty()) { return EMPTY_SETS; } if(resource instanceof IProject){ return cache.getChangesets(); } return cache.getChangesets(resource); } /** * @return ALL changesets known by the hg root, or empty set, never null */ public SortedSet getChangeSets(){ if(changesets.isEmpty()){ return EMPTY_SETS; } Set set = changesets.get(new Path(getRoot().getAbsolutePath())); if(set == null || set.isEmpty()) { return EMPTY_SETS; } if(set instanceof SortedSet) { return Collections.unmodifiableSortedSet((SortedSet) set); } TreeSet sorted = new TreeSet(set); return Collections.unmodifiableSortedSet(sorted); } private void populateCache(IProject project) { if(projectMap.containsKey(project)){ return; } TreeSet psets = new TreeSet(); ProjectCache cache = new ProjectCache(project, getBranch(), psets); projectMap.put(project, cache); IPath projectPath = ResourceUtils.getPath(project); Set set = changesets.get(projectPath); if(set != null){ psets.addAll(set); return; } Path rootPath = new Path(getRoot().getAbsolutePath()); set = changesets.get(rootPath); for (ChangeSet changeSet : set) { Set files = changeSet.getFiles(); for (IFile file : files) { IPath path = ResourceUtils.getPath(file); if(!path.isEmpty() && projectPath.isPrefixOf(path)){ // TODO filter by branch, or it is already filtered? // if(Branch.same(branch, changeSet.getBranch())) psets.add(changeSet); break; } } } } public boolean isValid(IProject project){ synchronized (projectMap) { return projectMap.containsKey(project); } } public boolean clear(IProject project){ ProjectCache removed; synchronized (projectMap) { removed = projectMap.remove(project); } return removed != null && !removed.isEmpty(); } public boolean clear(){ boolean changed; synchronized (projectMap) { changed = !projectMap.isEmpty(); projectMap.clear(); } return changed; } /** * @return never null, a list with all projects contained by related hg root directory */ public Set getRelatedProjects(){ return ResourceUtils.getProjects(getRoot()); } public IHgRepositoryLocation getRepo() { return key.getRepo(); } public HgRoot getRoot() { return key.getRoot(); } /** * @return specific branch or null if the changesets are not limited by the branch */ public String getBranch() { return key.getBranch(); } public Direction getDirection(){ return direction; } public boolean matches(RemoteKey otherKey){ return key.equals(otherKey); } public RemoteKey getKey(){ return key; } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("RemoteData ["); if (direction != null) { builder.append("direction="); builder.append(direction); builder.append(", "); } if (key != null) { builder.append("key="); builder.append(key); } builder.append("]"); return builder.toString(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/RemoteKey.java000066400000000000000000000072511173713500500331350ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * A key to identify remote cache. The key is direction-insensitive, e.g. it can be * used in both outgoing/incoming cache * @author Andrei */ public class RemoteKey { private final HgRoot root; private final IHgRepositoryLocation repo; /** * The branch name, or null to indicate all branches. */ private final String branch; /** * True if unrelated compare is not an error */ private final boolean allowUnrelated; /** * @param branch can be null (means all branches) */ public RemoteKey(HgRoot root, IHgRepositoryLocation repo, String branch) { this(root, repo, branch, false); } public RemoteKey(HgRoot root, IHgRepositoryLocation repo, String branch, boolean force) { this.root = root; this.repo = repo; this.branch = branch != null && Branch.isDefault(branch)? Branch.DEFAULT : branch; this.allowUnrelated = force; } public static RemoteKey create(IResource res, IHgRepositoryLocation repo, String branch){ HgRoot hgRoot = MercurialTeamProvider.getHgRoot(res); if(hgRoot != null) { return new RemoteKey(hgRoot, repo, branch); } return new RemoteKey(null, repo, Branch.DEFAULT); } public IHgRepositoryLocation getRepo() { return repo; } public HgRoot getRoot() { return root; } public boolean isAllowUnrelated() { return allowUnrelated; } /** * Can be null (means all branches) */ public String getBranch() { return branch; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((repo == null) ? 0 : repo.hashCode()); result = prime * result + ((root == null) ? 0 : root.hashCode()); result = prime * result + ((branch == null) ? 0 : branch.hashCode()); result = prime * result + (allowUnrelated ? 0 : 73); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof RemoteKey)) { return false; } RemoteKey other = (RemoteKey) obj; if (repo == null) { if (other.repo != null) { return false; } } else if (!repo.equals(other.repo) || allowUnrelated != other.allowUnrelated) { return false; } if (root == null) { if (other.root != null) { return false; } } else if (!root.equals(other.root)) { return false; } return Branch.same(branch, other.branch); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("RemoteKey ["); if (branch != null) { builder.append("branch="); builder.append(branch); builder.append(", "); } if (repo != null) { builder.append("repo="); builder.append(repo); builder.append(", "); } if (root != null) { builder.append("root="); builder.append(root); builder.append(", "); } builder.append("force="); builder.append(allowUnrelated); builder.append("]"); return builder.toString(); } } ResourceDeltaVisitor.java000066400000000000000000000153521173713500500352740ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.osgi.util.NLS; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.ui.IWorkbenchWindow; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeWorkspaceJob; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.InitOperation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; final class ResourceDeltaVisitor implements IResourceDeltaVisitor { private final Map> removed; private final Map> changed; private final Map> added; private final boolean autoShare; private final MercurialStatusCache cache; private int resourcesCount; private HgRoot currentRoot; ResourceDeltaVisitor(Map> removed, Map> changed, Map> added) { this.removed = removed; this.changed = changed; this.added = added; cache = MercurialStatusCache.getInstance(); autoShare = Boolean.valueOf( HgClients.getPreference(MercurialPreferenceConstants.PREF_AUTO_SHARE_PROJECTS, "false")) .booleanValue(); } public boolean visit(IResourceDelta delta) throws CoreException { IResource res = delta.getResource(); if (res.getType() == IResource.ROOT) { return true; } final IProject project = res.getProject(); // handle projects that contain a mercurial repository boolean openOrClosedOrDeleted = delta.getFlags() == IResourceDelta.OPEN || delta.getKind() == IResourceDelta.REMOVED; if (autoShare && openOrClosedOrDeleted && project.isAccessible() && RepositoryProvider.getProvider(project) == null) { autoshareProject(project); // stop tracking changes: after auto-share is completed, we will do a full refresh anyway return false; } if (!MercurialTeamProvider.isHgTeamProviderFor(res)) { return false; } // We should re-set currentRoot each time because the delta resources may be // from different projects AND from different UNRELATED roots too. currentRoot = MercurialTeamProvider.getHgRoot(res); if(currentRoot == null) { return true; } if((res == project && openOrClosedOrDeleted) || isCompleteStatusRequested()){ addResource(changed, project, currentRoot, project); return false; } // NB: the resource may not exist at this point (deleted/moved) // so any access to the IResource's API should be checked against null if (res.getType() == IResource.FILE) { IResource resource = isCompleteStatusRequested()? project : res; switch (delta.getKind()) { case IResourceDelta.ADDED: addResource(added, project, currentRoot, resource); // System.out.println("\t ADDED: " + resource); if(isCompleteStatusRequested()){ return false; } break; case IResourceDelta.CHANGED: if (hasChangedBits(delta) && cache.isSupervised(project, ResourceUtils.getPath(res))) { // fix for issue 10155: No status update after reverting changes on .hgignore if(MercurialStatusCache.canTriggerFullCacheUpdate(resource)){ addResource(changed, project, currentRoot, project); return false; } addResource(changed, project, currentRoot, resource); // System.out.println("\t CHANGED: " + resource); if(isCompleteStatusRequested()){ return false; } } break; case IResourceDelta.REMOVED: if (cache.isSupervised(project, ResourceUtils.getPath(res))) { addResource(removed, project, currentRoot, resource); // System.out.println("\t REMOVED: " + resource); if(isCompleteStatusRequested()){ return false; } } else { // check the parent folder: if the file had "unknown" state, folder was // marked as "modified". Now the file is deleted, so we should try // to refresh the folder state res = res.getParent(); if (res != null && cache.isSupervised(project, ResourceUtils.getPath(res))){ resource = isCompleteStatusRequested()? project : res; addResource(changed, project, currentRoot, resource); // System.out.println("\t CHANGED: " + resource); if(isCompleteStatusRequested()){ return false; } } } break; } } return true; } private boolean isCompleteStatusRequested() { return resourcesCount > MercurialStatusCache.NUM_CHANGED_FOR_COMPLETE_STATUS; } private void addResource(Map> map, IProject project, HgRoot root, IResource res){ if(root == null) { return; } RootResourceSet set = map.get(project); if(set == null){ set = new RootResourceSet(); map.put(project, set); } set.add(root, res); resourcesCount++; } private boolean hasChangedBits(IResourceDelta delta){ return (delta.getFlags() & MercurialStatusCache.MASK_CHANGED) != 0; } private void autoshareProject(final IProject project) { final HgRoot hgRoot = MercurialRootCache.getInstance().calculateHgRoot(project); if(hgRoot == null){ return; } MercurialEclipsePlugin.logInfo("Autosharing " + project.getName() + ". Detected repository location: " + hgRoot, null); final IWorkbenchWindow activeWorkbenchWindow = MercurialEclipsePlugin.getActiveWindow(); new SafeWorkspaceJob(NLS.bind(Messages.mercurialStatusCache_autoshare, project.getName())) { @Override protected IStatus runSafe(IProgressMonitor monitor) { try { new InitOperation(activeWorkbenchWindow, project, hgRoot).run(monitor); } catch (Exception e) { throw new RuntimeException(e); } return super.runSafe(monitor); } }.schedule(); } }RootResourceSet.java000066400000000000000000000074151173713500500342630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cache/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * lordofthepigs implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.team.cache; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IResource; import com.vectrace.MercurialEclipse.model.HgRoot; final class RootResourceSet { private final Map> resources = new HashMap>(); RootResourceSet(){ super(); } public void add(HgRoot root, T resource){ if(root == null){ throw new IllegalArgumentException("HgRoot is null"); } Set set = resources.get(root); if(set == null){ set = new HashSet(); resources.put(root, set); } set.add(resource); } public void addAll(RootResourceSet that){ for(Map.Entry> entry : that.resources.entrySet()){ if(resources.containsKey(entry.getKey())){ resources.get(entry.getKey()).addAll(entry.getValue()); }else{ resources.put(entry.getKey(), entry.getValue()); } } } public boolean contains(Object resource){ for(Set set : this.resources.values()){ if(set.contains(resource)){ return true; } } return false; } public int size(){ int size = 0; for(Set set :resources.values()){ size += set.size(); } return size; } public boolean isEmpty(){ return this.size() == 0; } public void clear(){ this.resources.clear(); } public HgRoot rootOf(T res){ for(Map.Entry> entry : this.resources.entrySet()){ if(entry.getValue().contains(res)){ return entry.getKey(); } } return null; } public Set>> entrySet(){ return this.resources.entrySet(); } public Set roots(){ return this.resources.keySet(); } public Set getResources(HgRoot root){ return this.resources.get(root); } public boolean remove(Object res){ Iterator> iter = this.resources.values().iterator(); while(iter.hasNext()){ Set set = iter.next(); if(set.remove(res)){ if(set.size() == 0){ // no more resources under this root, remove the root itself iter.remove(); } return true; } } return false; } public Iterator resourceIterator(){ return new ResourceIterator(); } @Override public int hashCode(){ return 23 * this.resources.hashCode(); } @Override public boolean equals(Object o){ if(o == null || !o.getClass().equals(this.getClass())){ return false; } RootResourceSet that = (RootResourceSet)o; return this.resources.equals(that.resources); } private class ResourceIterator implements Iterator { private final Iterator> rootIterator; private Set currentSet; private Iterator setIterator; public ResourceIterator(){ rootIterator = resources.values().iterator(); } public boolean hasNext() { if(setIterator != null && setIterator.hasNext()){ return true; } return rootIterator.hasNext(); } public T next() { if(setIterator != null && setIterator.hasNext()){ return setIterator.next(); } currentSet = rootIterator.next(); setIterator = currentSet.iterator(); return setIterator.next(); } public void remove() { if(setIterator != null){ setIterator.remove(); if(currentSet.size() == 0){ rootIterator.remove(); } } } } }messages.properties000066400000000000000000000020641173713500500342310ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/cachelocalChangesetCache_LogLimitLessThanZero=Limit < 0 localChangesetCache_LogLimitNotCorrectlyConfigured=Log limit not correctly configured in preferences. mercurialStatusCache_autoshare=Associating {0} with MercurialEclipse team provider. mercurialStatusCache_BatchSizeForStatusCommandNotCorrect=Batch size for status command not correct. mercurialStatusCache_FailedToRefreshMergeStatus=Failed to refresh merge status mercurialStatusCache_Refreshing=Refreshing {0} mercurialStatusCache_RefreshingProject=Refreshing project {0} ... mercurialStatusCache_RefreshingResources=Refreshing resources... mercurialStatusCache_RefreshStatus=Refresh status... mercurialStatusCache_UnknownStatus=Unknown status: ' refreshJob_LoadingIncomingRevisions=Loading incoming revisions for {0} refreshJob_LoadingLocalRevisions=Loading local revisions... refreshJob_LoadingOutgoingRevisionsFor=Loading outgoing revisions for {0} refreshJob_UpdatingStatusAndVersionCache=Updating status and version cache... refreshStatusJob_OptainingMercurialStatusInformation=Obtaining Mercurial Status information. eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/000077500000000000000000000000001173713500500305635ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/added.png000066400000000000000000000004221173713500500323300ustar00rootroot00000000000000PNG  IHDRRWbKGD pHYsHHFk>IDATeým@wO$ "^%FB 6A RB Sdwe~W^(˒@ Z }?0}F$`v-J[4K6-Uwo~e)y&/K99Ģb1ƒIbz!"1=B:EY<IENDB`eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/added_ov.gif000066400000000000000000000002061173713500500330150ustar00rootroot00000000000000GIF89aV|$~LjL! ,3$(@ @ (0@"&4 !A>@0A$L;eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/confchg_ov.gif000066400000000000000000000003021173713500500333600ustar00rootroot00000000000000GIF89a 26<=HJ    '-+1,3#$ +(43(-&.&&""" \[!, ?&fh&a{02uf̕Uh@J`Y,N K1X vDȔQ:;eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/copied_ov.gif000066400000000000000000000002601173713500500332170ustar00rootroot00000000000000GIF89aƧϻԲhԲiղiڽ|ȏ!,-$_)y($uT2ڱUԳ(Y+̤8`岴 *;deleted_still_tracked.png000066400000000000000000000003541173713500500355260ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/imagesPNG  IHDRK0 pHYsHHFk>IDAT @ٝYDD {{babl{DpBee?'-J.MS.23)2f\!xN&DdwmE+Ā!eǑ_M՚QIItmLkZ<0;`G;H>/wIENDB`deleted_still_tracked_ov.gif000066400000000000000000000001531173713500500362100ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/imagesGIF89akY@_+A`,Mm6zxxzx! ,PɩxT [B|!B&qryeJ;eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/ignored.png000066400000000000000000000003601173713500500327170ustar00rootroot00000000000000PNG  IHDRK0 pHYsHHFk>IDAT10Я&A^8xWO*pqvr58z`Biq:LO"RJ13\(ip/ܲ*8I|i R;G0} @kiў$*Z֪҃(Jlm4oMu$6=1IENDB`eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/ignored_ov.gif000066400000000000000000000001341173713500500334030ustar00rootroot00000000000000GIF89a kY@_+A`,Mm6zxxzx!, I8;eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/managed.png000066400000000000000000000005111173713500500326620ustar00rootroot00000000000000PNG  IHDRRWbKGD pHYs  tIME 95IDAT4Ѡ^       >S IENDB`eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/managed_ov.gif000066400000000000000000000001521173713500500333500ustar00rootroot00000000000000GIF89ad$?ԋչm!,ɉ@(xb9[p%9j;mercurialeclipse_small.png000066400000000000000000000004011173713500500357250ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/imagesPNG  IHDRRWbKGD pHYsHHFk>IDAT[@ѯ\ۆ {6 6d:.BUU d-L ZцHi%sOY CO8VM7͊{N瀱 )ٌ<]"8gK1l[&,n+Ǔ{/Fz>|)IENDB`eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/modified.png000066400000000000000000000004061173713500500330510ustar00rootroot00000000000000PNG  IHDRK0 pHYs  tIME ; IDATeѠ^-]-]Fw3bۭk3cϠ`{  y,83(XIENDB`eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/modified_ov.gif000066400000000000000000000001621173713500500335350ustar00rootroot00000000000000GIF89a! ) " * 4$>,3$I4?,Q9I3T80!,9˱O⍇tg8y xD;eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/moved_ov.gif000066400000000000000000000001231173713500500330640ustar00rootroot00000000000000GIF89a/`6rI]n 5!,(*-J4\@ dI ;eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/not_tracked.png000066400000000000000000000003631173713500500335700ustar00rootroot00000000000000PNG  IHDRK0 pHYsHHFk>IDATeѠ^?p٭k’Q͝[%S  ֧e ߰n!P 8"zIENDB`not_tracked_ov.gif000066400000000000000000000001171173713500500341730ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/imagesGIF89a o!,XV + l%_ ( 8%;eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/removed.png000066400000000000000000000004021173713500500327260ustar00rootroot00000000000000PNG  IHDRRWbKGD pHYsHHFk>IDATe Pѧ_! !l!A\DIXV\,h FP9T="-.I٬,(Hӄm'p4r*b"a58hr>5aPFku$.$/rq<0h~|!"<%ߪ(:oF·hIENDB`eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/images/removed_ov.gif000066400000000000000000000001101173713500500334070ustar00rootroot00000000000000GIF89a!,@P@D0B 6D C;eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/team/messages.properties000066400000000000000000000065141173713500500332510ustar00rootroot00000000000000ActionRemove.removeFileConfirmation=Mark the selected file(s) to be removed on next commit? ActionRemove.removeFileTitle=Remove file(s) on next commit? ActionRemove.removeOutput=Mercurial hg remove ActionRemove.unableToRefresh=Unable to refresh project: ActionRevert.HgRevert=Mercurial hg revert ActionRevert.mergeIsRunning=Previous merge operation is not finished yet.\nRevert merge and discard all changes? ActionRevert.noFilesToRevert=No files to revert\! ActionRevert.refreshing=Refreshing ActionRevert.revertFiles=Revert files ActionRevert.reverting=Reverting ActionRevert.revertingResources=Reverting resources... CompareWithAction.compareWith=Compare With Revision... DecoratorStatus.couldntGetVersionOfResource=Couldn't get version of resource DecoratorStatus.updatingDecos=Updating Decorations HgMoveDeleteHook.moveFailed=Move failed: IStorageMercurialRevision.parentChangeset=\ [parent changeset] MercurialConfigurationWizard.descriptionExisting=Define the Mercurial repository location to connect the project with. MercurialConfigurationWizard.descriptionNew=Confirm the location for the new Mercurial repository. MercurialConfigurationWizard.selectDirectory=Selected repository MercurialConfigurationWizard.titleExisting=Connect to an existing Mercurial repository MercurialConfigurationWizard.titleNew=Mercurial Repository Location Setup MercurialConfigurationWizard.useExistingHgDir=Use existing repository in the parent directory MercurialConfigurationWizard.useProjectRoot=Create new repository in the project directory MercurialConfigurationWizard.wizardTitle=Share Project MercurialProjectSetCapability.cancelled=Project reference determination cancelled. MercurialProjectSetCapability.determiningProjectReferences=Determining project references... MercurialProjectSetCapability.errorWhileImporting=Error while importing project sets MercurialProjectSetCapability.notDeterminable=Project reference not determinable for MercurialTeamProvider.doesNotBelongToHgRepo=\ does not belong to a Hg repository. MercurialUtilities.errorNotConfiguredCorrectly=Mercurial is not configured correctly. MercurialUtilities.linkWarningLong=The Selected resource is in a link and can't be handled by this plugin sorry\! MercurialUtilities.linkWarningShort=Resource in link URI MercurialUtilities.openingPreferencesForConfiguringMercurialEclipse=Opening preferences for configuring Mercurial MercurialUtilities.runDebugInstall=Run 'hg debuginstall' to analyse. MultipleFilesAction.hgSays=Hg says... MultipleFilesAction.seeErrorLog=\nSee Error Log for more details. MultipleFilesAction.unexpectedResourceType=Unexpected resource type: MultipleResourcesAction.hgSays=Hg says... MultipleResourcesAction.seeErrorLog=\nSee Error Log for more details. ResourceDecorator.couldntGetVersionOfResource=Couldn't get version of resource ResourceDecorator.merging=\ MERGING! ResourceDecorator.rebasing=\ REBASING! ResourceDecorator.new=\ [ new ] ResourceDecorator.refreshingChangesetDeco=Refreshing changeset decoration ResourceDecorator.updatingStatusForProject.1=Updating status for project ResourceDecorator.updatingStatusForProject.2=\ on behalf of resource SingleFileAction.hgSays=Hg says... SingleFileAction.seeErrorLog=\nSee Error Log for more details. SingleResourceAction.hgSays=Hg says... SingleResourceAction.seeErrorLog=\nSee Error Log for more details. TagAction.unableToRefresh=Unable to refresh project: eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/000077500000000000000000000000001173713500500270055ustar00rootroot00000000000000AbstractHighlightableTable.java000066400000000000000000000077411173713500500347710ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; /** * */ public abstract class AbstractHighlightableTable extends Composite { private static final Font APPLIED_FONT = JFaceResources.getFontRegistry().getBold( JFaceResources.DIALOG_FONT); private final TableViewer viewer; public AbstractHighlightableTable(Composite parent, final HighlightingLabelProvider labelProvider) { super(parent, SWT.NONE); setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); TableColumnLayout tableColumnLayout = new TableColumnLayout(); setLayout(tableColumnLayout); viewer = new TableViewer(this, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL); viewer.setContentProvider(new ArrayContentProvider()); viewer.setLabelProvider(labelProvider); List cols = createColumns(viewer, tableColumnLayout); CellLabelProvider clp = new CellLabelProvider() { @SuppressWarnings("unchecked") @Override public void update(ViewerCell cell) { E patch = (E) cell.getElement(); HighlightingLabelProvider lp = (HighlightingLabelProvider) viewer .getLabelProvider(); cell.setText(labelProvider.getColumnText(patch, cell.getColumnIndex())); cell.setImage(labelProvider.getColumnImage(patch, cell.getColumnIndex())); if (lp.isHighlighted(patch)) { cell.setFont(APPLIED_FONT); } else { cell.setFont(null); } } }; for (Iterator it = cols.iterator(); it.hasNext();) { it.next().setLabelProvider(clp); } Table table = viewer.getTable(); table.setLinesVisible(true); table.setHeaderVisible(true); } protected abstract List createColumns(TableViewer tableViewer, TableColumnLayout tableColumnLayout); /** * @return The first selected patch, or {@code null} if the selection is empty. */ @SuppressWarnings("unchecked") public E getSelection() { return (E) ((IStructuredSelection) viewer.getSelection()).getFirstElement(); } /** * @return A list of the selected patches. If the selection is empty an empty list is returned, * never {@code null}. */ @SuppressWarnings("unchecked") public List getSelections() { return ((IStructuredSelection) viewer.getSelection()).toList(); } public void setItems(List patches) { viewer.setInput(patches); } @SuppressWarnings("unchecked") public List getItems() { Object inp = viewer.getInput(); if (inp instanceof List) { return (List) inp; } return Collections.emptyList(); } public TableViewer getTableViewer() { return viewer; } public abstract static class HighlightingLabelProvider extends LabelProvider implements ITableLabelProvider { public abstract boolean isHighlighted(F inst); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/BookmarkTable.java000066400000000000000000000072461173713500500323760ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Brian Wallis - adaptation to branches * Bastian Doetsch - adaptation to bookmarks * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.List; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.extensions.HgBookmarkClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Bookmark; import com.vectrace.MercurialEclipse.model.HgRoot; /** * * @author Jerome Negre */ public class BookmarkTable extends Composite { private static final Font PARENT_FONT = JFaceResources.getFontRegistry() .getBold(JFaceResources.DIALOG_FONT); private final Table table; public BookmarkTable(Composite parent) { super(parent, SWT.NONE); this.setLayout(new GridLayout()); this.setLayoutData(new GridData()); table = new Table(this, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL); table.setLinesVisible(true); table.setHeaderVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = 150; data.minimumHeight = 50; table.setLayoutData(data); String[] titles = { Messages.getString("BookmarkTable.column.rev"), Messages.getString("BookmarkTable.column.global"), Messages.getString("BookmarkTable.column.name"), Messages.getString("BookmarkTable.column.state") }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ int[] widths = { 60, 150, 300, 70 }; for (int i = 0; i < titles.length; i++) { TableColumn column = new TableColumn(table, SWT.NONE); column.setText(titles[i]); column.setWidth(widths[i]); } } public void updateTable(HgRoot hgRoot) { try { List bookmarks = HgBookmarkClient.getBookmarks(hgRoot); setBookmarks(bookmarks.toArray(new Bookmark[bookmarks.size()])); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } public void setBookmarks(Bookmark[] bookmarks) { table.removeAll(); for (Bookmark bm : bookmarks) { TableItem row = new TableItem(table, SWT.NONE); row.setText(0, Integer.toString(bm.getRevision())); row.setText(1, bm.getShortNodeId()); row.setText(2, bm.getName()); row.setText(3, bm.isActive() ? Messages.getString("BookmarkTable.stateActive") : Messages.getString("BookmarkTable.stateInactive")); //$NON-NLS-1$ //$NON-NLS-2$ row.setData(bm); if (bm.isActive()) { row.setFont(PARENT_FONT); } } } public Bookmark getSelection() { TableItem[] selection = table.getSelection(); if (selection.length == 0) { return null; } return (Bookmark) selection[0].getData(); } public void addSelectionListener(SelectionListener listener) { table.addSelectionListener(listener); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/BranchTable.java000066400000000000000000000124501173713500500320170ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Brian Wallis - adaptation to branches * Andrei Loskutov - bug fixes * Zsolt Kopany (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.Comparator; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.model.Branch; /** * @author Jerome Negre * @author Zsolt Koppany * @version $Id$ */ public class BranchTable extends Composite { private static final Font PARENT_FONT = JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT); private final Table table; private int[] parents; private boolean showTip = true; private String highlightBranch; private Branch[] branches; @SuppressWarnings("unchecked") public BranchTable(Composite parent) { super(parent, SWT.NONE); this.setLayout(new GridLayout()); this.setLayoutData(new GridData()); table = new Table(this, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL); table.setLinesVisible(true); table.setHeaderVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); table.setLayoutData(data); String[] titles = { Messages.getString("BranchTable.column.rev"), Messages.getString("BranchTable.column.global"), Messages.getString("BranchTable.column.branch"), Messages.getString("BranchTable.column.active") }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ Comparator[] comparators = { new Comparator() { public int compare(Branch o1, Branch o2) { return TableSortListener.sort(o1.getRevision(), o2.getRevision()); } }, new Comparator() { public int compare(Branch o1, Branch o2) { return o1.getGlobalId().compareTo(o2.getGlobalId()); } }, new Comparator() { public int compare(Branch o1, Branch o2) { return o1.getName().compareTo(o2.getName()); } }, new Comparator() { public int compare(Branch o1, Branch o2) { return TableSortListener.sort(o1.isActive() ? 1 : 0, o2.isActive() ? 1 : 0); } } }; int[] widths = { 60, 150, 300, 70 }; Listener sortListener = new TableSortListener(table, comparators) { @Override protected Object[] getData() { return branches; } }; for (int i = 0; i < titles.length; i++) { TableColumn column = new TableColumn(table, SWT.NONE); column.setText(titles[i]); column.setWidth(widths[i]); column.addListener(SWT.Selection, sortListener); } table.addListener(SWT.SetData, new Listener() { public void handleEvent(org.eclipse.swt.widgets.Event event) { TableItem row = (TableItem) event.item; int index = table.indexOf(row); if (branches != null && 0 <= index && index < branches.length) { Branch branch = branches[index]; if (showTip || !HgRevision.TIP.getChangeset().equals(branch.getName())) { if ((parents != null && isParent(branch.getRevision())) || Branch.same(highlightBranch, branch.getName())) { row.setFont(PARENT_FONT); } row.setText(0, Integer.toString(branch.getRevision())); row.setText(1, branch.getGlobalId()); row.setText(2, branch.getName()); row.setText(3, branch.isActive() ? Messages .getString("BranchTable.stateActive") //$NON-NLS-1$ : Messages.getString("BranchTable.stateInactive")); //$NON-NLS-1$ row.setData(branch); } } } }); } public void hideTip() { this.showTip = false; } public void highlightParents(int[] newParents) { this.parents = newParents; } public void setBranches(Branch[] branches) { table.clearAll(); table.setItemCount(branches.length); this.branches = branches; } public Branch getSelection() { TableItem[] selection = table.getSelection(); if (selection.length == 0) { return null; } return (Branch) selection[0].getData(); } public void addSelectionListener(SelectionListener listener) { table.addSelectionListener(listener); } private boolean isParent(int r) { switch (parents.length) { case 2: if (r == parents[1]) { return true; } //$FALL-THROUGH$ case 1: if (r == parents[0]) { return true; } //$FALL-THROUGH$ default: return false; } } /** * @param branch non null branch to highlight */ public void highlightBranch(String branch) { this.highlightBranch = branch; } } ChangeSetLabelProvider.java000066400000000000000000000027531173713500500341140ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Philip Graf bug fix *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.graphics.Image; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.utils.ChangeSetUtils; public class ChangeSetLabelProvider extends LabelProvider implements ITableLabelProvider { public Image getColumnImage(Object element, int columnIndex) { return null; } public String getColumnText(Object element, int columnIndex) { ChangeSet rev = (ChangeSet) element; switch(columnIndex) { case 0: return Integer.toString(rev.getChangesetIndex()); case 1: return rev.getChangeset(); case 2: return rev.getDateString(); case 3: return rev.getAuthor(); case 4: return rev.getBranch(); case 5: return ChangeSetUtils.getPrintableTagsString(rev); case 6: return rev.getSummary(); } return null; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/ChangesetInfoTray.java000066400000000000000000000162121173713500500332270ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Philip Graf bug fix *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.SimpleLabelImageProvider; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.utils.ChangeSetUtils; import com.vectrace.MercurialEclipse.utils.CompareUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author bastian * */ public class ChangesetInfoTray extends org.eclipse.jface.dialogs.DialogTray { private Composite comp; private final ChangeSet changeset; private ChangedFilesTable changedFileTable; private static class ChangesetInfoPathLabelProvider extends DecoratingLabelProvider implements ITableLabelProvider { public ChangesetInfoPathLabelProvider() { super(new SimpleLabelImageProvider(), PlatformUI.getWorkbench().getDecoratorManager() .getLabelDecorator()); } public Image getColumnImage(Object element, int columnIndex) { if (!(element instanceof FileStatus)) { return null; } return getImage(element); } public String getColumnText(Object element, int columnIndex) { if (!(element instanceof FileStatus)) { return null; } return getText(element); } } public ChangesetInfoTray(ChangeSet cs) { this.changeset = cs; } /** * @see org.eclipse.jface.dialogs.DialogTray#createContents(org.eclipse.swt.widgets .Composite) */ @Override public Control createContents(Composite parent) { comp = SWTWidgetHelper.createComposite(parent, 1); GridData layoutData = new GridData(GridData.FILL_BOTH); layoutData.minimumWidth = 100; comp.setLayoutData(layoutData); createChangesetInfoGroup(); createChangedFilesTable(); // populate viewer changedFileTable.getViewer().setInput(changeset); return comp; } /** * */ private void createChangedFilesTable() { Group g = SWTWidgetHelper.createGroup(comp, Messages.getString("ChangesetInfoTray.changedFiles"), 1, GridData.FILL_BOTH); //$NON-NLS-1$ changedFileTable = new ChangedFilesTable(g, changeset); } private void createChangesetInfoGroup() { Group g = SWTWidgetHelper.createGroup(comp, Messages .getString("ChangesetInfoTray.changesetToBeAmended"), 2, GridData.FILL_BOTH); //$NON-NLS-1$ SWTWidgetHelper.createLabel(g, Messages.getString("ChangesetInfoTray.changeset")); //$NON-NLS-1$ SWTWidgetHelper.createLabel(g, ChangeSetUtils.getPrintableRevisionShort(changeset)); SWTWidgetHelper.createLabel(g, Messages.getString("ChangesetInfoTray.tags")); //$NON-NLS-1$ SWTWidgetHelper.createLabel(g, ChangeSetUtils.getPrintableTagsString(changeset)); SWTWidgetHelper.createLabel(g, Messages.getString("ChangesetInfoTray.user")); //$NON-NLS-1$ SWTWidgetHelper.createLabel(g, changeset.getAuthor()); SWTWidgetHelper.createLabel(g, Messages.getString("ChangesetInfoTray.date")); //$NON-NLS-1$ SWTWidgetHelper.createLabel(g, String.valueOf(changeset.getDate())); SWTWidgetHelper.createLabel(g, Messages.getString("ChangesetInfoTray.comment")); //$NON-NLS-1$ SWTWidgetHelper.createWrappingLabel(g, changeset.getComment(), 0); } // inner types public static class ChangedFilesTable extends Composite { private TableViewer viewer; public ChangedFilesTable(Composite parent, final ChangeSet changeset) { super(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.verticalSpacing = 3; layout.horizontalSpacing = 0; layout.marginWidth = 0; layout.marginHeight = 0; setLayout(layout); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = 150; data.minimumHeight = 50; setLayoutData(data); Table table = new Table(this, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); table.setLinesVisible(true); table.setHeaderVisible(false); data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = 150; data.minimumHeight = 50; table.setLayoutData(data); viewer = new TableViewer(table); viewer.setLabelProvider(new ChangesetInfoPathLabelProvider()); IStructuredContentProvider contentProvider = new IStructuredContentProvider() { public void inputChanged(Viewer viewer1, Object oldInput, Object newInput) { viewer = (TableViewer) viewer1; } public void dispose() { } public Object[] getElements(Object inputElement) { return changeset.getChangedFiles().toArray(); } }; viewer.setContentProvider(contentProvider); IDoubleClickListener listener = new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { FileStatus clickedFileStatus = (FileStatus) ((IStructuredSelection) event .getSelection()).getFirstElement(); ChangeSet cs = changeset; IPath fileAbsPath = cs.getHgRoot().toAbsolute( clickedFileStatus.getRootRelativePath()); IFile file = ResourceUtils.getFileHandle(fileAbsPath); if (file != null) { try { String[] parents = HgParentClient.getParentNodeIds(file, cs); // our amend changeset was a merge changeset. diff is difficult... if (parents == null || parents.length == 2) { return; } MercurialRevisionStorage left = new MercurialRevisionStorage(file, cs .getChangesetIndex()); MercurialRevisionStorage right = new MercurialRevisionStorage(file, parents[0]); CompareUtils.openEditor(left, right, true); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } } }; viewer.addDoubleClickListener(listener); } public StructuredViewer getViewer() { return viewer; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/ChangesetTable.java000066400000000000000000000324541173713500500325310ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch - support for multi-select tables * Andrei Loskutov - bug fixes * Philip Graf - bug fix * Ilya Ivanov (Intland) - modifications * John Peberdy - use virtual table *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.Collections; import java.util.Comparator; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.utils.ChangeSetUtils; /** * @author Jerome Negre */ public class ChangesetTable extends Composite { /** single selection, border, scroll */ private static final int DEFAULT_STYLE = SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL; private static final Font PARENT_FONT = JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT); private final Table table; protected Strategy strategy; private int[] parents; private int logBatchSize; // constructors public ChangesetTable(Composite parent, boolean multiSelect) { this(parent, (Strategy)null, multiSelect); } public ChangesetTable(Composite parent, IResource resource) { this(parent, new ResourceStrategy(resource), false); } public ChangesetTable(Composite parent, HgRoot hgRoot) { this(parent, new RootStrategy(hgRoot), false); } public ChangesetTable(Group parent, HgRoot root, boolean multiSelect) { this(parent, new RootStrategy(root), multiSelect); } /** * @param parent non null swt parent widget * @param workspaceResource a resource to show changesets for, mutually exclusive with the hgRoot argument * @param hgRoot a hg root to show changesets for, , mutually exclusive with the resource argument * @param autoFetch true to fetch extra changesets info on scroll as needed */ private ChangesetTable(Composite parent, Strategy strategy, boolean multiSelect) { super(parent, SWT.NONE); this.logBatchSize = LocalChangesetCache.getInstance().getLogBatchSize(); // limit log to allow "smooth" scrolling (not too small and not too big) // - but only if not set in preferences if (logBatchSize <= 0) { logBatchSize = 200; } this.setLayout(new GridLayout()); this.setLayoutData(new GridData()); int tableStyle = DEFAULT_STYLE; if (multiSelect) { tableStyle |= SWT.MULTI; } else { tableStyle |= SWT.SINGLE; } table = new Table(this, tableStyle); table.setLinesVisible(true); table.setHeaderVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.heightHint = 150; data.minimumHeight = 50; table.setLayoutData(data); String[] titles = { Messages.getString("ChangesetTable.column.rev"), Messages.getString("ChangesetTable.column.global"), Messages.getString("ChangesetTable.column.date"), Messages.getString("ChangesetTable.column.author"), Messages.getString("ChangesetTable.column.branch"), "Tags", Messages.getString("ChangesetTable.column.summary") }; //$NON-NLS-1$ int[] widths = { 60, 80, 100, 80, 70, 70, 300 }; @SuppressWarnings("unchecked") Comparator[] comparators = { new Comparator() { public int compare(ChangeSet a, ChangeSet b) { return TableSortListener.sort(a.getChangesetIndex(), b.getChangesetIndex()); } }, new Comparator() { public int compare(ChangeSet a, ChangeSet b) { return a.getChangeset().compareTo(b.getChangeset()); } }, new Comparator() { public int compare(ChangeSet a, ChangeSet b) { return a.getRealDate().compareTo(b.getRealDate()); } }, new Comparator() { public int compare(ChangeSet a, ChangeSet b) { return a.getAuthor().compareTo(b.getAuthor()); } }, new Comparator() { public int compare(ChangeSet a, ChangeSet b) { return a.getBranch().compareTo(b.getBranch()); } }, new Comparator() { public int compare(ChangeSet a, ChangeSet b) { return a.getTagsStr().compareTo(b.getTagsStr()); } }, new Comparator() { public int compare(ChangeSet a, ChangeSet b) { return a.getSummary().compareTo(b.getSummary()); } } }; Listener sortListener = new TableSortListener(table, comparators) { @Override protected Object[] getData() { return ChangesetTable.this.strategy.getFetched(); } @Override protected boolean canSort() { return ChangesetTable.this.strategy != null && ChangesetTable.this.strategy.isFullyLoaded(); } }; for (int i = 0; i < titles.length; i++) { TableColumn column = new TableColumn(table, SWT.NONE); column.setText(titles[i]); column.setWidth(widths[i]); column.addListener(SWT.Selection, sortListener); } table.addListener(SWT.PaintItem, new Listener() { public void paintControl(Event e) { // When painting the last item, attempt to load more data TableItem tableItem = (TableItem) e.item; if (table.isEnabled() && tableItem.equals(table.getItems()[table.getItemCount() - 1])) { loadMore(); } } public void handleEvent(Event event) { paintControl(event); } }); table.addListener(SWT.SetData, new Listener() { public void handleEvent(org.eclipse.swt.widgets.Event event) { TableItem row = (TableItem) event.item; if (ChangesetTable.this.strategy != null) { ChangeSet rev = ChangesetTable.this.strategy.getChangeSet(table.indexOf(row)); if (parents != null && isParent(rev.getChangesetIndex())) { row.setFont(PARENT_FONT); } row.setText(0, Integer.toString(rev.getChangesetIndex())); row.setText(1, rev.getChangeset()); row.setText(2, rev.getDateString()); row.setText(3, rev.getAuthor()); row.setText(4, rev.getBranch()); row.setText(5, ChangeSetUtils.getPrintableTagsString(rev)); row.setText(6, rev.getSummary()); row.setData(rev); } } }); setStrategy(strategy); } // operations public void highlightParents(int[] newParents) { this.parents = newParents; } public void setStrategy(Strategy strategy) { this.strategy = strategy; table.removeAll(); loadMore(); } public Strategy getStrategy() { return strategy; } protected void loadMore() { try { if (ChangesetTable.this.strategy != null) { int nLength = ChangesetTable.this.strategy.load(null, logBatchSize); if (nLength >= 0) { table.setItemCount(nLength); } } } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); } } public void setSelection(ChangeSet selection) { try { if (ChangesetTable.this.strategy != null) { int n = ChangesetTable.this.strategy.load(selection, logBatchSize); if (n >= 0) { table.setItemCount(n); } n = ChangesetTable.this.strategy.indexOf(selection); if (n >= 0) { table.setSelection(n); } } } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); } } public void clearSelection(){ table.deselectAll(); } public ChangeSet[] getSelections() { TableItem[] selection = table.getSelection(); if (selection.length == 0) { return null; } ChangeSet[] csArray = new ChangeSet[selection.length]; for (int i = 0; i < selection.length; i++) { csArray[i] = (ChangeSet) selection[i].getData(); } return csArray; } public ChangeSet getSelection() { if (getSelections() != null) { return getSelections()[0]; } return null; } public void addSelectionListener(SelectionListener listener) { table.addSelectionListener(listener); } @Override public void setEnabled(boolean enabled) { table.setEnabled(enabled); } protected boolean isParent(int r) { switch (parents.length) { case 2: if (r == parents[1]) { return true; } //$FALL-THROUGH$ case 1: if (r == parents[0]) { return true; } //$FALL-THROUGH$ default: return false; } } // inner types public abstract static class Strategy { private static final ChangeSet[] NO_CHANGESETS = new ChangeSet[0]; protected ChangeSet[] fetched = NO_CHANGESETS; public final ChangeSet getChangeSet(int i) { if (0 <= i && i < fetched.length) { return fetched[i]; } return null; } /** * Load up to a changeset. If null then load some more. */ public abstract int load(ChangeSet cs, int batchSize) throws HgException; public int indexOf(ChangeSet cs) { if (cs != null) { for (int i = 0; i < fetched.length; i++) { if (cs.compareTo(fetched[i]) == 0) { // Why not use equals? return i; } } } return -1; } public ChangeSet[] getFetched() { return fetched; } public boolean isFullyLoaded() { return true; } } public static class PrefetchedStrategy extends Strategy { public PrefetchedStrategy(ChangeSet[] changeSets) { Assert.isNotNull(changeSets); this.fetched = changeSets; } @Override public int load(ChangeSet cs, int batchSize) { return fetched.length; } } private abstract static class AutofetchStrategy extends Strategy { private boolean canLoad = true; @Override public boolean isFullyLoaded() { return !canLoad; } @Override public int load(ChangeSet cs, int batchSize) throws HgException { if (cs != null) { while (indexOf(cs) < 0 && loadMore(batchSize)) { } } else { loadMore(batchSize); } return fetched.length; } private boolean loadMore(int batchSize) throws HgException { if (!canLoad) { return false; } // Get stuff from cache and added it to fetched LocalChangesetCache cache = LocalChangesetCache.getInstance(); SortedSet set = get(cache); int prevLen = fetched.length; if (!set.isEmpty()) { int smallestInCache = set.first().getChangesetIndex(); // TODO: what if the cache is flushed requested from elsewhere meaning we'd have a // gap in revs. Should not happen. if (fetched.length != 0 && smallestInCache >= fetched[fetched.length - 1].getChangesetIndex()) { set = getMore(cache, batchSize, smallestInCache); } SortedSet reverseOrderSet = new TreeSet(Collections.reverseOrder()); reverseOrderSet.addAll(set); for (ChangeSet changeSet : fetched) { reverseOrderSet.add(changeSet); } fetched = reverseOrderSet.toArray(new ChangeSet[reverseOrderSet.size()]); } return canLoad = prevLen < fetched.length; } protected abstract SortedSet get(LocalChangesetCache cache) throws HgException; protected abstract SortedSet getMore(LocalChangesetCache cache, int batchSize, int startRev) throws HgException; } public static class ResourceStrategy extends AutofetchStrategy { private final IResource resource; public ResourceStrategy(IResource resource) { this.resource = resource; } @Override protected SortedSet get(LocalChangesetCache cache) throws HgException { return cache.getOrFetchChangeSets(resource); } @Override protected SortedSet getMore(LocalChangesetCache cache, int batchSize, int startRev) throws HgException { cache.fetchRevisions(resource, true, batchSize, startRev, false); return get(cache); } } public static class RootStrategy extends AutofetchStrategy { protected final HgRoot root; public RootStrategy(HgRoot root) { this.root = root; } @Override protected SortedSet get(LocalChangesetCache cache) throws HgException { return cache.getOrFetchChangeSets(root); } @Override protected SortedSet getMore(LocalChangesetCache cache, int batchSize, int startRev) throws HgException { cache.fetchRevisions(root, true, batchSize, startRev, false); return get(cache); } } public static class BranchStrategy extends RootStrategy { private final String branch; public BranchStrategy(HgRoot root, String branch) { super(root); this.branch = branch; // TODO: If there are no changesets for a given branch within a batch size then it will // incorrectly detect it as being fully loaded } @Override protected SortedSet get(LocalChangesetCache cache) throws HgException { return cache.getOrFetchChangeSetsByBranch(root, branch); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/CommitFilesChooser.java000066400000000000000000000345651173713500500334230ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Administrator implementation * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.TableColumnSorter; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.dialogs.CommitResource; import com.vectrace.MercurialEclipse.dialogs.CommitResourceLabelProvider; import com.vectrace.MercurialEclipse.dialogs.CommitResourceUtil; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.utils.CompareUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * TODO enable tree/flat view switch * * @author steeven */ public class CommitFilesChooser extends Composite { private final UntrackedFilesFilter untrackedFilesFilter; private final CommittableFilesFilter committableFilesFilter; private final boolean selectable; private Button showUntrackedFilesButton; private Button selectAllButton; private final CheckboxTableViewer viewer; private final boolean showUntracked; private final boolean missing; private final ListenerList stateListeners = new ListenerList(); protected Control trayButton; protected boolean trayClosed = true; protected IFile selectedFile; private final boolean showClean; public CheckboxTableViewer getViewer() { return viewer; } public CommitFilesChooser(HgRoot hgRoot, Composite container, boolean selectable, boolean showUntracked, boolean showMissing, boolean showClean) { this(container, selectable, null, showUntracked, showMissing, showClean); setResources(hgRoot); } public CommitFilesChooser(Composite container, boolean selectable, List resources, boolean showUntracked, boolean showMissing, boolean showClean) { super(container, container.getStyle()); this.selectable = selectable; this.showUntracked = showUntracked; this.missing = showMissing; this.showClean = showClean; this.untrackedFilesFilter = new UntrackedFilesFilter(missing); this.committableFilesFilter = new CommittableFilesFilter(); GridLayout layout = new GridLayout(); layout.verticalSpacing = 3; layout.horizontalSpacing = 0; layout.marginWidth = 0; layout.marginHeight = 0; setLayout(layout); setLayoutData(SWTWidgetHelper.getFillGD(150)); Table table = createTable(); viewer = new CheckboxTableViewer(table); viewer.setContentProvider(new ArrayContentProvider()); CommitResourceLabelProvider labelProvider = new CommitResourceLabelProvider(); labelProvider.addListener(new ILabelProviderListener() { public void labelProviderChanged(LabelProviderChangedEvent event) { int count = viewer.getTable().getItemCount(); for (int i = 0; i < count; i++) { CommitResource commitResource = (CommitResource) viewer .getElementAt(i); viewer.update(commitResource, null); } } }); viewer.setLabelProvider(labelProvider); viewer.setComparator(new ViewerComparator()); viewer.addFilter(committableFilesFilter); if (!showUntracked) { viewer.addFilter(untrackedFilesFilter); } createOptionCheckbox(); createShowDiffButton(container); createFileSelectionListener(); makeActions(); if (resources != null) { setResources(resources); } } private void createFileSelectionListener() { getViewer().addSelectionChangedListener( new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) selection; CommitResource commitResource = (CommitResource) sel .getFirstElement(); if (commitResource != null) { IFile oldSelectedFile = selectedFile; selectedFile = (IFile) commitResource .getResource(); if (oldSelectedFile == null || !oldSelectedFile .equals(selectedFile)) { trayButton.setEnabled(true); } } } } }); } private void createShowDiffButton(Composite container) { trayButton = SWTWidgetHelper.createPushButton(container, Messages .getString("CommitFilesChooser.showDiffButton.text"), //$NON-NLS-1$ 1); trayButton.setEnabled(false); trayButton.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { showDiffForSelection(); } }); } private Table createTable() { int flags = SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER; if (selectable) { flags |= SWT.CHECK | SWT.FULL_SELECTION | SWT.MULTI; } else { flags |= SWT.READ_ONLY | SWT.HIDE_SELECTION; } Table table = new Table(this, flags); table.setHeaderVisible(false); table.setLinesVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); table.setLayoutData(data); return table; } private void createOptionCheckbox() { if (!selectable) { return; } selectAllButton = new Button(this, SWT.CHECK); selectAllButton.setText(Messages .getString("Common.SelectOrUnselectAll")); //$NON-NLS-1$ selectAllButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); if (!showUntracked) { return; } showUntrackedFilesButton = new Button(this, SWT.CHECK); showUntrackedFilesButton.setText(Messages .getString("Common.ShowUntrackedFiles")); //$NON-NLS-1$ showUntrackedFilesButton.setLayoutData(new GridData( GridData.FILL_HORIZONTAL)); } private void makeActions() { getViewer().addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { showDiffForSelection(); } }); getViewer().addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { fireStateChanged(); } }); if (selectable) { selectAllButton.setSelection(false); // Start not selected selectAllButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (selectAllButton.getSelection()) { getViewer().setAllChecked(true); } else { getViewer().setAllChecked(false); } fireStateChanged(); } }); } if (selectable && showUntracked) { showUntrackedFilesButton.setSelection(true); // Start selected. showUntrackedFilesButton .addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (showUntrackedFilesButton.getSelection()) { getViewer().removeFilter(untrackedFilesFilter); } else { getViewer().addFilter(untrackedFilesFilter); } getViewer().refresh(true); fireStateChanged(); } }); } final Table table = getViewer().getTable(); TableColumn[] columns = table.getColumns(); for (int ci = 0; ci < columns.length; ci++) { TableColumn column = columns[ci]; final int colIdx = ci; new TableColumnSorter(getViewer(), column) { @Override protected int doCompare(Viewer v, Object e1, Object e2) { StructuredViewer v1 = (StructuredViewer) v; ITableLabelProvider lp = (ITableLabelProvider) v1.getLabelProvider(); String t1 = lp.getColumnText(e1, colIdx); String t2 = lp.getColumnText(e2, colIdx); if (t1 != null) { return t1.compareTo(t2); } return 0; } }; } } /** * Set the resources, and from those select resources, which are tracked by * Mercurial * * @param resources * non null */ public void setResources(List resources) { CommitResource[] commitResources = createCommitResources(resources); getViewer().setInput(commitResources); IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); boolean preSelectAll = store.getBoolean(MercurialPreferenceConstants.PREF_PRESELECT_UNTRACKED_IN_COMMIT_DIALOG); if (preSelectAll) { getViewer().setCheckedElements(commitResources); } else { List tracked = CommitResourceUtil.filterForTracked(commitResources); getViewer().setCheckedElements(tracked.toArray()); } if (selectable && (!showUntracked || preSelectAll)) { selectAllButton.setSelection(true); } // show clean file, if we are called on a single, not modified file // (revert to any version in the past) if (showClean && resources.size() == 1 && commitResources.length == 0) { IResource resource = resources.get(0); if (resource.getType() == IResource.FILE) { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(resource); if(hgRoot == null) { return; } File path = new File(hgRoot.toRelative(ResourceUtils.getFileHandle(resource))); CommitResource cr = new CommitResource(MercurialStatusCache.BIT_CLEAN, resource, path); CommitResource[] input = new CommitResource[] { cr }; getViewer().setInput(input); getViewer().setCheckedElements(input); } } } /** * Set the all the modified resources from given hg root, and from those * select resources, which are tracked by Mercurial * * @param hgRoot * non null */ public void setResources(HgRoot hgRoot) { List resources = new ArrayList(); // Future: get this from the status cache // get the dirty files... try { Set dirtyFilePaths = HgStatusClient .getDirtyFilePaths(hgRoot); for (IPath path : dirtyFilePaths) { IFile fileHandle = ResourceUtils.getFileHandle(path); // XXX this would NOT add files which are not under Eclipse // control (outside of a project) if (fileHandle != null) { resources.add(fileHandle); } } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } setResources(resources); } /** * Create the Commit-resources' for a set of resources * * @param res */ private CommitResource[] createCommitResources(List res) { return CommitResourceUtil.getCommitResources(res); } /** * Set the selected resources. Obviously this will only select those * resources, which are displayed... * * @param resources */ public void setSelectedResources(List resources) { CommitResource[] allCommitResources = (CommitResource[]) getViewer() .getInput(); if (allCommitResources == null) { return; } List selected = CommitResourceUtil .filterForResources(Arrays.asList(allCommitResources), resources); getViewer().setCheckedElements(selected.toArray()); } public List getCheckedResources(String... status) { return getViewerResources(true, status); } public List getUncheckedResources(String... status) { return getViewerResources(false, status); } public List getViewerResources(boolean checked, String... status) { TableItem[] children = getViewer().getTable().getItems(); List list = new ArrayList(children.length); for (TableItem item : children) { if (item.getChecked() == checked && item.getData() instanceof CommitResource) { CommitResource resource = (CommitResource) item.getData(); if (status == null || status.length == 0) { list.add(resource.getResource()); } else { for (String stat : status) { if (resource.getStatusMessage().equals(stat)) { list.add(resource.getResource()); break; } } } } } return list; } public void addStateListener(Listener listener) { stateListeners.add(listener); } protected void fireStateChanged() { for (Object obj : stateListeners.getListeners()) { ((Listener) obj).handleEvent(null); } } private void showDiffForSelection() { if (selectedFile != null) { MercurialRevisionStorage iStorage = new MercurialRevisionStorage(selectedFile); try { CompareUtils.openEditor(selectedFile, iStorage, true, null); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } } public boolean isSelectable() { return selectable; } } CommittableFilesFilter.java000066400000000000000000000010571173713500500341650ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/uipackage com.vectrace.MercurialEclipse.ui; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import com.vectrace.MercurialEclipse.dialogs.CommitResource; public class CommittableFilesFilter extends ViewerFilter { public CommittableFilesFilter() { super(); } /** * Filter out un commitable files (i.e. ! -> deleted but still tracked) */ @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof CommitResource) { return true; } return true; } } HgProjectPropertyPage.java000066400000000000000000000220551173713500500340240ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/******************************************************************************* * Copyright (c) 2005-2009 Bastian Doetsch and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import static com.vectrace.MercurialEclipse.ui.SWTWidgetHelper.*; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.dialogs.PropertyPage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.wizards.NewLocationWizard; /** * @author bastian */ public class HgProjectPropertyPage extends PropertyPage { public static final String ID = "com.vectrace.MercurialEclipse.ui.HgProjectPropertyPage"; private IProject project; private Group reposGroup; private Text defTextField; private HgRoot hgRoot; private Combo allReposCombo; private Text commitText; public HgProjectPropertyPage() { super(); } @Override protected Control createContents(Composite parent) { this.project = (IProject) super.getElement(); Composite comp = createComposite(parent, 1); if (!MercurialTeamProvider.isHgTeamProviderFor(project)) { setMessage("This project doesn't use MercurialEclipse as Team provider."); return comp; } hgRoot = MercurialTeamProvider.getHgRoot(project); if(hgRoot == null) { setMessage("Failed to find hg root for project."); return comp; } final HgRepositoryLocationManager mgr = MercurialEclipsePlugin.getRepoManager(); Set allRepos = mgr.getAllRepoLocations(); IHgRepositoryLocation defLoc = mgr.getDefaultRepoLocation(hgRoot); createCommitGroup(comp); createRepoGroup(comp); createButtons(mgr); updateSelection(allRepos, defLoc); allReposCombo.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { updateDefaultRepo(); } }); updateApplyButton(); commitText.setFocus(); return comp; } private void createRepoGroup(Composite comp) { reposGroup = SWTWidgetHelper.createGroup(comp, "Default repository", 1, GridData.FILL_HORIZONTAL); defTextField = createTextField(reposGroup); defTextField.setEditable(false); createLabel(reposGroup, "Set as default:"); allReposCombo = createCombo(reposGroup); } private void createCommitGroup(Composite comp) { Group commitGroup = SWTWidgetHelper.createGroup(comp, "Hg root settings", 1, GridData.FILL_HORIZONTAL); Composite commitComp = createComposite(commitGroup, 2); createLabel(commitComp, "Default commit name:"); commitText = createTextField(commitComp); commitText.setText(HgCommitMessageManager.getDefaultCommitName(hgRoot)); } private void createButtons(final HgRepositoryLocationManager mgr) { Composite buttonComposite = createComposite(reposGroup, 3); final Button addRepo = createPushButton(buttonComposite, "Add...", 1); addRepo.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { NewLocationWizard wizard = new NewLocationWizard(); WizardDialog dialog = new WizardDialog(addRepo.getShell(), wizard); int result = dialog.open(); if(result != Window.OK){ return; } if(wizard.getRepository() != null){ updateSelection(mgr.getAllRepoLocations(), wizard.getRepository()); } } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); final Button modifyRepo = createPushButton(buttonComposite, "Modify...", 1); modifyRepo.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { if (defTextField.getData() != null) { PreferenceDialog dialog = PreferencesUtil.createPropertyDialogOn(addRepo .getShell(), (IAdaptable) defTextField.getData(), "com.vectrace.MercurialEclipse.repositoryProperties", null, null); dialog.open(); } } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); final Button deleteRepo = createPushButton(buttonComposite, "Delete...", 1); deleteRepo.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { IHgRepositoryLocation repo = (IHgRepositoryLocation) defTextField.getData(); if (repo != null) { Set locationRoots = mgr.getAllRepoLocationRoots(repo); String message; if ((locationRoots.size() == 1 && !locationRoots.contains(hgRoot)) || locationRoots.size() > 1) { message = "Delete repository '" + repo.getLocation() + "'?" + "\nAt least one other project still uses this repository!"; } else { message = "Delete repository '" + repo.getLocation() + "'?"; } boolean confirm = MessageDialog.openConfirm(getShell(), "Mercurial", message); if(confirm){ mgr.disposeRepository(repo); updateSelection(mgr.getAllRepoLocations(), null); } } } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); } private void updateSelection(final Set allRepos, IHgRepositoryLocation defLoc) { allReposCombo.removeAll(); int idx = -1; int defIndex = idx; for (final IHgRepositoryLocation repo : allRepos) { idx++; allReposCombo.add(repo.getLocation()); if(defLoc != null && defLoc.equals(repo)){ defIndex = idx; } } if(defIndex >= 0) { allReposCombo.select(defIndex); } else if(idx >= 0){ allReposCombo.select(idx); } setSelectedRepo(defLoc); } @Override public boolean performOk() { if (hgRoot == null) { return super.performOk(); } final HgRepositoryLocationManager mgr = MercurialEclipsePlugin.getRepoManager(); IHgRepositoryLocation defLoc = mgr.getDefaultRepoLocation(hgRoot); IHgRepositoryLocation data = (IHgRepositoryLocation) defTextField.getData(); if (data != null && (defLoc == null || !defTextField.getText().equals(defLoc.getLocation()))) { mgr.setDefaultRepository(hgRoot, data); } String commitName = commitText.getText().trim(); String defaultCommitName = HgCommitMessageManager.getDefaultCommitName(hgRoot); if(!defaultCommitName.equals(commitName)) { HgCommitMessageManager.setDefaultCommitName(hgRoot, commitName); } return super.performOk(); } @Override protected void performApply() { this.performOk(); } @Override public boolean isValid() { if (hgRoot == null) { return super.isValid(); } IHgRepositoryLocation data = (IHgRepositoryLocation) defTextField.getData(); if (data == null) { return false; } String commitName = commitText.getText().trim(); if(commitName.length() == 0) { return false; } return super.isValid(); } @Override protected void performDefaults() { if (hgRoot == null) { return; } final HgRepositoryLocationManager mgr = MercurialEclipsePlugin.getRepoManager(); IHgRepositoryLocation defLoc = mgr.getDefaultRepoLocation(hgRoot); if(defLoc != null){ defTextField.setText(defLoc.getLocation()); defTextField.setData(defLoc); } else { defTextField.setText(""); defTextField.setData(null); } Set allRepos = mgr.getAllRepoLocations(); updateSelection(allRepos, defLoc); commitText.setText(HgCommitMessageManager.getDefaultCommitName(hgRoot)); super.performDefaults(); } private void updateDefaultRepo() { HgRepositoryLocationManager mgr = MercurialEclipsePlugin.getRepoManager(); final Set repos = mgr.getAllRepoLocations(); for (IHgRepositoryLocation repo : repos) { if(repo.getLocation().equals(allReposCombo.getText())){ setSelectedRepo(repo); } } } private void setSelectedRepo(IHgRepositoryLocation repo) { defTextField.setData(repo); if(repo != null) { defTextField.setText(repo.getLocation()); } else { defTextField.setText(""); } updateApplyButton(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/LocationChooser.java000066400000000000000000000260521173713500500327500ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Administrator - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.io.File; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ResourceListSelectionDialog; import org.eclipse.ui.dialogs.SaveAsDialog; import com.vectrace.MercurialEclipse.utils.ClipboardUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.wizards.Messages; /** * control for choose location: clipboard, file or workspace file * * @author Administrator * */ public class LocationChooser extends Composite implements Listener { public enum LocationType { Clipboard, FileSystem, Workspace } private Button btnClipboard; private Button btnFilesystem; private Text txtSystemFile; private Button btnBrowseFileSystem; private Button btnWorkspace; private Text txtWorkspaceFile; private Button btnBrowseWorkspace; private final boolean save; private final ListenerList stateListeners = new ListenerList(); private final IDialogSettings settings; // constructors public LocationChooser(Composite parent, boolean save, IDialogSettings settings) { this(parent, save, settings, null); } public LocationChooser(Composite parent, boolean save, IDialogSettings settings, String defaultFileName) { super(parent, SWT.None); GridLayout layout = new GridLayout(); layout.numColumns = 3; setLayout(layout); createLocationControl(); this.save = save; this.settings = settings; restoreSettings(defaultFileName); } // operations protected void createLocationControl() { btnClipboard = SWTWidgetHelper.createRadioButton(this, Messages .getString("ExportPatchWizard.Clipboard"), 3); //$NON-NLS-1$ btnClipboard.addListener(SWT.Selection, this); btnFilesystem = SWTWidgetHelper.createRadioButton(this, Messages .getString("ExportPatchWizard.FileSystem"), //$NON-NLS-1$ 1); btnFilesystem.addListener(SWT.Selection, this); txtSystemFile = SWTWidgetHelper.createTextField(this); txtSystemFile.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { fireStateChanged(); } }); txtSystemFile.addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { ((Text) e.getSource()).selectAll(); } }); btnBrowseFileSystem = SWTWidgetHelper.createPushButton(this, "...", 1); //$NON-NLS-1$ btnBrowseFileSystem.addListener(SWT.Selection, this); btnWorkspace = SWTWidgetHelper.createRadioButton(this, Messages .getString("ExportPatchWizard.Workspace"), 1); //$NON-NLS-1$ btnWorkspace.addListener(SWT.Selection, this); txtWorkspaceFile = SWTWidgetHelper.createTextField(this); txtWorkspaceFile.setEditable(false); btnBrowseWorkspace = SWTWidgetHelper.createPushButton(this, "...", 1); //$NON-NLS-1$ btnBrowseWorkspace.addListener(SWT.Selection, this); } public void handleEvent(Event event) { if (event.widget == btnBrowseFileSystem) { FileDialog dialog = new FileDialog(getDisplay().getActiveShell(), SWT.PRIMARY_MODAL | (save ? SWT.SAVE : SWT.OPEN)); // dialog.setText("Choose file to save"); dialog.setFileName(txtSystemFile.getText()); String file = dialog.open(); if (file != null) { txtSystemFile.setText(new Path(file).toOSString()); } } else if (event.widget == btnBrowseWorkspace) { if (save) { SaveAsDialog dialog = new SaveAsDialog(getDisplay() .getActiveShell()); IFile file = getWorkspaceFile(); if (file != null) { dialog.setOriginalFile(file); } else { dialog.setOriginalName(txtWorkspaceFile.getText()); } // dialog.setText(txtWorkspaceFile.getText()); // dialog.setTitle(getTitle()); if (dialog.open() == Window.OK) { txtWorkspaceFile.setText(dialog.getResult().toString()); } } else { // no folder // OpenResourceDialog dialog = new // OpenResourceDialog(getShell(),ResourcesPlugin.getWorkspace().getRoot(),IResource.FILE); // multi // ResourceSelectionDialog dialog = new // ResourceSelectionDialog(getShell(), // ResourcesPlugin.getWorkspace().getRoot(),null); ResourceListSelectionDialog dialog = new ResourceListSelectionDialog( getShell(), ResourcesPlugin.getWorkspace().getRoot(), IResource.FILE); List list = new ArrayList(1); list.add(txtWorkspaceFile.getText()); dialog.setInitialElementSelections(list); dialog.open(); Object[] result = dialog.getResult(); if (result != null && result.length > 0) { txtWorkspaceFile.setText(((IFile) result[0]).getFullPath() .toPortableString()); } } } else if (event.widget == btnClipboard || event.widget == btnFilesystem || event.widget == btnWorkspace) { updateBtnStatus(); } fireStateChanged(); } public String validate() { boolean valid = false; LocationType type = getLocationType(); if (type == null) { return null; } switch (type) { case Workspace: // valid = isValidWorkSpaceLocation(getWorkspaceFile()); // break; case FileSystem: valid = isValidSystemFile(getPatchFile()); break; case Clipboard: return validateClipboard(); } if (valid) { return null; } return Messages.getString("ExportPatchWizard.InvalidFileName"); //$NON-NLS-1$ } private String validateClipboard() { if (save) { return null; } return ClipboardUtils.isEmpty() ? Messages .getString("LocationChooser.clipboardEmpty") : null; //$NON-NLS-1$ } private boolean isValidSystemFile(File file) { if (file == null || file.getPath().length() == 0) { return false; } if (!file.isAbsolute()) { return false; } if (file.isDirectory()) { return false; } if (save) { File parent = file.getParentFile(); if (parent == null) { return false; } if (!parent.exists()) { return false; } if (!parent.isDirectory()) { return false; } } else { if (!file.exists()) { return false; } } return true; } public File getPatchFile() { switch (getLocationType()) { case FileSystem: return btnFilesystem.getSelection() ? new File(txtSystemFile .getText()) : null; case Clipboard: return null; case Workspace: IFile file = getWorkspaceFile(); return file == null ? null : ResourceUtils.getFileHandle(file); default: return null; } } private IFile getWorkspaceFile() { if (!btnWorkspace.getSelection() || txtWorkspaceFile.getText() == null || txtWorkspaceFile.getText().length() == 0) { return null; } try { IPath parentToWorkspace = new Path(txtWorkspaceFile.getText()); return ResourcesPlugin.getWorkspace().getRoot().getFile( parentToWorkspace); } catch (Throwable e) { // Invalid path return null; } } // private boolean isValidWorkSpaceLocation(IFile file) { // if (save) // return file != null && file.getParent().exists(); // return file != null && file.exists(); // } public LocationType getLocationType() { if (btnClipboard.getSelection()) { return LocationType.Clipboard; } else if (btnFilesystem.getSelection()) { return LocationType.FileSystem; } else if (btnWorkspace.getSelection()) { return LocationType.Workspace; } return null; } private void updateBtnStatus() { LocationType type = getLocationType(); txtSystemFile.setEnabled(type == LocationType.FileSystem); btnBrowseFileSystem.setEnabled(type == LocationType.FileSystem); txtWorkspaceFile.setEnabled(type == LocationType.Workspace); btnBrowseWorkspace.setEnabled(type == LocationType.Workspace); } public void addStateListener(Listener listener) { stateListeners.add(listener); } protected void fireStateChanged() { for (Object obj : stateListeners.getListeners()) { ((Listener) obj).handleEvent(null); } } public Location getCheckedLocation() { return new Location(getLocationType(), getPatchFile(), getWorkspaceFile()); } public static class Location { private final LocationType locationType; public LocationType getLocationType() { return locationType; } public File getFile() { return file; } public IFile getWorkspaceFile() { return workspaceFile; } private final File file; private final IFile workspaceFile; public Location(LocationType locationType, File file, IFile workspaceFile) { this.locationType = locationType; this.file = file; this.workspaceFile = workspaceFile; } } /** * @param defaultFilename May be null */ protected void restoreSettings(String defaultFileName) { if (settings == null) { return; } String val; if ((val = settings.get("LocationType")) != null) { setLocationType(LocationType.valueOf(val)); } if ((val = applyDefaultFileName(defaultFileName, settings.get("TxtSystemFile"))) != null) { txtSystemFile.setText(val); } if ((val = applyDefaultFileName(defaultFileName, settings.get("TxtWorkspaceFile"))) != null) { txtWorkspaceFile.setText(val); } } private static String applyDefaultFileName(String defaultFileName, String val) { if (val == null) { return defaultFileName; } else if (defaultFileName == null || defaultFileName.length() == 0) { return val; } int nEnd = Math.max(val.lastIndexOf('\\'), val.lastIndexOf('/')); if (nEnd >= 0) { return val.substring(0, nEnd + 1) + defaultFileName; } return defaultFileName; } public void saveSettings() { if (settings == null) { return; } settings.put("LocationType", getLocationType().name()); settings.put("TxtSystemFile", txtSystemFile.getText()); settings.put("TxtWorkspaceFile", txtWorkspaceFile.getText()); } private void setLocationType(LocationType type) { switch (type) { case Clipboard: btnClipboard.setSelection(true); break; case FileSystem: btnFilesystem.setSelection(true); break; case Workspace: btnWorkspace.setSelection(true); break; } updateBtnStatus(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/Messages.java000066400000000000000000000021151173713500500314160ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.ui.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/PatchTable.java000066400000000000000000000066111173713500500316630ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Bastian Doetsch - adaptation to patches * Andrei Loskutov - bug fixes * Philip Graf - refactoring: replaced Table with TableViewer *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.ArrayList; import java.util.List; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.viewers.ColumnLayoutData; import org.eclipse.jface.viewers.ColumnPixelData; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import com.vectrace.MercurialEclipse.model.Patch; /** * * @author Jerome Negre */ public class PatchTable extends AbstractHighlightableTable { public PatchTable(Composite parent) { super(parent, new PatchTableLabelProvider()); } /** * @see com.vectrace.MercurialEclipse.ui.AbstractHighlightableTable#createColumns(org.eclipse.jface.viewers.TableViewer, org.eclipse.jface.layout.TableColumnLayout) */ @Override protected List createColumns(TableViewer viewer, TableColumnLayout tableColumnLayout) { List l = new ArrayList(4); String[] titles = { Messages.getString("PatchTable.index"), //$NON-NLS-1$ Messages.getString("PatchTable.applied"), //$NON-NLS-1$ Messages.getString("PatchTable.name"), //$NON-NLS-1$ Messages.getString("PatchTable.summary") }; //$NON-NLS-1$ ColumnLayoutData[] columnWidths = { new ColumnPixelData(20, false, true), new ColumnPixelData(75, false, true), new ColumnWeightData(25, 200, true), new ColumnWeightData(75, 200, true) }; for (int i = 0; i < titles.length; i++) { TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE); column.getColumn().setText(titles[i]); tableColumnLayout.setColumnData(column.getColumn(), columnWidths[i]); l.add(column); } return l; } private static class PatchTableLabelProvider extends HighlightingLabelProvider { public Image getColumnImage(Object element, int columnIndex) { return null; } public String getColumnText(Object element, int columnIndex) { Patch patch = (Patch) element; switch (columnIndex) { case 0: return String.valueOf(patch.getIndex()); case 1: return patch.isApplied() ? Messages.getString("PatchTable.statusApplied") : Messages.getString("PatchTable.statusUnapplied"); //$NON-NLS-1$ //$NON-NLS-2$ case 2: return patch.getName(); case 3: return patch.getSummary(); } return null; } /** * @see com.vectrace.MercurialEclipse.ui.AbstractHighlightableTable.HighlightingLabelProvider#isHighlighted(java.lang.Object) */ @Override public boolean isHighlighted(Patch patch) { return patch.isApplied(); } } } ResourcesTreeContentProvider.java000066400000000000000000000042131173713500500354310ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.Set; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.viewers.Viewer; import org.eclipse.ui.model.BaseWorkbenchContentProvider; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; public class ResourcesTreeContentProvider extends BaseWorkbenchContentProvider { //the pseudo-root public static final Object ROOT = new Object(); //the real roots private final Set roots; public ResourcesTreeContentProvider(Set roots) { super(); this.roots = roots; } @Override public Object[] getChildren(Object parentElement) { if(parentElement == ROOT) { return roots.toArray(new IResource[0]); } else if(parentElement instanceof IContainer){ try { return ((IContainer) parentElement).members(); } catch (CoreException e) { MercurialEclipsePlugin.logWarning(Messages.getString("ResourcesTreeContentProvider.failedToGetChildrenOf")+parentElement, e); //$NON-NLS-1$ return new Object[0]; } } else { return new Object[0]; } } @Override public Object getParent(Object element) { return ((IResource) element).getParent(); } @Override public boolean hasChildren(Object element) { return element == ROOT || element instanceof IContainer; } @Override public Object[] getElements(Object inputElement) { return getChildren(inputElement); } @Override public void dispose() { } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/SWTWidgetHelper.java000066400000000000000000000320471173713500500326370ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.preference.ColorFieldEditor; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.preference.FontFieldEditor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.source.AnnotationModel; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; /** * @author bastian * */ public final class SWTWidgetHelper { public static final int LABEL_WIDTH_HINT = 400; public static final int LABEL_INDENT_WIDTH = 32; public static final int LIST_HEIGHT_HINT = 100; public static final int SPACER_HEIGHT = 8; private SWTWidgetHelper() { // hide constructor of utility class. } /** * Creates a new checkbox instance and sets the default layout data. * * @param group * the composite in which to create the checkbox * @param label * the string to set into the checkbox * @return the new checkbox */ public static Button createCheckBox(Composite group, String label) { Button button = new Button(group, SWT.CHECK | SWT.LEFT); button.setText(label); GridData data = new GridData(); data.horizontalSpan = 2; button.setLayoutData(data); return button; } /** * @return */ public static GridData getFillGD(int minHeight) { GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); gd.minimumHeight = minHeight; return gd; } public static Button createPushButton(Composite parent, String label, int span) { Button button = new Button(parent, SWT.PUSH); button.setText(label); GridData data = new GridData(); data.horizontalSpan = span; button.setLayoutData(data); return button; } public static ColorFieldEditor createColorFieldEditor(String preferenceName, String label, Composite parent, DialogPage page, IPreferenceStore preferenceStore) { ColorFieldEditor editor = new ColorFieldEditor(preferenceName, label, parent); editor.setPage(page); editor.setPreferenceStore(preferenceStore); return editor; } /** * Utility method that creates a combo box * * @param parent * the parent for the new label * @return the new widget */ public static Combo createCombo(Composite parent) { Combo combo = new Combo(parent, SWT.READ_ONLY); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; combo.setLayoutData(data); return combo; } /** * Utility method that creates an editable combo box * * @param parent * the parent for the new label * @return the new widget */ public static Combo createEditableCombo(Composite parent) { Combo combo = new Combo(parent, SWT.NULL); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; combo.setLayoutData(data); return combo; } /** * Creates composite control and sets the default layout data. * * @param parent * the parent of the new composite * @param numColumns * the number of columns for the new composite * @return the newly-created coposite */ public static Composite createComposite(Composite parent, int numColumns) { Composite composite = new Composite(parent, SWT.NULL); // GridLayout GridLayout layout = new GridLayout(); layout.numColumns = numColumns; composite.setLayout(layout); // GridData GridData data = new GridData(GridData.FILL_HORIZONTAL); data.verticalAlignment = SWT.FILL; data.horizontalAlignment = SWT.FILL; composite.setLayoutData(data); return composite; } /** * Utility method that creates a label instance and sets the default layout data. * * @param parent * the parent for the new label * @param text * the text for the new label * @return the new label */ public static Label createLabel(Composite parent, String text) { return createIndentedLabel(parent, text, 0); } /** * Utility method that creates a label instance indented by the specified number of pixels and * sets the default layout data. * * @param parent * the parent for the new label * @param text * the text for the new label * @param indent * the indent in pixels, or 0 for none * @return the new label */ public static Label createIndentedLabel(Composite parent, String text, int indent) { Label label = new Label(parent, SWT.LEFT); label.setText(text); GridData data = new GridData(); data.horizontalSpan = 1; data.horizontalAlignment = GridData.FILL; data.horizontalIndent = indent; label.setLayoutData(data); return label; } /** * Utility method that creates a label instance with word wrap and sets the default layout data. * * @param parent * the parent for the new label * @param text * the text for the new label * @param indent * the indent in pixels, or 0 for none * @param widthHint * the nominal width of the label * @return the new label */ public static Label createWrappingLabel(Composite parent, String text, int indent) { return createWrappingLabel(parent, text, indent, 1); } public static Label createWrappingLabel(Composite parent, String text, int indent, int horizontalSpan) { Label label = new Label(parent, SWT.LEFT | SWT.WRAP); label.setText(text); GridData data = new GridData(); data.horizontalSpan = horizontalSpan; data.horizontalAlignment = GridData.FILL; data.horizontalIndent = indent; data.grabExcessHorizontalSpace = true; data.widthHint = SWTWidgetHelper.LABEL_WIDTH_HINT; label.setLayoutData(data); return label; } /** * Create a text field specific for this application * * @param parent * the parent of the new text field * @return the new text field */ public static Text createTextField(Composite parent) { Text text = new Text(parent, SWT.SINGLE | SWT.BORDER); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.verticalAlignment = GridData.CENTER; data.grabExcessVerticalSpace = false; data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; text.setLayoutData(data); return text; } /** * Create a password entry field specific for this application * * @param parent * the parent of the new text field * @return the new password field */ public static Text createPasswordField(Composite parent) { Text text = new Text(parent, SWT.SINGLE | SWT.BORDER | SWT.PASSWORD); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.verticalAlignment = GridData.CENTER; data.grabExcessVerticalSpace = false; data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; text.setLayoutData(data); return text; } /** * Utility method to create a radio button * * @param parent * the parent of the radio button * @param label * the label of the radio button * @param span * the number of columns to span * @return the created radio button */ public static Button createRadioButton(Composite parent, String label, int span) { Button button = new Button(parent, SWT.RADIO); button.setText(label); GridData data = new GridData(); data.horizontalSpan = span; button.setLayoutData(data); return button; } /** * Utility method to create a full width separator preceeded by a blank space * * @param parent * the parent of the separator * @param verticalSpace * the vertical whitespace to insert before the label */ public static void createSeparator(Composite parent, int verticalSpace) { // space Label label = new Label(parent, SWT.NONE); GridData data = new GridData(); data.heightHint = verticalSpace; label.setLayoutData(data); // separator label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL); data = new GridData(GridData.FILL_HORIZONTAL); label.setLayoutData(data); } /** * Creates a ListViewer * * @param parent * the parent of the viewer * @param title * the text for the title label * @param heightHint * the nominal height of the list * @param the * label decorator * @return the created list viewer */ public static ListViewer createListViewer(Composite parent, String title, int heightHint, IBaseLabelProvider labelProvider) { if (title != null) { createLabel(parent, title); } ListViewer listViewer = new ListViewer(parent, SWT.READ_ONLY | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.MULTI); listViewer.setContentProvider(new IStructuredContentProvider() { public Object[] getElements(Object inputElement) { return (Object[]) inputElement; } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); listViewer.setLabelProvider(labelProvider); GridData data = new GridData(GridData.FILL_BOTH); data.heightHint = heightHint; listViewer.getList().setLayoutData(data); listViewer.setUseHashlookup(true); return listViewer; } public static Group createGroup(Composite parent, String text, int span, int style) { Group group = new Group(parent, SWT.NULL); group.setText(text); GridData data = new GridData(style); data.horizontalSpan = span; // data.widthHint = GROUP_WIDTH; group.setLayoutData(data); GridLayout layout = new GridLayout(); layout.numColumns = span; group.setLayout(layout); return group; } public static Group createGroup(Composite parent, String text) { return createGroup(parent, text, GridData.FILL_HORIZONTAL); } public static Group createGroup(Composite parent, String text, int style) { return createGroup(parent, text, 2, style); } public static SourceViewer createTextArea(Composite container) { SourceViewer textBox = new SourceViewer(container, null, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.WRAP); textBox.setEditable(true); // set up spell-check annotations final SourceViewerDecorationSupport decorationSupport = new SourceViewerDecorationSupport( textBox, null, new DefaultMarkerAnnotationAccess(), EditorsUI.getSharedTextColors()); AnnotationPreference pref = EditorsUI.getAnnotationPreferenceLookup() .getAnnotationPreference(SpellingAnnotation.TYPE); decorationSupport.setAnnotationPreference(pref); decorationSupport.install(EditorsUI.getPreferenceStore()); textBox.configure(new TextSourceViewerConfiguration(EditorsUI.getPreferenceStore())); textBox.setDocument(new Document(), new AnnotationModel()); textBox.getTextWidget().addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { decorationSupport.uninstall(); } }); GridData data = new GridData(GridData.FILL_BOTH); // data.heightHint = heightHint; textBox.getControl().setLayoutData(data); return textBox; } /** * @param prefHistoryMergeChangesetFont * @param string * @param g * @param historyPreferencePage * @param preferenceStore * @return */ public static FieldEditor createFontFieldEditor(String pref, String label, Composite parent, DialogPage page, IPreferenceStore preferenceStore) { FontFieldEditor editor = new FontFieldEditor(pref, label, parent); editor.setPage(page); editor.setPreferenceStore(preferenceStore); return editor; } /* * incompatible with 3.2 public static DateTime createDateTime(Composite c, int style) { * DateTime dt = new DateTime(c, style); GridData data = new GridData(GridData.FILL_HORIZONTAL); * data.verticalAlignment = GridData.CENTER; data.grabExcessVerticalSpace = false; * data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; dt.setLayoutData(data); return dt; } */ } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/TableSortListener.java000066400000000000000000000040241173713500500332550ustar00rootroot00000000000000package com.vectrace.MercurialEclipse.ui; import java.util.Arrays; import java.util.Comparator; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; /** * Sorts a table. Should listen to column selection */ @SuppressWarnings("unchecked") public abstract class TableSortListener implements Listener { private final Comparator[] comparators; private final Table table; public TableSortListener(Table table, Comparator[] comparators) { this.table = table; this.comparators = comparators; } public void handleEvent(Event e) { if (!canSort()) { MessageDialog.openInformation(table.getShell(), "Table not loaded", "Cannot sort because the table is not fully loaded"); return; } // determine new sort column and direction TableColumn sortColumn = table.getSortColumn(); TableColumn currentColumn = (TableColumn) e.widget; int dir = table.getSortDirection(); if (sortColumn == currentColumn) { dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; } else { table.setSortColumn(currentColumn); dir = SWT.UP; } // sort the data based on column and direction int nIdx = 0; for (TableColumn c : table.getColumns()) { if (c == currentColumn) { break; } nIdx++; } Object[] data = getData(); Arrays.sort(data, comparators[nIdx]); if (dir == SWT.DOWN) { for (int i = 0, n = data.length; i < n / 2; i++) { Object temp = data[i]; data[i] = data[n - i - 1]; data[n - i - 1] = temp; } } // update data displayed in table table.setSortDirection(dir); table.clearAll(); } /** * @return False if the data is not fully loaded and so can't be sorted */ protected boolean canSort() { return true; } /** * @return The data. Will be sorted in place */ protected abstract Object[] getData(); public static int sort(int a, int b) { if (a == b) { return 0; } return a < b ? -1 : 1; } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/TagTable.java000066400000000000000000000212411173713500500313330ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) - bug fixes * Philip Graf - bug fix *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Tag; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; /** * @author Jerome Negre * @author Zsolt Koppany */ public class TagTable extends Composite { private static final Font PARENT_FONT = JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT); private final Table table; private int[] parents; private boolean showTip; private HgRoot hgRoot; private ItemMediator[] data; @SuppressWarnings("unchecked") public TagTable(Composite parent, HgRoot hgRoot) { super(parent, SWT.NONE); showTip = true; this.hgRoot = hgRoot; this.setLayout(new GridLayout()); this.setLayoutData(new GridData()); table = new Table(this, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL); table.setItemCount(0); table.setLinesVisible(true); table.setHeaderVisible(true); table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); String[] titles = { Messages.getString("TagTable.column.rev"), Messages.getString("TagTable.column.global"), Messages.getString("TagTable.column.tag"), Messages.getString("TagTable.column.local"), Messages.getString("ChangesetTable.column.summary") }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ int[] widths = { 60, 150, 200, 70, 300 }; Comparator[] comparators = { new Comparator() { public int compare(ItemMediator a, ItemMediator b) { return TableSortListener.sort(a.tag.getRevision(), b.tag.getRevision()); } }, new Comparator() { public int compare(ItemMediator a, ItemMediator b) { return a.tag.getGlobalId().compareTo(b.tag.getGlobalId()); } }, new Comparator() { public int compare(ItemMediator a, ItemMediator b) { return a.tag.getName().compareTo(b.tag.getName()); } }, new Comparator() { public int compare(ItemMediator a, ItemMediator b) { return TableSortListener.sort(a.tag.isLocal() ? 0 : 1, b.tag.isLocal() ? 0 : 1); } }, new Comparator() { public int compare(ItemMediator a, ItemMediator b) { return a.summary.compareTo(b.summary); } } }; Listener sortListener = new TableSortListener(table, comparators) { @Override protected Object[] getData() { return data; } }; for (int i = 0; i < titles.length; i++) { TableColumn column = new TableColumn(table, SWT.NONE); column.setText(titles[i]); column.setWidth(widths[i]); column.addListener(SWT.Selection, sortListener); } table.addListener(SWT.SetData, new Listener() { public void handleEvent(org.eclipse.swt.widgets.Event event) { TableItem item = (TableItem) event.item; int index = table.indexOf(item); if (data != null && 0 <= index && index < data.length) { data[index].setTableItem(item); } } }); } public void hideTip() { this.showTip = false; } public void highlightParents(int[] newParents) { this.parents = newParents; } public void setHgRoot(HgRoot newRoot) { this.hgRoot = newRoot; table.removeAll(); } public void setTags(Tag[] tags) { List filtered = new ArrayList(tags.length); for (Tag tag : tags) { if (showTip || !tag.isTip()) { filtered.add(new ItemMediator(tag)); } } data = filtered.toArray(new ItemMediator[filtered.size()]); table.clearAll(); table.setItemCount(data.length); fetchChangesetInfo(data); } /** * Fetch changeset comments. * * @param tags That tags for which to get comments */ void fetchChangesetInfo(final ItemMediator[] tags) { final LocalChangesetCache cache = LocalChangesetCache.getInstance(); Job fetchJob = new Job("Retrieving changesets info") { @Override protected IStatus run(IProgressMonitor monitor) { // this can cause UI hang for big projects. Should be done in a job. // the only reason we need this is to show the changeset comments, so we can complete // this data in background Map tagged = new HashMap(); try { Set allLocalRevisions = cache.refreshAllLocalRevisions(hgRoot, false, false); for (ChangeSet cs : allLocalRevisions) { if(monitor.isCanceled()) { return Status.CANCEL_STATUS; } for (Tag tag : cs.getTags()) { tagged.put(tag.getName(), cs); } } } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); } final Map tagToCs = new HashMap(); for (ItemMediator tag : tags) { if(monitor.isCanceled()) { return Status.CANCEL_STATUS; } if (showTip || !tag.tag.isTip()) { ChangeSet changeSet = tagged.get(tag.tag.getName()); if(changeSet != null) { tagToCs.put(tag, changeSet); } } } Runnable updateTable = new Runnable() { public void run() { for (ItemMediator item : data) { if (tagToCs.get(item) != null) { item.setSummary(tagToCs.get(item).getSummary()); } } } }; MercurialEclipsePlugin.getStandardDisplay().asyncExec(updateTable); return Status.OK_STATUS; } }; fetchJob.schedule(); } public Tag getSelection() { TableItem[] selection = table.getSelection(); if (selection.length == 0) { return null; } return (Tag) selection[0].getData(); } public void addSelectionListener(SelectionListener listener) { table.addSelectionListener(listener); } private boolean isParent(int r) { if (parents == null) { return false; } switch (parents.length) { case 2: if (r == parents[1]) { return true; } //$FALL-THROUGH$ case 1: if (r == parents[0]) { return true; } //$FALL-THROUGH$ default: return false; } } // inner types /** * This would require synchronization, but it's only being called from the UI thread. */ private class ItemMediator { public final Tag tag; private TableItem item; public String summary; // constructor public ItemMediator(Tag tag) { this.tag = tag; } // operations /** * Set the summary. Must be called from the UI thread. * @param summary The summary to set */ public void setSummary(String summary) { this.summary = summary; if (item != null && !item.isDisposed()) { item.setText(4, summary); } } /** * Apply the tag information to the row. Must be called from the UI thread. * * @param curItem * The table row */ public void setTableItem(TableItem curItem) { if (isParent(tag.getRevision())) { curItem.setFont(PARENT_FONT); } curItem.setText(0, Integer.toString(tag.getRevision())); curItem.setText(1, tag.getGlobalId()); curItem.setText(2, tag.getName()); curItem.setText(3, tag.isLocal() ? Messages.getString("TagTable.stateLocal") //$NON-NLS-1$ : Messages.getString("TagTable.stateGlobal")); curItem.setData(tag); this.item = curItem; if (summary != null) { item.setText(4, summary); } } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/UntrackedFilesFilter.java000066400000000000000000000024451173713500500337260ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * StefanC - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import com.vectrace.MercurialEclipse.dialogs.CommitResource; public class UntrackedFilesFilter extends ViewerFilter { private final boolean allowMissing; public UntrackedFilesFilter(boolean allowMissing){ super(); this.allowMissing = allowMissing; } /** * Filter out untracked files. */ @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof CommitResource){ CommitResource cres = (CommitResource) element; if (cres.isUnknown()) { return false; } if (!allowMissing && cres.isMissing()) { return false; } } return true; } }UntrackedResourcesFilter.java000066400000000000000000000046121173713500500345550ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.ui; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class UntrackedResourcesFilter extends ViewerFilter { private final Map> untrackedFiles; private final Map> untrackedFolders; public UntrackedResourcesFilter(Map> untrackedFiles, Map> untrackedFolders) { super(); this.untrackedFiles = untrackedFiles; this.untrackedFolders = untrackedFolders; } @Override public boolean select(Viewer viewer, Object parentElement, Object element) { IResource resource = (IResource) element; HgRoot hgRoot = MercurialTeamProvider.getHgRoot(resource); if(hgRoot == null){ // paranoia return false; } String path = hgRoot.toRelative(ResourceUtils.getFileHandle(resource)); if(resource.getType() == IResource.FILE) { Set set = untrackedFiles.get(hgRoot); return set != null && matchesPath(path, set); } else if(resource.getType() == IResource.FOLDER){ Set set = untrackedFolders.get(hgRoot); return set != null && matchesPath(path, set); } else { // project return untrackedFolders.containsKey(hgRoot); } } /** * @param pathStrToTest * @param untrackedPaths known untracked files * @return true if the path to test matches one of known untracked paths */ private static boolean matchesPath(String pathStrToTest, Set untrackedPaths) { IPath pathToTest = new Path(pathStrToTest); return untrackedPaths.contains(pathToTest); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/ui/messages.properties000066400000000000000000000027211173713500500327340ustar00rootroot00000000000000BookmarkTable.column.global=Global BookmarkTable.column.name=Name BookmarkTable.column.rev=Revision BookmarkTable.column.state=State BookmarkTable.stateActive=active BookmarkTable.stateInactive=inactive BranchTable.column.active=Active BranchTable.column.branch=Branch BranchTable.column.global=Global BranchTable.column.rev=Revision BranchTable.stateActive=active BranchTable.stateInactive=inactive ChangesetInfoTray.changedFiles=Changed files ChangesetInfoTray.changeset=Changeset: ChangesetInfoTray.changesetToBeAmended=Changeset to be amended ChangesetInfoTray.comment=Comment: ChangesetInfoTray.date=Date: ChangesetInfoTray.tags=Tags: ChangesetInfoTray.user=User: ChangesetTable.column.author=Author ChangesetTable.column.branch=Branch ChangesetTable.column.date=Date ChangesetTable.column.global=Global ChangesetTable.column.rev=Revision ChangesetTable.column.summary=Summary PatchTable.index=\# PatchTable.applied=Status PatchTable.name=Name PatchTable.statusApplied=Applied PatchTable.statusUnapplied=Unapplied PatchTable.summary=Message Summary ResourcesTreeContentProvider.failedToGetChildrenOf=Failed to get children of TagTable.column.global=Global TagTable.column.local=Local TagTable.column.rev=Revision TagTable.column.tag=Tag TagTable.stateGlobal=global TagTable.stateLocal=local Common.ColumnFile=File Common.ColumnStatus=Status Common.SelectOrUnselectAll=Select/unselect all Common.ShowUntrackedFiles=Show untracked files CommitFilesChooser.showDiffButton.text=Show Diff eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/000077500000000000000000000000001173713500500275305ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/Base64Coder.java000066400000000000000000000137151173713500500324030ustar00rootroot00000000000000// Copyright 2003-2009 Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland // www.source-code.biz, www.inventec.ch/chdh // // This module is multi-licensed and may be used under the terms // of any of the following licenses: // // EPL, Eclipse Public License, http://www.eclipse.org/legal // LGPL, GNU Lesser General Public License, http://www.gnu.org/licenses/lgpl.html // AL, Apache License, http://www.apache.org/licenses // BSD, BSD License, http://www.opensource.org/licenses/bsd-license.php // // Please contact the author if you need another license. // This module is provided "as is", without warranties of any kind. package com.vectrace.MercurialEclipse.utils; /** * A Base64 Encoder/Decoder. * *

* This class is used to encode and decode data in Base64 format as described in RFC 1521. * *

* Home page: www.source-code.biz
* Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland
* Multi-licensed: EPL/LGPL/AL/BSD. * *

* Version history:
* 2003-07-22 Christian d'Heureuse (chdh): Module created.
* 2005-08-11 chdh: Lincense changed from GPL to LGPL.
* 2006-11-21 chdh:
*   Method encode(String) renamed to encodeString(String).
*   Method decode(String) renamed to decodeString(String).
*   New method encode(byte[],int) added.
*   New method decode(String) added.
* 2009-07-16: Additional licenses (EPL/AL) added.
* 2009-09-16: Additional license (BSD) added.
*/ public final class Base64Coder { // Mapping table from 6-bit nibbles to Base64 characters. private static char[] map1 = new char[64]; static { int i = 0; for (char c = 'A'; c <= 'Z'; c++) { map1[i++] = c; } for (char c = 'a'; c <= 'z'; c++) { map1[i++] = c; } for (char c = '0'; c <= '9'; c++) { map1[i++] = c; } map1[i++] = '+'; map1[i++] = '/'; } // Mapping table from Base64 characters to 6-bit nibbles. private static byte[] map2 = new byte[128]; static { for (int i = 0; i < map2.length; i++) { map2[i] = -1; } for (int i = 0; i < 64; i++) { map2[map1[i]] = (byte) i; } } /** * Encodes a string into Base64 format. No blanks or line breaks are inserted. * * @param s * a String to be encoded. * @return A String with the Base64 encoded data. */ public static String encodeString(String s) { return new String(encode(s.getBytes())); } /** * Encodes a byte array into Base64 format. No blanks or line breaks are inserted. * * @param in * an array containing the data bytes to be encoded. * @return A character array with the Base64 encoded data. */ public static char[] encode(byte[] in) { return encode(in, in.length); } /** * Encodes a byte array into Base64 format. No blanks or line breaks are inserted. * * @param in * an array containing the data bytes to be encoded. * @param iLen * number of bytes to process in in. * @return A character array with the Base64 encoded data. */ public static char[] encode(byte[] in, int iLen) { int oDataLen = (iLen * 4 + 2) / 3; // output length without padding int oLen = ((iLen + 2) / 3) * 4; // output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++] & 0xff; int i1 = ip < iLen ? in[ip++] & 0xff : 0; int i2 = ip < iLen ? in[ip++] & 0xff : 0; int o0 = i0 >>> 2; int o1 = ((i0 & 3) << 4) | (i1 >>> 4); int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); int o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : '='; op++; out[op] = op < oDataLen ? map1[o3] : '='; op++; } return out; } /** * Decodes a string from Base64 format. * * @param s * a Base64 String to be decoded. * @return A String containing the decoded data. * @throws IllegalArgumentException * if the input is not valid Base64 encoded data. */ public static String decodeString(String s) { return new String(decode(s)); } /** * Decodes a byte array from Base64 format. * * @param s * a Base64 String to be decoded. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException * if the input is not valid Base64 encoded data. */ public static byte[] decode(String s) { return decode(s.toCharArray()); } /** * Decodes a byte array from Base64 format. No blanks or line breaks are allowed within the * Base64 encoded data. * * @param in * a character array containing the Base64 encoded data. * @return An array containing the decoded data bytes. * @throws IllegalArgumentException * if the input is not valid Base64 encoded data. */ public static byte[] decode(char[] in) { int iLen = in.length; if (iLen % 4 != 0) { throw new IllegalArgumentException( "Length of Base64 encoded input string is not a multiple of 4."); } while (iLen > 0 && in[iLen - 1] == '=') { iLen--; } int oLen = (iLen * 3) / 4; byte[] out = new byte[oLen]; int ip = 0; int op = 0; while (ip < iLen) { int i0 = in[ip++]; int i1 = in[ip++]; int i2 = ip < iLen ? in[ip++] : 'A'; int i3 = ip < iLen ? in[ip++] : 'A'; if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) { throw new IllegalArgumentException("Illegal character in Base64 encoded data."); } int b0 = map2[i0]; int b1 = map2[i1]; int b2 = map2[i2]; int b3 = map2[i3]; if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) { throw new IllegalArgumentException("Illegal character in Base64 encoded data."); } int o0 = (b0 << 2) | (b1 >>> 4); int o1 = ((b1 & 0xf) << 4) | (b2 >>> 2); int o2 = ((b2 & 3) << 6) | b3; out[op++] = (byte) o0; if (op < oLen) { out[op++] = (byte) o1; } if (op < oLen) { out[op++] = (byte) o2; } } return out; } // Dummy constructor. private Base64Coder() { } } // end class Base64Coder eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/Bits.java000066400000000000000000000022721173713500500312770ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; public final class Bits { private Bits(){ } /** * @return true if at least one of given bits is set in the source */ public static boolean contains(int source, int bits) { return (source & bits) != 0; } /** * @return true if ALL given bits are set in the source */ public static boolean matchesAll(int source, int bits) { return (source & bits) == bits; } public static int clear(int source, int bit) { return source & ~bit; } public static int highestBit(int source) { return Integer.highestOneBit(source); } public static int cardinality(int source) { return Integer.bitCount(source); } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/ChangeSetUtils.java000066400000000000000000000045261173713500500332640ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Philip Graf implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.Tag; /** * @author Philip Graf */ public final class ChangeSetUtils { private ChangeSetUtils() { // hide constructor of utility class. } /** * Returns a printable String listing of all tags of a changeset. If the changeset does not have * any tags, an empty String is returned. * * @param changeSet * The changeset. May be {@code null}. * @return a printable String listing all tags of a changeset. Never returns {@code null}. */ public static String getPrintableTagsString(ChangeSet changeSet) { String tagsString = ""; //$NON-NLS-1$ if (changeSet != null) { Tag[] tags = changeSet.getTags(); if (tags.length > 0) { StringBuilder builder = new StringBuilder(tags[0].getName()); for (int i = 1; i < tags.length; i++) { builder.append(", ").append(tags[i].getName()); //$NON-NLS-1$ } tagsString = builder.toString(); } } return tagsString; } /** * Returns the changeset index followed by the short revision. If the changeset is {@code null}, * an empty String is returned. If the short revision is not available, only the index is * returned. * *@param changeSet * The changeset. May be {@code null}. * @return the changeset index followed by the short revision. Never returns {@code null}. */ public static String getPrintableRevisionShort(ChangeSet changeSet) { String revisionShort; if (changeSet == null) { revisionShort = ""; //$NON-NLS-1$ } else if (changeSet.getNodeShort() == null) { revisionShort = Integer.toString(changeSet.getChangesetIndex()); } else { revisionShort = changeSet.getChangesetIndex() + ":" + changeSet.getNodeShort(); //$NON-NLS-1$ } return revisionShort; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/ClipboardUtils.java000066400000000000000000000064761173713500500333300ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Administrator implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import java.io.File; import java.io.FileWriter; import java.io.IOException; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.wizards.Messages; public final class ClipboardUtils { private ClipboardUtils() { // hide constructor of utility class. } /** * copy string to clipboard * * @param result */ public static void copyToClipboard(final String result) { if (result == null) { return; } if (MercurialEclipsePlugin.getStandardDisplay().getThread() == Thread .currentThread()) { Clipboard cb = new Clipboard(MercurialEclipsePlugin .getStandardDisplay()); cb.setContents(new Object[] { result }, new Transfer[] { TextTransfer.getInstance() }); cb.dispose(); return; } MercurialEclipsePlugin.getStandardDisplay().syncExec(new Runnable() { public void run() { copyToClipboard(result); } }); } /** * @return string message from clipboard */ public static String getClipboardString() { if (MercurialEclipsePlugin.getStandardDisplay().getThread() == Thread .currentThread()) { Clipboard cb = new Clipboard(MercurialEclipsePlugin .getStandardDisplay()); String result = (String) cb.getContents(TextTransfer.getInstance()); cb.dispose(); return result; } final String[] r = { null }; MercurialEclipsePlugin.getStandardDisplay().syncExec(new Runnable() { public void run() { r[0] = getClipboardString(); } }); return r[0]; } public static File clipboardToTempFile(String prefix, String suffix) throws HgException { File file = null; String txt = getClipboardString(); if (txt == null || txt.trim().length() == 0) { return null; } FileWriter w = null; try { file = File.createTempFile(prefix, suffix); w = new FileWriter(file); w.write(txt); return file; } catch (IOException e) { if (file != null && file.exists()) { boolean deleted = file.delete(); if(!deleted){ MercurialEclipsePlugin.logError("Failed to delete clipboard content file: " + file, null); } } throw new HgException(Messages .getString("ClipboardUtils.error.writeTempFile"), e); //$NON-NLS-1$ } finally { if (w != null) { try { w.close(); } catch (IOException e1) { MercurialEclipsePlugin.logError(e1); } } } } public static boolean isEmpty() { Clipboard cb = new Clipboard(MercurialEclipsePlugin .getStandardDisplay()); String contents = (String) cb.getContents(TextTransfer.getInstance()); cb.dispose(); return contents == null || contents.trim().length() == 0; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/CompareUtils.java000066400000000000000000000305051173713500500330050ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import java.util.TreeSet; import org.eclipse.compare.CompareConfiguration; import org.eclipse.compare.CompareEditorInput; import org.eclipse.compare.CompareUI; import org.eclipse.compare.internal.CompareEditor; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Display; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.core.variants.IResourceVariant; import org.eclipse.team.core.variants.IResourceVariantComparator; import org.eclipse.team.internal.ui.IPreferenceIds; import org.eclipse.team.internal.ui.TeamUIPlugin; import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration; import org.eclipse.team.ui.synchronize.SyncInfoCompareInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IReusableEditor; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.progress.UIJob; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.AbstractClient; import com.vectrace.MercurialEclipse.commands.HgLocateClient; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.compare.HgCompareEditorInput; import com.vectrace.MercurialEclipse.compare.RevisionNode; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgFile; import com.vectrace.MercurialEclipse.model.HgFolder; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgResource; import com.vectrace.MercurialEclipse.model.NullHgFile; import com.vectrace.MercurialEclipse.synchronize.MercurialResourceVariant; import com.vectrace.MercurialEclipse.synchronize.MercurialResourceVariantComparator; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; /** * This class helps to invoke the compare facilities of Eclipse. * @author bastian */ @SuppressWarnings("restriction") public final class CompareUtils { public static final IResourceVariantComparator COMPARATOR = new MercurialResourceVariantComparator(); private CompareUtils() { // hide constructor of utility class. } public static void openEditor(IFile file, ChangeSet changeset) throws HgException { int changesetIndex = changeset == null ? 0 : changeset.getChangesetIndex(); String changesetId = changeset == null ? null : changeset.getChangeset(); openEditor(file, new MercurialRevisionStorage(file, changesetIndex, changesetId, changeset), false, null); } public static void openEditor(IResource resource, ChangeSet changeset) throws HgException { String changesetId = changeset == null ? null : changeset.getChangeset(); IHgResource left = null; IHgResource right = null; HgRoot root = MercurialRootCache.getInstance().getHgRoot(resource); if(resource instanceof IContainer) { String inPattern = AbstractClient.getHgResourceSearchPattern(resource); String[] status = HgStatusClient.getStatus(root, changesetId, null, "-mardu", inPattern, null); TreeSet filter = HgStatusClient.removeStatusIndicator(status); left = new HgFolder(root, (IContainer)resource, filter); right = HgLocateClient.getHgResources(resource, changeset, filter); } else if (resource instanceof IFile) { left = new HgFile(root, (IFile)resource); right = HgLocateClient.getHgResources(resource, changeset, null); } openEditor(new RevisionNode(left), new RevisionNode(right), false, null); } public static void openEditor(MercurialRevisionStorage left, MercurialRevisionStorage right, boolean dialog) { openEditor(left, right, dialog, null); } public static void openEditor(MercurialRevisionStorage left, MercurialRevisionStorage right, boolean dialog, ISynchronizePageConfiguration configuration) { if (right == null && left != null) { // comparing with file-system try { openEditor(left.getResource(), left, dialog, configuration); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } else { RevisionNode leftNode = getNode(left); RevisionNode rightNode = getNode(right); openEditor(leftNode, rightNode, dialog, configuration); } } /** * Open a compare editor asynchronously * * @param configuration might be null */ public static void openEditor(final RevisionNode left, final RevisionNode right, final boolean dialog, final ISynchronizePageConfiguration configuration) { Assert.isNotNull(right); if (dialog) { // TODO: is it intentional the config is ignored? openCompareDialog(getCompareInput(left, right, null)); } else { openEditor(getCompareInput(left, right, configuration)); } } /** * Open a compare editor asynchronously * * @param configuration might be null * @throws HgException */ public static void openEditor(final IResource left, final MercurialRevisionStorage right, final boolean dialog, final ISynchronizePageConfiguration configuration) throws HgException { Assert.isNotNull(right); openEditor(left, getNode(right), dialog, configuration); } public static void openEditor(final IResource left, final RevisionNode right, final boolean dialog, final ISynchronizePageConfiguration configuration) throws HgException { Assert.isNotNull(right); if(!left.getProject().isOpen()) { final boolean [] open = new boolean[1]; Runnable runnable = new Runnable() { public void run() { open[0] = MessageDialog.openQuestion(null, "Compare", "To compare selected file, enclosing project must be opened.\n" + "Open the appropriate project (may take time)?"); } }; Display.getDefault().syncExec(runnable); if(open[0]) { try { left.getProject().open(null); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } else { return; } } if (dialog) { // TODO: is it intentional the config is ignored? openCompareDialog(getPrecomputedCompareInput(null, left, null, right)); } else { openEditor(getPrecomputedCompareInput(configuration, left, null, right)); } } private static void openEditor(final CompareEditorInput compareInput) { UIJob uiDiffJob = new UIJob("Preparing hg diff...") { @Override public IStatus runInUIThread(IProgressMonitor monitor) { IWorkbenchPage workBenchPage = MercurialEclipsePlugin.getActivePage(); boolean reuse = TeamUIPlugin.getPlugin().getPreferenceStore().getBoolean( IPreferenceIds.REUSE_OPEN_COMPARE_EDITOR); IEditorPart editor = null; if(reuse) { IEditorReference[] editorRefs = workBenchPage.getEditorReferences(); for (IEditorReference ref : editorRefs) { IEditorPart part = ref.getEditor(false); if(part != null && part instanceof CompareEditor){ editor = part; break; } } } if (editor == null) { CompareUI.openCompareEditor(compareInput); return Status.OK_STATUS; } // re-use existing editor enforces Eclipse to re-compare the both sides // even if the compare editor already opened the file. The point is, that the // file may be changed by user after opening the compare editor and so editor // still shows "old" diff state and to be updated. See also issue #10757. CompareUI.reuseCompareEditor(compareInput, (IReusableEditor) editor); // provide focus to editor workBenchPage.activate(editor); return Status.OK_STATUS; } }; uiDiffJob.schedule(); } /** * Opens a compare dialog using the given input. * * @param compareInput * @return */ private static int openCompareDialog(final CompareEditorInput compareInput) { Runnable uiAction = new Runnable() { public void run() { CompareUI.openCompareDialog(compareInput); } }; Display.getDefault().asyncExec(uiAction); return Window.CANCEL; } /** * @param configuration might be null */ private static CompareEditorInput getCompareInput(RevisionNode left, RevisionNode right, ISynchronizePageConfiguration configuration) { // switch left to right if left is null and put local to left RevisionNode leftNode = left != null ? left : right; return new HgCompareEditorInput(new CompareConfiguration(), leftNode, right, findCommonAncestorIfExists(left, right), configuration); } public static CompareEditorInput getPrecomputedCompareInput(IResource leftResource, MercurialRevisionStorage ancestor, MercurialRevisionStorage right) throws HgException { return getPrecomputedCompareInput(null, leftResource, getNode(ancestor), getNode(right)); } private static CompareEditorInput getPrecomputedCompareInput( ISynchronizePageConfiguration configuration, IResource leftResource, RevisionNode ancestor, RevisionNode iResourceNode) throws HgException { IResourceVariant ancestorRV = getResourceVariant(ancestor); IResourceVariant rightRV = getResourceVariant(iResourceNode); if (ancestorRV == null) { // 2 way diff ancestorRV = rightRV; } SyncInfo syncInfo = new SyncInfo(leftResource, ancestorRV, rightRV, COMPARATOR); try { syncInfo.init(); } catch(TeamException e) { throw new HgException(e); } if (configuration == null) { return new SyncInfoCompareInput(leftResource.getName(), syncInfo); } return new SyncInfoCompareInput(configuration, syncInfo); } private static IResourceVariant getResourceVariant(RevisionNode storage) { return storage == null ? null : new MercurialResourceVariant(storage); } private static RevisionNode getNode(MercurialRevisionStorage rev) { if (rev == null) { return null; } IHgResource hgresource = null; try { hgresource = HgLocateClient.getHgResources(rev.getResource(), rev.getChangeSet(), null); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } if (hgresource != null) { // existing file return new RevisionNode(hgresource); } // non-existing file IFile file = rev.getResource(); HgRoot hgRoot = MercurialRootCache.getInstance().getHgRoot(file); return new RevisionNode(new NullHgFile(hgRoot, rev.getChangeSet(), file.getFullPath().makeRelativeTo(hgRoot.getIPath()))); } private static RevisionNode findCommonAncestorIfExists(RevisionNode lNode, RevisionNode rNode) { if (lNode == null || lNode.isWorkingCopy() || rNode.isWorkingCopy()) { return null; } HgRoot hgRoot = lNode.getHgResource().getHgRoot(); ChangeSet lCS = lNode.getHgResource().getChangeSet(); ChangeSet rCS = rNode.getHgResource().getChangeSet(); if (hgRoot == null || lCS == null || rCS == null) { return null; } String commonAncestor = null; try { commonAncestor = HgParentClient.findCommonAncestor(hgRoot,lCS, rCS)[1]; } catch (HgException e) { // continue } String lId = lCS.getChangeset(); String rId = rCS.getChangeset(); if (commonAncestor == null || commonAncestor.length() == 0){ try { commonAncestor = HgParentClient.findCommonAncestor(hgRoot, lId, rId)[1]; } catch (HgException e) { // continue: no changeset in the local repo, se issue #10616 } } if (commonAncestor == null || commonAncestor.equals(lCS.getChangeset()) || commonAncestor.equals(rCS.getChangeset())) { return null; } //TODO: should apply filter here and recreate left and right IHgResource hgResource = HgLocateClient.getHgResources(lNode.getHgResource(), commonAncestor, null); return new RevisionNode(hgResource); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/IniFile.java000066400000000000000000000232671173713500500317240ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * wleggette implementation * Andrei Loskutov - bug fixes * Zsolt Koppany (Intland) * Philip Graf - Fixed bugs which FindBugs found *******************************************************************************/ /* ==================================================================== * * @PROJECT.FULLNAME@ @VERSION@ License. * * Copyright (c) @YEAR@ L2FProd.com. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by L2FProd.com * (http://www.L2FProd.com/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "@PROJECT.FULLNAME@", "SkinLF" and "L2FProd.com" must not * be used to endorse or promote products derived from this software * without prior written permission. For written permission, please * contact info@L2FProd.com. * * 5. Products derived from this software may not be called "SkinLF" * nor may "SkinLF" appear in their names without prior written * permission of L2FProd.com. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL L2FPROD.COM OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ package com.vectrace.MercurialEclipse.utils; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * @author $Author: l2fprod $ * @created 27 avril 2002 * $Id$ */ public class IniFile { private final Map> sections; /** * Constructor for the IniFile object */ public IniFile() { sections = new HashMap>(); } /** * Constructor for the IniFile object * * @param filename * Description of Parameter * @exception FileNotFoundException * Description of Exception */ public IniFile(String filename) throws FileNotFoundException { this(); load(filename); } /** * Sets the KeyValue attribute of the IniFile object * * @param section * The new KeyValue value * @param key * The new KeyValue value * @param value * The new KeyValue value */ public void setKeyValue(String section, String key, String value) { Map section2 = getSection(section); if(section2 != null) { section2.put(key.toLowerCase(), value); } } /** * Gets the Sections attribute of the IniFile object * * @return The Sections value */ public Map> getSections() { return sections; } /** * Gets the Section attribute of the IniFile object * * @param section * Description of Parameter * @return The Section value */ public Map getSection(String section) { if(section == null){ return sections.get(null); } return sections.get(section.toLowerCase()); } /** * Gets the NullOrEmpty attribute of the IniFile object * * @param section * Description of Parameter * @param key * Description of Parameter * @return The NullOrEmpty value */ public boolean isNullOrEmpty(String section, String key) { String value = getKeyValue(section, key); return value == null || value.length() == 0; } /** * Gets the KeyValue attribute of the IniFile object. If the specified section is null, only values that * are defined before the first section may be returned * * @param section * Description of Parameter * @param key * Description of Parameter * @return The KeyValue value */ public String getKeyValue(String section, String key) { Map section2 = getSection(section); if(section2 != null) { return section2.get(key.toLowerCase()); } return null; } /** * Gets the KeyIntValue attribute of the IniFile object * * @param section * Description of Parameter * @param key * Description of Parameter * @return The KeyIntValue value */ public int getKeyIntValue(String section, String key) { return getKeyIntValue(section, key, 0); } /** * Gets the KeyIntValue attribute of the IniFile object * * @param section * Description of Parameter * @param key * Description of Parameter * @param defaultValue * Description of Parameter * @return The KeyIntValue value */ public int getKeyIntValue(String section, String key, int defaultValue) { String value = getKeyValue(section, key.toLowerCase()); if (value == null) { return defaultValue; } try { return Integer.parseInt(value); } catch (NumberFormatException e) { return 0; } } /** * Description of the Method * * @param filename * Description of Parameter * @exception FileNotFoundException * Description of Exception */ public void load(String filename) throws FileNotFoundException { FileInputStream in = new FileInputStream(filename); try { load(in); } finally { try { in.close(); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } } /** * Description of the Method * * @param filename * Description of Parameter * @exception IOException * Description of Exception */ public void save(String filename) throws IOException { FileOutputStream out = new FileOutputStream(filename); try { save(out); } finally { try { out.close(); } catch (IOException e) { // ignore } } } /** * Loads the whole init file. Values that are defined before the first section are stored in the null section. * * @param in * Description of Parameter */ private void load(InputStream in) { try { BufferedReader input = new BufferedReader(new InputStreamReader(in)); try { Map section = null; String sectionName; for (String read = null; (read = input.readLine()) != null;) { if (read.startsWith(";") || read.startsWith("#")) { continue; } else if (read.startsWith("[")) { // new section sectionName = read.substring(1, read.indexOf("]")).toLowerCase(); section = sections.get(sectionName); if (section == null) { section = new HashMap(); sections.put(sectionName, section); } } else if (read.indexOf("=") != -1) { if(section == null){ // create the null-section entry section = new HashMap(); sections.put(null, section); } // new key String key = read.substring(0, read.indexOf("=")).trim().toLowerCase(); String value = read.substring(read.indexOf("=") + 1).trim(); section.put(key, value); } } } finally { input.close(); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } /** * Description of the Method * * @param out * Description of Parameter */ private void save(OutputStream out) { try { PrintWriter output = new PrintWriter(out); try { for (String section : sections.keySet()) { output.println("[" + section + "]"); for (Map.Entry entry : getSection(section).entrySet()) { output.println(entry.getKey() + "=" + entry.getValue()); } } } finally { output.close(); } } finally { try { out.close(); } catch (IOException ex) { } } } /** * Adds a feature to the Section attribute of the IniFile object * * @param section * The feature to be added to the Section attribute */ public void addSection(String section) { sections.put(section.toLowerCase(), new HashMap()); } /** * Description of the Method * * @param section * Description of Parameter */ public void removeSection(String section) { } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/Messages.java000066400000000000000000000021231173713500500321400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.utils.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/PatchUtils.java000066400000000000000000000104441173713500500324560ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.compare.patch.ApplyPatchOperation; import org.eclipse.compare.patch.IFilePatch; import org.eclipse.compare.patch.IFilePatchResult; import org.eclipse.compare.patch.PatchConfiguration; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; /** * @author bastian * */ public final class PatchUtils { public static final Pattern DIFF_START_PATTERN = Pattern.compile("^diff -r ", Pattern.MULTILINE); private PatchUtils() { // hide constructor of utility class. } /** * @param outgoingPatch * @return * @throws HgException */ public static IFilePatch[] getFilePatches(String outgoingPatch) throws HgException { if (outgoingPatch == null) { return new IFilePatch[0]; } Matcher matcher = PatchUtils.DIFF_START_PATTERN.matcher(outgoingPatch); if (matcher.find()) { final String strippedPatch = outgoingPatch.substring(matcher .start(), outgoingPatch.length()); try { return PatchUtils.createPatches(strippedPatch); } catch (CoreException e) { throw new HgException(e); } } return new IFilePatch[0]; } public static IFilePatch[] createPatches(final String patch) throws CoreException { return ApplyPatchOperation.parsePatch(new IStorage() { public InputStream getContents() throws CoreException { return new ByteArrayInputStream(patch.getBytes()); } public IPath getFullPath() { return null; } public String getName() { return null; } public boolean isReadOnly() { return true; } public Object getAdapter( @SuppressWarnings("unchecked") Class adapter) { return null; } }); } /** * Gets an input stream containing the patched contents of the given file. * It patches doesn't contain the file, the file contents are returned. * * @param file * the file to be patched * @param patches * the result of a parsed patch string * @param reversed * if true, a reverse patch will be done * @return * @throws CoreException */ public static InputStream getPatchedContents(IFile file, IFilePatch[] patches, boolean reversed) throws CoreException { for (IFilePatch patch : patches) { String[] headerWords = patch.getHeader().split(" "); String patchPath = headerWords[headerWords.length - 1].trim(); if (file.getFullPath().toString().endsWith(patchPath)) { PatchConfiguration configuration = new PatchConfiguration(); configuration.setReversed(reversed); IFilePatchResult patchResult = patch.apply(file, configuration, null); return patchResult.getPatchedContents(); } } /* If there's no patch, we just return no differences */ return file.getContents(); } public static byte[] getPatchedContentsAsBytes(IFile file, IFilePatch[] patches, boolean reversed) throws CoreException { InputStream stream = getPatchedContents(file, patches, reversed); ByteArrayOutputStream bos = null; try { bos = new ByteArrayOutputStream(); byte[] tmpBytes = new byte[8192]; int read; while((read = stream.read(tmpBytes)) > 0){ bos.write(tmpBytes, 0, read); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); return new byte[0]; } finally { try { stream.close(); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } return bos.toByteArray(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/ResourceUtils.java000066400000000000000000000607331173713500500332140ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian - implementation * Andrei Loskutov - bugfixes * Zsolt Koppany (Intland) *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.ide.ResourceUtil; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgLocateClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileFromChangeSet; import com.vectrace.MercurialEclipse.model.HgFile; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgResource; import com.vectrace.MercurialEclipse.model.NullHgFile; import com.vectrace.MercurialEclipse.model.PathFromChangeSet; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.NullRevision; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.MercurialRootCache; /** * @author bastian * @author Andrei Loskutov */ public final class ResourceUtils { public static final IPath[] NO_PATHS = new Path[0]; private static final File TMP_ROOT = new File(System.getProperty("java.io.tmpdir")); private static long tmpFileSuffix; private ResourceUtils() { // hide constructor of utility class. } public static File getSystemTempDirectory() { return TMP_ROOT; } /** * @return a newly created temp directory which is located inside the default temp directory */ public static File createNewTempDirectory() { File tmp = getSystemTempDirectory(); File newTemp = null; while (!(newTemp = new File(tmp, "hgTemp_" + tmpFileSuffix)).mkdir()) { tmpFileSuffix++; } return newTemp; } /** * If "recursive" is false, then this is a single file/directory delete operation. Directory * should be empty before it can be deleted. If "recursive" is true, then all children will be * deleted too. * * @param source * @return true if source was successfully deleted or if it was not existing */ public static boolean delete(File source, boolean recursive) { if (source == null || !source.exists()) { return true; } if (recursive) { if (source.isDirectory()) { for (File file : source.listFiles()) { boolean ok = delete(file, true); if (!ok) { return false; } } } } boolean result = source.delete(); if (!result && !source.isDirectory()) { MercurialEclipsePlugin.logWarning("Could not delete file '" + source + "'", null); } return result; } /** * Moves contents of one directory to another and deletes source directory if all files were * successfully moved to destination. If any target file with the same relative path exists in the * destination directory, it will be NOT overridden, and kept in the source directory. * * @param sourceDir * - must already exist and be a directory * @param destinationDir * - must already exist and be a directory * @return true if source was successfully moved to destination. */ public static boolean move(File sourceDir, File destinationDir) { File[] files = sourceDir.listFiles(); if(files == null) { // can't be ok return false; } Set fileSet = new LinkedHashSet(Arrays.asList(files)); boolean result = true; while (!fileSet.isEmpty()) { File next = fileSet.iterator().next(); String relative = toRelative(sourceDir, next); File dest = new File(destinationDir, relative); if (!dest.exists()) { result &= next.renameTo(dest); } else if(next.isDirectory()){ files = next.listFiles(); if(files != null) { fileSet.addAll(Arrays.asList(files)); } } else { // file exists in target result = false; } fileSet.remove(next); } try { if(result && !sourceDir.getCanonicalFile().equals(destinationDir.getCanonicalFile())) { return ResourceUtils.delete(sourceDir, true); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); } return false; } /** * Converts given path to the relative * * @param parent * parent path, non null * @param child * a possible child path, non null * @return a parent relative path of a given child file, if the given child file is located * under given parent, otherwise the given child path. If the given child path matches * the parent, returns an empty string */ public static String toRelative(File parent, File child) { // first try with the unresolved path. In most cases it's enough String fullPath = child.getAbsolutePath(); String parentpath = parent.getPath(); if (!fullPath.startsWith(parentpath)) { try { // ok, now try to resolve all the links etc. this takes A LOT of time... fullPath = child.getCanonicalPath(); if (!fullPath.startsWith(parentpath)) { return child.getPath(); } } catch (IOException e) { MercurialEclipsePlugin.logError(e); return child.getPath(); } } if(fullPath.equals(parentpath)){ return Path.EMPTY.toOSString(); } // +1 is to remove the file separator / at the start of the relative path return fullPath.substring(parentpath.length() + 1); } /** * Checks which editor is active an determines the IResource that is edited. */ public static IFile getActiveResourceFromEditor() { IEditorPart editorPart = MercurialEclipsePlugin.getActivePage().getActiveEditor(); if (editorPart != null) { IFileEditorInput input = (IFileEditorInput) editorPart.getEditorInput(); IFile file = ResourceUtil.getFile(input); return file; } return null; } /** * @param resource * a handle to possibly non-existing resource * @return a (file) path representing given resource, never null. May return an "empty" file. */ public static File getFileHandle(IResource resource) { return getPath(resource).toFile(); } /** * Tries to determine the encoding for a file resource. Returns null, if the encoding cannot be * determined. */ public static String getFileEncoding(IFile resource){ try{ String charset = resource.getCharset(true); if(charset != null) { new String(new byte[]{}, charset); //test that JVM has the charset available } return charset; } catch (CoreException e) { //cannot determine the file charset return null; } catch (UnsupportedEncodingException e) { //unknown encoding, ignore the request return null; } } /** * @param path * a path to possibly non-existing or not mapped resource * @return a (file) representing given resource, may return null if the resource is not in the * workspace */ public static IFile getFileHandle(IPath path) { if(path == null) { return null; } return (IFile) getHandle(path, true); } private static IResource getHandle(final IPath origPath, boolean isFile) { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); // origPath may be canonical but not necessarily. // Eclipse allows a project to be symlinked or an arbitrary folder under a project // to be symlinked. Also Eclipse allows a subtree of one project to exist as another // project. // Mercurial doesn't follow symbolic links so if path is canonical it is sufficient to find // a containing hg root. hg roots are always canonical. // There is an unresolvable ambiguity when a project with a sub repo is imported // as a project. Such cases are unsupported for now. // If one of the candidate resources is under a Mercurial managed project it must // be returned. IPath[] paths = NO_PATHS; IResource best = null; loop: for (int i = 0;; i++) { IPath path; switch (i) { case 0: path = origPath; break; case 1: // Only query the root cache if the plain path didn't find a definite match. paths = MercurialRootCache.getInstance().uncanonicalize(origPath); //$FALL-THROUGH$ default: if (i - 1 >= paths.length) { break loop; } path = paths[i - 1]; } URI uri = URIUtil.toURI(path.makeAbsolute()); IResource[] resources = isFile ? root.findFilesForLocationURI(uri) : root .findContainersForLocationURI(uri); if (resources.length > 0) { if (resources.length == 1) { best = resources[0]; } else { // try to find the first file contained in a hg root and managed by our team // provider for (IResource resource : resources) { if (MercurialTeamProvider.isHgTeamProviderFor(resource.getProject())) { return resource; } } } } else { best = ifNull(isFile ? root.getFileForLocation(path) : root .getContainerForLocation(path), best); } IProject proj; // Is best a definite match? if (best != null && (proj = best.getProject()) != null && MercurialTeamProvider.isHgTeamProviderFor(proj)) { return best; } } if(best == null) { Collection roots = MercurialRootCache.getInstance().getKnownHgRoots(); for (HgRoot hgRoot : roots) { if(!hgRoot.getIPath().isPrefixOf(origPath)) { continue; } IPath relative = hgRoot.toRelative(origPath); if(relative.isEmpty()) { if(!isFile) { // same folder as root return hgRoot.getResource(); } // requested is file => some error! return null; } best = hgRoot.getResource().findMember(relative); if(best != null) { if(isFile && best.getType() == IResource.FILE || ! isFile && best.getType() != IResource.FILE) { return best; } if(isFile) { return hgRoot.getResource().getFile(relative); } return hgRoot.getResource().getFolder(relative); } } } if(best != null) { return best; } // here we didn't found any existing file matching any hg root // but we can try to return a handle to not existing resource, // according to API contract of IResource.getFile() // second try: now we return also handles to currently not existing files // if they *could* be located under the first matching root Collection roots = MercurialRootCache.getInstance().getKnownHgRoots(); for (HgRoot hgRoot : roots) { if(!hgRoot.getIPath().isPrefixOf(origPath)) { continue; } IPath relative = hgRoot.toRelative(origPath); if(!relative.isEmpty()) { if(isFile) { return hgRoot.getResource().getFile(relative); } return hgRoot.getResource().getFolder(relative); } } return null; } private static IResource ifNull(IResource a, IResource b) { return a == null ? b : a; } /** * @param resource * a handle to possibly non-existing resource * @return a (file) path representing given resource, might be {@link Path#EMPTY} in case the * resource location and project location are both unknown. {@link Path#EMPTY} return * value will be logged as error unless virtual. */ public static IPath getPath(IResource resource) { IPath path = resource.getLocation(); if (path == null) { // file was removed IProject project = resource.getProject(); IPath projectLocation = project.getLocation(); if (projectLocation == null) { // project removed too, there is no way to correctly determine the right // location in case project is not located under workspace or project name doesn't // match project root folder name String message = "Failed to resolve location for resource (project deleted): " + resource; MercurialEclipsePlugin.logWarning(message, new IllegalStateException(message)); return Path.EMPTY; } URI locationURI = resource.getLocationURI(); if(isVirtual(locationURI)) { // path is null for virtual folders => we can't do anything here return Path.EMPTY; } path = projectLocation.append(resource.getFullPath().removeFirstSegments(1)); } return path; } /** * see issue 12500: we should check whether the resource is virtual *

* TODO as soon as 3.5 is not supported, use resource.isVirtual() call * * @param locationURI * may be null * @return true if the given path is null OR is virtual location */ public static boolean isVirtual(URI locationURI) { return locationURI == null || "virtual".equals(locationURI.getScheme()); } /** * @param linked non null linked resource * @return may return null if the link target is not inside workspace */ public static IResource getRealLocation(IResource linked) { IPath path = getPath(linked); if(path.isEmpty()) { return null; } IResource handle = getHandle(path, linked.getType() == IResource.FILE); if(handle == null || handle.isLinked()) { return null; } return handle; } /** * Converts a {@link java.io.File} to a workspace resource */ public static IResource convert(File file) throws HgException { String canonicalPath; try { canonicalPath = file.getCanonicalPath(); } catch (IOException e) { throw new HgException(e.getLocalizedMessage(), e); } return getHandle(new Path(canonicalPath), !file.isDirectory()); } /** * For a given path, tries to find out first existing parent directory * * @param path * may be null * @return may return null */ public static File getFirstExistingDirectory(File path) { while (path != null && !path.isDirectory()) { path = path.getParentFile(); } return path; } /** * For a given path, tries to find out first existing parent directory * * @param res * may be null * @return may return null */ public static IContainer getFirstExistingDirectory(IResource res) { if (res == null) { return null; } IContainer parent = res instanceof IContainer ? (IContainer) res : res.getParent(); if (parent instanceof IWorkspaceRoot) { return null; } while (parent != null && !parent.exists()) { parent = parent.getParent(); if (parent instanceof IWorkspaceRoot) { return null; } } return parent; } /** * @param resources * non null * @return never null */ public static Map> groupByProject(Collection resources) { Map> result = new HashMap>(); for (IResource resource : resources) { IProject root = resource.getProject(); List list = result.get(root); if (list == null) { list = new ArrayList(); result.put(root, list); } list.add(resource); } return result; } /** * @return never null, a list with all projects contained by given hg root directory */ public static Set getProjects(HgRoot root) { Set set = new HashSet(); IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject project : projects) { if (!project.isAccessible()) { continue; } HgRoot proot = MercurialRootCache.getInstance().hasHgRoot(project, true); if (proot == null) { continue; } if (root.equals(proot)) { set.add(project); } } return set; } /** * @param resources * non null * @return never null */ public static Map> groupByRoot(Collection resources) { Map> result = new HashMap>(); if (resources != null) { for (IResource resource : resources) { HgRoot root = MercurialRootCache.getInstance().hasHgRoot(resource, true); if (root == null) { continue; } List list = result.get(root); if (list == null) { list = new ArrayList(); result.put(root, list); } list.add(resource); } } return result; } public static void collectAllResources(IContainer root, Set children) { IResource[] members; try { members = root.members(); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return; } children.add(root); for (IResource res : members) { if (res instanceof IFolder && !res.equals(root)) { collectAllResources((IFolder) res, children); } else { children.add(res); } } } /** * Converts a HgRoot relative path to a project relative IResource. The specified hgRoot * can be higher than, deeper than, or at project level in the directory hierarchy. * @param hgRoot * non null * @param project * non null * @param repoRelPath * path relative to the hg root * @return may return null, if the path is not found in the project */ public static IResource convertRepoRelPath(HgRoot hgRoot, IProject project, String repoRelPath) { // determine absolute path IPath path = hgRoot.toAbsolute(repoRelPath); // determine project relative path int equalSegments = path.matchingFirstSegments(getPath(project)); path = path.removeFirstSegments(equalSegments); return project.findMember(path); } public static Set getMembers(IResource r) { return getMembers(r, true); } public static Set getMembers(IResource r, boolean withLinks) { HashSet set = new HashSet(); if (r instanceof IContainer && r.isAccessible()) { IContainer cont = (IContainer) r; try { IResource[] members = cont.members(); if (members != null) { for (IResource member : members) { if(!withLinks && member.isLinked()) { continue; } if (member instanceof IContainer) { set.addAll(getMembers(member)); } else { set.add(member); } } } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } set.add(r); return set; } /** * @param o * some object which is or can be adapted to resource * @return given object as resource, may return null */ public static IResource getResource(Object o) { if(o == null) { return null; } if (o instanceof IResource) { return (IResource) o; } if (o instanceof ChangeSet) { ChangeSet changeSet = (ChangeSet) o; Set files = changeSet.getFiles(); if (files.size() > 0) { IFile file = files.iterator().next(); if (files.size() == 1) { return file; } return file.getProject(); } return null; } if (o instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) o; IResource adapter = (IResource) adaptable.getAdapter(IResource.class); if (adapter != null) { return adapter; } adapter = (IResource) adaptable.getAdapter(IFile.class); if (adapter != null) { return adapter; } } return (IResource) Platform.getAdapterManager().getAdapter(o, IResource.class); } public static void touch(final IResource res) { Job job = new Job("Refresh for: " + res.getName()) { @Override protected IStatus run(IProgressMonitor monitor) { // triggers the decoration update try { if (res.isAccessible()) { res.touch(monitor); } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } return Status.OK_STATUS; } }; job.schedule(); } /** * @param selection may be null * @return never null , may be empty list containing all resources from given selection */ public static List getResources(IStructuredSelection selection) { List resources = new ArrayList(); List list = selection.toList(); for (Object object : list) { if(object instanceof ChangeSet) { Set files = ((ChangeSet)object).getFiles(); for (IFile file : files) { if(!resources.contains(file)) { resources.add(file); } } } else if(object instanceof PathFromChangeSet) { PathFromChangeSet pathFromChangeSet = (PathFromChangeSet) object; Set files = pathFromChangeSet.getFiles(); for (FileFromChangeSet ffc : files) { IFile file = ffc.getFile(); if(file != null && !resources.contains(file)) { resources.add(file); } } } else { IResource resource = getResource(object); if(resource != null && !resources.contains(resource)){ resources.add(resource); } } } return resources; } /** * This is optimized version of {@link IPath#isPrefixOf(IPath)} (30-50% faster). Main difference is * that we prefer the cheap operations first and check path segments starting from the * end of the first path (with the assumption that paths starts in most cases * with common paths segments => so we postpone redundant comparisons). * @param first non null * @param second non null * @return true if the first path is prefix of the second */ public static boolean isPrefixOf(IPath first, IPath second) { int len = first.segmentCount(); if (len > second.segmentCount()) { return false; } for (int i = len - 1; i >= 0; i--) { if (!first.segment(i).equals(second.segment(i))) { return false; } } return sameDevice(first, second); } private static boolean sameDevice(IPath first, IPath second) { String device = first.getDevice(); if (device == null) { if (second.getDevice() != null) { return false; } } else { if (!device.equalsIgnoreCase(second.getDevice())) { return false; } } return true; } /** * Opens appropriate editor * @param file must be not null * @param activePage can be null * @return */ public static IEditorPart openEditor(IWorkbenchPage activePage, IFile file) { if(activePage == null) { activePage = MercurialEclipsePlugin.getActivePage(); } try { if (file instanceof IHgResource) { return IDE.openEditor(activePage, file.getLocationURI(), EditorsUI.DEFAULT_TEXT_EDITOR_ID, true); } return IDE.openEditor(activePage, file); } catch (PartInitException e) { MercurialEclipsePlugin.logError(e); return null; } } /** * Get the IHgResource for the given resource as it is in the current repository revision. * * @param resource The resource to use * @return The resource as it would be if clean */ public static IHgResource getCleanLocalHgResource(IResource resource) { HgRoot hgRoot = MercurialTeamProvider.getHgRoot(resource); if (hgRoot == null) { return null; } ChangeSet cs = null; try { cs = LocalChangesetCache.getInstance().getChangesetForRoot(hgRoot); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } if(cs != null){ try { return HgLocateClient.getHgResources(resource, cs, null); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } return null; } /** * Convert deprecated MercurialRevisionStorage to HgFile */ public static IHgResource convertToHgFile(MercurialRevisionStorage rev) { IFile file = rev.getResource(); HgRoot hgRoot = MercurialRootCache.getInstance().getHgRoot(file); IPath relPath = ResourceUtils.getPath(file).makeRelativeTo(hgRoot.getIPath()); if (rev instanceof NullRevision) { return new NullHgFile(hgRoot, rev.getChangeSet(), relPath); } return new HgFile(hgRoot, rev.getChangeSet(), relPath); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/StringUtils.java000066400000000000000000000033151173713500500326640ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Adam Berkes (Intland) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import java.util.regex.Pattern; /** * General string manipulation functions set. * * @author adam.berkes */ public final class StringUtils { public static final String NEW_LINE = System.getProperty("line.separator"); private static final String OPTIONAL_BLANK_AND_TAB = "[ \t]*"; private static final String REGEX = OPTIONAL_BLANK_AND_TAB + "(\r|\n)+" + OPTIONAL_BLANK_AND_TAB; private static final Pattern NEWLINE_PATTERN = Pattern.compile(REGEX); private StringUtils() { // hide constructor of utility class. } /** * Removes all \r \n characters and optional leading and/or trailing blanks and TAB characters. * * @param text trimmed result * @return */ public static String removeLineBreaks(String text) { if (text != null && text.length() != 0) { text = NEWLINE_PATTERN.matcher(text).replaceAll(" "); text = text.trim(); } return text; } /** * @param text any kind of text * @return true if the text is either null or empty string */ public static boolean isEmpty(String text){ return text == null || text.trim().length() == 0; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/utils/messages.properties000066400000000000000000000002101173713500500334460ustar00rootroot00000000000000ClipboardUtils.error.writeTempFile=Error write temp file RepositoryGraph.changesetWasNull=Changeset was null, but must not be null :-(. eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/000077500000000000000000000000001173713500500275255ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/AbstractRootView.java000066400000000000000000000072731173713500500336430ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.views; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.part.ViewPart; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; /** * */ public abstract class AbstractRootView extends ViewPart implements ISelectionListener { protected HgRoot hgRoot; @Override public void createPartControl(Composite parent) { setContentDescription(getDescription()); parent.setLayout(new GridLayout(1, false)); createTable(parent); createActions(); createToolBar(getViewSite().getActionBars().getToolBarManager()); createMenus(getViewSite().getActionBars().getMenuManager()); getSite().getPage().addSelectionListener(this); } protected abstract void createTable(Composite parent); protected abstract void createActions(); protected abstract void createMenus(IMenuManager mgr); protected abstract void createToolBar(IToolBarManager mgr); protected static IContributionItem makeActionContribution(IAction a) { ActionContributionItem c = new ActionContributionItem(a); c.setMode(c.getMode() | ActionContributionItem.MODE_FORCE_TEXT); return c; } protected void handleError(CoreException e) { MercurialEclipsePlugin.logError(e); String sMessage; if (e instanceof HgException) { sMessage = ((HgException) e).getConciseMessage(); } else { sMessage = e.getLocalizedMessage(); } showWarning(sMessage); } protected void showWarning(String sMessage) { MessageDialog.openError(getSite().getShell(), "Error", fixCase(sMessage)); } private static String fixCase(String sMessage) { if (sMessage != null) { sMessage = sMessage.trim(); if (sMessage.length() > 0) { sMessage = Character.toUpperCase(sMessage.charAt(0)) + sMessage.substring(1); } } return sMessage; } @Override public void dispose() { getSite().getPage().removeSelectionListener(this); super.dispose(); } public final void refresh(HgRoot newRoot) { hgRoot = null; if (newRoot != null && canChangeRoot(newRoot, false)) { hgRoot = newRoot; } handleRootChanged(); } protected final void rootSelected(HgRoot newRoot) { if (newRoot != null && canChangeRoot(newRoot, true)) { hgRoot = newRoot; handleRootChanged(); } } private void handleRootChanged() { onRootChanged(); setContentDescription(getDescription()); } protected abstract String getDescription(); /** * Template method to customize root changing behavior * * @return True if the selection can be changed */ protected boolean canChangeRoot(HgRoot newRoot, boolean fromSelection) { return !newRoot.equals(hgRoot); } /** * Called when the selected root changes */ protected abstract void onRootChanged(); } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/MergeView.java000066400000000000000000000430021173713500500322610ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Jerome Negre - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.views; import java.util.ArrayList; import java.util.List; import java.util.Observable; import java.util.Observer; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.viewers.ColumnLayoutData; import org.eclipse.jface.viewers.ColumnPixelData; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.team.ui.TeamUI; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgResolveClient; import com.vectrace.MercurialEclipse.commands.extensions.HgRebaseClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.AbortRebaseHandler; import com.vectrace.MercurialEclipse.menu.CommitMergeHandler; import com.vectrace.MercurialEclipse.menu.ContinueRebaseHandler; import com.vectrace.MercurialEclipse.menu.RunnableHandler; import com.vectrace.MercurialEclipse.menu.UpdateHandler; import com.vectrace.MercurialEclipse.model.FlaggedAdaptable; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.CompareAction; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.ui.AbstractHighlightableTable; import com.vectrace.MercurialEclipse.ui.AbstractHighlightableTable.HighlightingLabelProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class MergeView extends AbstractRootView implements Observer { public static final String ID = MergeView.class.getName(); private MergeTable table; private Action abortAction; private Action completeAction; private Action markResolvedAction; private Action markUnresolvedAction; protected boolean merging = true; @Override public void createPartControl(final Composite parent) { super.createPartControl(parent); MercurialStatusCache.getInstance().addObserver(this); } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#createTable(org.eclipse.swt.widgets.Composite) */ @Override protected void createTable(Composite parent) { table = new MergeTable(parent); table.getTableViewer().addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { openMergeEditor((FlaggedAdaptable) ((IStructuredSelection) event.getSelection()).getFirstElement()); } }); } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#createActions() */ @Override protected void createActions() { completeAction = new Action(Messages.getString("MergeView.merge.complete")) { //$NON-NLS-1$ @Override public void run() { if (areAllResolved()) { attemptToCommit(); refresh(hgRoot); } } }; completeAction.setEnabled(false); completeAction.setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("actions/commit.gif")); abortAction = new Action(Messages.getString("MergeView.merge.abort")) { //$NON-NLS-1$ @Override public void run() { try { RunnableHandler runnable; if (!merging) { runnable = new AbortRebaseHandler(); } else { UpdateHandler update = new UpdateHandler(); update.setCleanEnabled(true); update.setRevision("."); runnable = update; } runnable.setShell(table.getShell()); runnable.run(hgRoot); refresh(hgRoot); } catch (CoreException e) { handleError(e); } MercurialUtilities.setOfferAutoCommitMerge(true); } }; abortAction.setEnabled(false); abortAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor( ISharedImages.IMG_ELCL_STOP)); markResolvedAction = new Action(Messages.getString("MergeView.markResolved")) { //$NON-NLS-1$ @Override public void run() { try { List files = getSelections(); if (files != null) { for (IFile file : files) { HgResolveClient.markResolved(file); } populateView(true); } } catch (HgException e) { handleError(e); } } }; markResolvedAction.setEnabled(false); markUnresolvedAction = new Action(Messages.getString("MergeView.markUnresolved")) { //$NON-NLS-1$ @Override public void run() { try { List files = getSelections(); if (files != null) { for (IFile file : files) { HgResolveClient.markUnresolved(file); } populateView(true); } } catch (HgException e) { handleError(e); } } }; markUnresolvedAction.setEnabled(false); } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#createToolBar(org.eclipse.jface.action.IToolBarManager) */ @Override protected void createToolBar(IToolBarManager mgr) { mgr.add(makeActionContribution(completeAction)); mgr.add(makeActionContribution(abortAction)); } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#createMenus(org.eclipse.jface.action.IMenuManager) */ @Override protected void createMenus(IMenuManager mgr) { final Action openMergeEditorAction = new Action("Open in Merge Editor") { @Override public void run() { FlaggedAdaptable selection = table.getSelection(); if (selection != null) { openMergeEditor(selection); } } }; final Action openEditorAction = new Action("Open in Default Editor") { @Override public void run() { IFile file = getSelection(); if(file == null){ return; } ResourceUtils.openEditor(getSite().getPage(), file); } }; final Action actionShowHistory = new Action("Show History") { @Override public void run() { IFile file = getSelection(); if(file == null){ return; } TeamUI.getHistoryView().showHistoryFor(file); } }; actionShowHistory.setImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("history.gif")); // Contribute actions to popup menu final MenuManager menuMgr = new MenuManager(); Menu menu = menuMgr.createContextMenu(table); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager menuMgr1) { menuMgr1.add(openMergeEditorAction); menuMgr1.add(openEditorAction); menuMgr1.add(new Separator()); menuMgr1.add(actionShowHistory); menuMgr1.add(new Separator()); menuMgr1.add(markResolvedAction); menuMgr1.add(markUnresolvedAction); menuMgr1.add(new Separator()); menuMgr1.add(completeAction); menuMgr1.add(abortAction); } }); menuMgr.setRemoveAllWhenShown(true); table.getTableViewer().getControl().setMenu(menu); } private void populateView(boolean attemptToCommit) throws HgException { boolean bAllResolved = true; List status = null; status = HgResolveClient.list(hgRoot); table.setItems(status); for (FlaggedAdaptable flagged : status) { if (flagged.getFlag() == MercurialStatusCache.CHAR_UNRESOLVED) { bAllResolved = false; } } completeAction.setEnabled(bAllResolved); /* TODO: remove this block? Commit button enablement provides sufficient feedback if (bAllResolved) { String label; if (merging) { label = Messages.getString("MergeView.PleaseCommitMerge"); } else { label = Messages.getString("MergeView.PleaseCommitRebase"); } showInfo(label); } else { hideStatus(); }*/ // Show commit dialog if (attemptToCommit && MercurialUtilities.isOfferAutoCommitMerge() && areAllResolved()) { /* * Offer commit of merge or rebase exactly once if no conflicts are found. Uses {@link * ResourceProperties#MERGE_COMMIT_OFFERED} to avoid showing the user the commit dialog * repeatedly. This flag should be cleared when any of the following operations occur: * commit, rebase, revert. */ attemptToCommit(); } } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#onRootChanged() */ @Override protected void onRootChanged() { if (hgRoot == null || !MercurialStatusCache.getInstance().isMergeInProgress(hgRoot)) { table.setItems(null); abortAction.setEnabled(false); completeAction.setEnabled(false); markResolvedAction.setEnabled(false); markUnresolvedAction.setEnabled(false); table.setEnabled(false); return; } abortAction.setEnabled(true); completeAction.setEnabled(true); markResolvedAction.setEnabled(true); markUnresolvedAction.setEnabled(true); table.setEnabled(true); try { merging = !HgRebaseClient.isRebasing(hgRoot); if (merging) { abortAction.setText(Messages.getString("MergeView.merge.abort")); completeAction.setText(Messages.getString("MergeView.merge.complete")); } else { abortAction.setText(Messages.getString("MergeView.rebase.abort")); completeAction.setText(Messages.getString("MergeView.rebase.complete")); } getViewSite().getActionBars().getToolBarManager().update(true); populateView(false); } catch (HgException e) { handleError(e); } } private void attemptToCommit() { try { MercurialUtilities.setOfferAutoCommitMerge(false); RunnableHandler handler = merging ? new CommitMergeHandler() : new ContinueRebaseHandler(); handler.setShell(getSite().getShell()); handler.run(hgRoot); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#getDescription() */ @Override protected String getDescription() { if (hgRoot == null || !MercurialStatusCache.getInstance().isMergeInProgress(hgRoot)) { return "No merge in progress. Select a merging or rebasing repository"; } if (merging) { String mergeNodeId = MercurialStatusCache.getInstance().getMergeChangesetId(hgRoot); if (mergeNodeId != null) { return hgRoot.getName() + ": Merging with " + mergeNodeId; } return hgRoot.getName() + ": Merging"; } return hgRoot.getName() + ": Rebasing"; } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#canChangeRoot(com.vectrace.MercurialEclipse.model.HgRoot, boolean) */ @Override protected boolean canChangeRoot(HgRoot newRoot, boolean fromSelection) { boolean ok = super.canChangeRoot(newRoot, fromSelection); if (fromSelection) { ok &= MercurialStatusCache.getInstance().isMergeInProgress(newRoot); } return ok; } private boolean areAllResolved() { boolean allResolved = true; for (FlaggedAdaptable fa : table.getItems()) { allResolved &= fa.getFlag() == MercurialStatusCache.CHAR_RESOLVED; } return allResolved; } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (selection instanceof IStructuredSelection && !selection.isEmpty()) { IStructuredSelection structured = (IStructuredSelection) selection; IResource resource = MercurialEclipsePlugin.getAdapter(structured.getFirstElement(), IResource.class); if (resource != null) { rootSelected(MercurialTeamProvider.hasHgRoot(resource)); } } } @Override public void setFocus() { table.setFocus(); } @Override public void dispose() { super.dispose(); MercurialStatusCache.getInstance().deleteObserver(this); } private IFile getSelection() { return getFile(table.getSelection()); } private List getSelections() { List selections = table.getSelections(); if (selections != null) { List result = new ArrayList(); for (FlaggedAdaptable flaggedAdaptable : selections) { IFile file = getFile(flaggedAdaptable); if (file != null) { result.add(file); } } return result; } return null; } private static IFile getFile(FlaggedAdaptable adaptable) { if (adaptable != null) { return (IFile) adaptable.getAdapter(IFile.class); } return null; } public void update(Observable o, Object arg) { if(hgRoot == null || !(arg instanceof Set)){ return; } Set set = (Set) arg; Set projects = ResourceUtils.getProjects(hgRoot); // create intersection of the root projects with the updated set projects.retainAll(set); // if the intersection contains common projects, we need update the view if(!projects.isEmpty()) { Display.getDefault().asyncExec(new Runnable() { public void run() { refresh(hgRoot); } }); } } private static void openMergeEditor(FlaggedAdaptable flagged) { IFile file = (IFile) flagged.getAdapter(IFile.class); CompareAction compareAction = new CompareAction(file); compareAction.setEnableMerge(true); compareAction.run(null); } /** * Must be called from the UI thread */ public static void showMergeConflict(HgRoot hgRoot, Shell shell) throws PartInitException { MergeView view = (MergeView) MercurialEclipsePlugin.getActivePage().showView(MergeView.ID); view.refresh(hgRoot); MercurialEclipsePlugin.showDontShowAgainConfirmDialog("A merge conflict occurred", "A merge conflict occurred. Use the merge view to resolve and commit the merge", MessageDialog.INFORMATION, MercurialPreferenceConstants.PREF_SHOW_MERGE_CONFICT_NOTIFICATION_DIALOG, shell); } /** * Must be called from the UI thread */ public static void showRebaseConflict(HgRoot hgRoot, Shell shell) throws PartInitException { MergeView view = (MergeView) MercurialEclipsePlugin.getActivePage().showView(MergeView.ID); view.refresh(hgRoot); MercurialEclipsePlugin .showDontShowAgainConfirmDialog( "A rebase conflict occurred", "A rebase conflict occurred. Use the merge view to resolve and complete the rebase", MessageDialog.INFORMATION, MercurialPreferenceConstants.PREF_SHOW_REBASE_CONFICT_NOTIFICATION_DIALOG, shell); } private static class MergeTable extends AbstractHighlightableTable { public MergeTable(Composite parent) { super(parent, new MergeTableLabelProvider()); } /** * @see com.vectrace.MercurialEclipse.ui.AbstractHighlightableTable#createColumns(org.eclipse.jface.viewers.TableViewer, org.eclipse.jface.layout.TableColumnLayout) */ @Override protected List createColumns(TableViewer viewer, TableColumnLayout tableColumnLayout) { List l = new ArrayList(2); String[] titles = { Messages.getString("MergeView.column.status"), Messages.getString("MergeView.column.file") }; //$NON-NLS-1$ //$NON-NLS-2$ ColumnLayoutData[] widths = { new ColumnPixelData(100, false, true), new ColumnWeightData(100, 200, true) }; for (int i = 0; i < titles.length; i++) { TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE); column.getColumn().setText(titles[i]); tableColumnLayout.setColumnData(column.getColumn(), widths[i]); l.add(column); } return l; } } private static class MergeTableLabelProvider extends HighlightingLabelProvider { /** * @see com.vectrace.MercurialEclipse.ui.AbstractHighlightableTable.HighlightingLabelProvider#isHighlighted(java.lang.Object) */ @Override public boolean isHighlighted(FlaggedAdaptable flagged) { return flagged.getFlag() == MercurialStatusCache.CHAR_UNRESOLVED; } /** * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java.lang.Object, int) */ public Image getColumnImage(Object element, int columnIndex) { return null; } /** * @see org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.lang.Object, int) */ public String getColumnText(Object element, int columnIndex) { FlaggedAdaptable flagged = (FlaggedAdaptable) element; switch (columnIndex) { case 0: return flagged.getStatus(); case 1: // TODO: this is wrong when hgroot not at project root return ((IFile) flagged.getAdapter(IFile.class)).getProjectRelativePath() .toString(); } throw new IllegalStateException(); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/Messages.java000066400000000000000000000021231173713500500321350ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.views; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.views.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/PatchQueueView.java000066400000000000000000000443471173713500500333030ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes * Philip Graf - bug fix, popup menu *******************************************************************************/ package com.vectrace.MercurialEclipse.views; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PartInitException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQFinishClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQFoldClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQPopClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQPushClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQSeriesClient; import com.vectrace.MercurialEclipse.dialogs.RejectsDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.QDeleteHandler; import com.vectrace.MercurialEclipse.menu.QImportHandler; import com.vectrace.MercurialEclipse.menu.QNewHandler; import com.vectrace.MercurialEclipse.menu.QRefreshHandler; import com.vectrace.MercurialEclipse.menu.StripHandler; import com.vectrace.MercurialEclipse.model.Patch; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.ui.PatchTable; import com.vectrace.MercurialEclipse.ui.TableSortListener; /** * @author bastian * */ public class PatchQueueView extends AbstractRootView { public static final String ID = PatchQueueView.class.getName(); private PatchTable table; private Action qNewAction; private Action qRefreshAction; private Action qPushAllAction; private Action qPopAllAction; private Action qDeleteAction; private Action qFinishAction; private Action qFoldAction; private Action qImportAction; private Action qGotoAction; private Action stripAction; private Patch topmostAppliedPatch; /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#createTable(org.eclipse.swt.widgets.Composite) */ @Override protected void createTable(Composite parent) { table = new PatchTable(parent); getSite().setSelectionProvider(table.getTableViewer()); } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#createToolBar(org.eclipse.jface.action.IToolBarManager) */ @Override protected void createToolBar(IToolBarManager mgr) { mgr.add(makeActionContribution(qImportAction)); mgr.add(makeActionContribution(qNewAction)); mgr.add(makeActionContribution(qRefreshAction)); mgr.add(makeActionContribution(qFinishAction)); mgr.add(makeActionContribution(qFoldAction)); mgr.add(makeActionContribution(qDeleteAction)); mgr.add(makeActionContribution(stripAction)); } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#createActions() */ @Override protected void createActions() { qImportAction = new Action("qimport...", MercurialEclipsePlugin.getImageDescriptor("import.gif")) { //$NON-NLS-1$ @Override public void run() { try { QImportHandler.openWizard(hgRoot, getSite().getShell()); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } } }; qImportAction.setEnabled(false); qNewAction = new Action("qnew...", MercurialEclipsePlugin.getImageDescriptor("import.gif")) { //$NON-NLS-1$ @Override public void run() { try { QNewHandler.openWizard(hgRoot, getSite().getShell()); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } } }; qNewAction.setEnabled(false); qRefreshAction = new Action("qrefresh...", MercurialEclipsePlugin.getImageDescriptor("actions/qrefresh.gif")) { //$NON-NLS-1$ @Override public void run() { QRefreshHandler.openWizard(hgRoot, getSite().getShell()); } }; qRefreshAction.setEnabled(false); qGotoAction = new MQPatchAction(Messages.getString("PatchQueueView.switchTo"), RefreshRootJob.LOCAL_AND_OUTGOING, "QPushRejectsDialog.conflict", true) { @Override public boolean doInvoke() throws HgException { // Switch to the first selected patch. There is only one patch selected because // the action is disabled if zero or more than one patches are selected. Patch patch = table.getSelection(); if (patch != null) { if (patch.isApplied()) { HgQPopClient.pop(hgRoot, false, patch.getName()); } else { HgQPushClient.push(hgRoot, false, patch.getName()); } return true; } return false; } }; qGotoAction.setImageDescriptor(MercurialEclipsePlugin .getImageDescriptor("actions/switch.gif")); qGotoAction.setEnabled(false); qPushAllAction = new MQPatchAction(Messages.getString("PatchQueueView.applyAll"), RefreshRootJob.LOCAL_AND_OUTGOING, "QPushRejectsDialog.conflict", true) { @Override public boolean doInvoke() throws HgException { HgQPushClient.pushAll(hgRoot, false); return true; } }; qPushAllAction.setEnabled(true); qPopAllAction = new MQAction(Messages.getString("PatchQueueView.unapplyAll"), RefreshRootJob.LOCAL_AND_OUTGOING) { @Override public boolean invoke() throws HgException { HgQPopClient.popAll(hgRoot, false); return true; } }; qPopAllAction.setEnabled(false); qFoldAction = new MQPatchAction("qfold", RefreshRootJob.LOCAL_AND_OUTGOING, "QFoldRejectsDialog.conflict", false) { @Override public boolean doInvoke() throws HgException { List patches = new ArrayList(table.getSelections()); if (patches.size() > 0) { Collections.sort(patches, new Comparator() { public int compare(Patch o1, Patch o2) { return TableSortListener.sort(o1.getIndex(), o2.getIndex()); } }); HgQFoldClient.fold(hgRoot, true, null, patches); return true; } return false; } @Override protected boolean isPatchConflict(HgException e) { return HgQFoldClient.isPatchConflict(e); } }; qFoldAction.setEnabled(false); stripAction = new Action("strip...", MercurialEclipsePlugin.getImageDescriptor("actions/revert.gif")) { //$NON-NLS-1$ @Override public void run() { try { // TODO: set initial selection to selected applied patch StripHandler.openWizard(hgRoot, getSite().getShell(), null); } catch (Exception e) { MercurialEclipsePlugin.logError(e); } } }; stripAction.setEnabled(false); qDeleteAction = new Action("qdelete...", MercurialEclipsePlugin.getImageDescriptor("rem_co.gif")) { //$NON-NLS-1$ @Override public void run() { QDeleteHandler.openWizard(hgRoot, getSite().getShell(), false); } }; qDeleteAction.setEnabled(false); qFinishAction = new MQAction("qfinish", MercurialEclipsePlugin.getImageDescriptor("actions/qrefresh.gif"), RefreshRootJob.OUTGOING) { //$NON-NLS-1$ @Override public boolean invoke() throws HgException { List patches = table.getSelections(); Patch max = null; boolean unappliedSelected = false; for (Patch p : patches) { if (p.isApplied()) { if (max == null || p.getIndex() > max.getIndex()) { max = p; } } else { unappliedSelected = true; } } List toApply = new ArrayList(table.getItems()); for (Iterator it = toApply.iterator(); it.hasNext();) { Patch cur = it.next(); if (!cur.isApplied()) { it.remove(); } else if (max != null && cur.getIndex() > max.getIndex()) { it.remove(); } } if (toApply.size() == 0) { MessageDialog.openInformation(getSite().getShell(), "No applied patches", "Only applied patches can be promoted."); } else if (max == null) { if (unappliedSelected) { MessageDialog .openInformation(getSite().getShell(), "Only applied patches can be promoted", "Only applied patches can be promoted. Select an applied patch to promote."); } else if (MercurialEclipsePlugin.showDontShowAgainConfirmDialog( "Promote all applied patches?", "No patches selected, promote all " + toApply.size() + " applied patches?", MessageDialog.CONFIRM, MercurialPreferenceConstants.PREF_SHOW_QFINISH_WARNING_DIALOG, getSite() .getShell())) { HgQFinishClient.finish(hgRoot, toApply); return true; } } else if (toApply.size() == 1 || MercurialEclipsePlugin.showDontShowAgainConfirmDialog( "QFinish multiple patches", "Promote " + toApply.size() + " patches?", MessageDialog.CONFIRM, MercurialPreferenceConstants.PREF_SHOW_QFINISH_WARNING_DIALOG, getSite() .getShell())) { HgQFinishClient.finish(hgRoot, toApply); return true; } return false; } }; qFinishAction.setEnabled(false); table.getTableViewer().addPostSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { updateEnablement((IStructuredSelection) event.getSelection()); } }); } @SuppressWarnings("unchecked") protected void updateEnablement(IStructuredSelection selection) { assert hgRoot != null; boolean isTopSelected = false; boolean selectionHasApplied = false; for (Iterator i = selection.iterator(); i.hasNext();) { Patch p = i.next(); if (p.equals(topmostAppliedPatch)) { isTopSelected = true; } selectionHasApplied |= p.isApplied(); } boolean isAllApplied = true; boolean isAllUnapplied = true; for (Patch patch : (List) table.getTableViewer().getInput()) { if (patch.isApplied()) { isAllUnapplied = false; } else { isAllApplied = false; } } qNewAction.setEnabled(true); qRefreshAction.setEnabled(true); qImportAction.setEnabled(true); qDeleteAction.setEnabled(true); qGotoAction.setEnabled(selection.size() == 1 && !isTopSelected); qPushAllAction.setEnabled(!isAllApplied); qPopAllAction.setEnabled(!isAllUnapplied); qFoldAction.setEnabled(!selectionHasApplied && !selection.isEmpty()); qFinishAction.setEnabled(selectionHasApplied || selection.isEmpty()); stripAction.setEnabled(true); } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#createMenus(org.eclipse.jface.action.IMenuManager) */ @Override protected void createMenus(IMenuManager menuMgr) { menuMgr.add(qImportAction); menuMgr.add(qNewAction); menuMgr.add(qRefreshAction); menuMgr.add(qFinishAction); menuMgr.add(qFoldAction); menuMgr.add(qDeleteAction); menuMgr.add(stripAction); MenuManager popupMenuMgr = new MenuManager(); popupMenuMgr.add(qGotoAction); popupMenuMgr.add(qPushAllAction); popupMenuMgr.add(qPopAllAction); popupMenuMgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); getSite().registerContextMenu(popupMenuMgr, table.getTableViewer()); Control control = table.getTableViewer().getControl(); control.setMenu(popupMenuMgr.createContextMenu(control)); } @Override public void setFocus() { populateTable(); } public void populateTable() { Job job = new SafeUiJob(Messages.getString("PatchQueueView.jobName.populateTable")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor monitor) { IStatus status = Status.OK_STATUS; if (hgRoot != null && !table.isDisposed()) { try { List patches = HgQSeriesClient.getPatchesInSeries(hgRoot); // TODO: We have to hide the popup menu if the table is empty or the team // menu will be appended. This is a side effect of the team menu's // locationURI being "popup:org.eclipse.ui.popup.any". If the team menu gets // a proper locationURI, the next line can be deleted. table.setEnabled(!patches.isEmpty()); topmostAppliedPatch = null; for (Patch patch : patches) { if (patch.isApplied()) { topmostAppliedPatch = patch; } } // Reverse so it's in the same order as the sync view patches = new ArrayList(patches); Collections.reverse(patches); table.setItems(patches); } catch (HgException e) { if (e.getCause() instanceof InterruptedException) { // ? } else { showWarning(e.getConciseMessage()); MercurialEclipsePlugin.logError(e); status = new Status(IStatus.ERROR, MercurialEclipsePlugin.ID, Messages.getString("PatchQueueView.cannotPopulatePatchViewTable"), e); //$NON-NLS-1$ } } finally { updateEnablement(StructuredSelection.EMPTY); } } return status; } }; job.setUser(false); job.setSystem(true); job.schedule(); } /** * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ public final void selectionChanged(IWorkbenchPart part, ISelection selection) { if (selection instanceof IStructuredSelection) { IStructuredSelection structured = (IStructuredSelection) selection; if (structured.getFirstElement() instanceof IAdaptable) { IResource newResource = (IResource) ((IAdaptable) structured.getFirstElement()) .getAdapter(IResource.class); if (newResource != null && newResource.isAccessible() && MercurialTeamProvider.isHgTeamProviderFor(newResource)) { rootSelected(MercurialTeamProvider.getHgRoot(newResource)); } } } // TODO: why? if (part instanceof IEditorPart) { IEditorInput input = ((IEditorPart) part).getEditorInput(); IFile file = (IFile) input.getAdapter(IFile.class); if (file != null && file.isAccessible() && MercurialTeamProvider.isHgTeamProviderFor(file)) { rootSelected(MercurialTeamProvider.getHgRoot(file)); } } } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#onRootChanged() */ @Override protected void onRootChanged() { populateTable(); } public static PatchQueueView getView() { PatchQueueView view = (PatchQueueView) MercurialEclipsePlugin.getActivePage().findView(ID); if (view == null) { try { view = (PatchQueueView) MercurialEclipsePlugin.getActivePage().showView(ID); } catch (PartInitException e) { MercurialEclipsePlugin.logError(e); } } return view; } /** * @see com.vectrace.MercurialEclipse.views.AbstractRootView#getDescription() */ @Override protected String getDescription() { if (hgRoot == null) { return "No repository selected"; } return Messages.getString("PatchQueueView.repository") + hgRoot; } private abstract class MQAction extends Action { protected final int refreshFlag; public MQAction(String name, int refreshFlag) { super(name); this.refreshFlag = refreshFlag; } public MQAction(String name, ImageDescriptor desc, int refreshFlag) { super(name, desc); this.refreshFlag = refreshFlag; } /** * @see org.eclipse.jface.action.Action#run() */ @Override public final void run() { boolean changed = true; try { changed = invoke(); } catch (HgException e) { MercurialEclipsePlugin.logError(e); showWarning(e.getConciseMessage()); if (e.isMultiLine()) { MercurialEclipsePlugin.showError(e); } } catch (CoreException e) { MercurialEclipsePlugin.logError(e); showWarning(e.getLocalizedMessage()); MercurialEclipsePlugin.showError(e); } finally { if (changed) { populateTable(); new RefreshWorkspaceStatusJob(hgRoot, refreshFlag).schedule(); } } } public abstract boolean invoke() throws HgException, CoreException; } private abstract class MQPatchAction extends MQAction { private final String message; private final boolean requireSource; public MQPatchAction(String name, int refreshFlag, String message, boolean requireSource) { super(name, refreshFlag); this.message = message; this.requireSource = requireSource; } @Override public final boolean invoke() throws HgException, CoreException { try { return doInvoke(); } catch (HgException e) { if (isPatchConflict(e)) { try { populateTable(); Job job = new RefreshWorkspaceStatusJob(hgRoot, refreshFlag); job.schedule(); job.join(); new RejectsDialog(getSite().getShell(), hgRoot, e.getMessage(), "QRejectsDialog.title", message, requireSource).open(); return false; // already refreshed and populated the table } catch (HgException e2) { MercurialEclipsePlugin.logError(e2); } catch (InterruptedException e1) { MercurialEclipsePlugin.logError(e1); } } throw e; } } protected boolean isPatchConflict(HgException e) { return HgQPushClient.isPatchApplyConflict(e); } public abstract boolean doInvoke() throws HgException, CoreException; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/console/000077500000000000000000000000001173713500500311675ustar00rootroot00000000000000ConsoleDocument.java000066400000000000000000000046151173713500500350620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/console/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.views.console; /** * Simple circular buffer that stores a fix number of lines. */ public class ConsoleDocument { public static final int COMMAND = 0; // command text public static final int MESSAGE = 1; // message received public static final int ERROR = 2; // error received public static final int STATUS = 3; // status text public static final int DELIMITER = 4; // delimiter text between runs private int[] lineTypes; private String[] lines; private int writeIndex; private int readIndex; private static final int BUFFER_SIZE = 200; protected static class ConsoleLine { public String line; public int type; ConsoleLine(String line, int type) { this.line = line; this.type = type; } } /** * Creates an empty console document. */ public ConsoleDocument() { } /** * Clears the console document. */ public void clear() { lineTypes = null; lines = null; writeIndex = 0; readIndex = 0; } /** * Appends a line of the specified type to the end of the console. */ public void appendConsoleLine(int type, String line) { if(lines == null) { lines = new String[BUFFER_SIZE]; lineTypes = new int[BUFFER_SIZE]; } lines[writeIndex] = line; lineTypes[writeIndex] = type; if(++writeIndex >= BUFFER_SIZE) { writeIndex = 0; } if(writeIndex == readIndex) { if(++readIndex >= BUFFER_SIZE) { readIndex = 0; } } } public ConsoleLine[] getLines() { if(isEmpty()) { return new ConsoleLine[0]; } ConsoleLine[] docLines = new ConsoleLine[readIndex > writeIndex ? BUFFER_SIZE : writeIndex]; int index = readIndex; for (int i = 0; i < docLines.length; i++) { docLines[i] = new ConsoleLine(lines[index], lineTypes[index]); if (++index >= BUFFER_SIZE) { index = 0; } } return docLines; } public boolean isEmpty() { return writeIndex == readIndex; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/console/HgConsole.java000066400000000000000000000266511173713500500337250ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2003, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.views.console; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.*; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.resource.FontRegistry; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.console.MessageConsole; import org.eclipse.ui.console.MessageConsoleStream; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * Console that shows the output of Hg commands. It is shown as a page in the * generic console view. It supports coloring for message, command, and error * lines in addition the font can be configured. * */ public class HgConsole extends MessageConsole { /** * Used in plugin.xml */ private static final String HG_CONSOLE_TYPE = "hgConsole"; /** created colors for each line type - must be disposed at shutdown*/ private Color commandColor; private Color messageColor; private Color errorColor; /** streams for each command type - each stream has its own color */ private MessageConsoleStream commandStream; private MessageConsoleStream messageStream; private MessageConsoleStream errorStream; private final ConsoleDocument document; /** Indicates whether the console is visible in the Console view */ private boolean visible; /** Indicates whether the console's streams have been initialized */ private boolean initialized; private boolean debugTimeEnabled; private boolean debugEnabled; /** * Constant used for indenting error status printing */ private static final String NESTING = " "; //$NON-NLS-1$ /** * Constructor initializes preferences and colors but doesn't create the * console page yet. */ public HgConsole() { super("Mercurial Console", HG_CONSOLE_TYPE, MercurialEclipsePlugin.getImageDescriptor("mercurialeclipse.png"), true); //$NON-NLS-1$ //$NON-NLS-2$ document = new ConsoleDocument(); IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); debugTimeEnabled = store.getBoolean(PREF_CONSOLE_DEBUG_TIME); debugEnabled = store.getBoolean(PREF_CONSOLE_DEBUG); } @Override protected void init() { // Called when console is added to the console view super.init(); IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); initLimitOutput(store); initWrapSetting(store); initializeStreams(); dump(); } private void initWrapSetting(IPreferenceStore store) { if (store.getBoolean(PREF_CONSOLE_WRAP)) { setConsoleWidth(store.getInt(PREF_CONSOLE_WIDTH)); } else { setConsoleWidth(-1); } } private void initLimitOutput(IPreferenceStore store) { if (store.getBoolean(PREF_CONSOLE_LIMIT_OUTPUT)) { int highWaterMark = store.getInt(PREF_CONSOLE_HIGH_WATER_MARK); if (highWaterMark < 1000) { highWaterMark = 1000; } setWaterMarks(0, highWaterMark); } else { setWaterMarks(0, 1000); } } /** * Initialize thre streams of the console. Must be called from the UI * thread. */ private void initializeStreams() { synchronized (document) { if (initialized) { return; } commandStream = newMessageStream(); errorStream = newMessageStream(); messageStream = newMessageStream(); IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); // install colors commandColor = createColor(store, PREF_CONSOLE_COMMAND_COLOR); commandStream.setColor(commandColor); messageColor = createColor(store, PREF_CONSOLE_MESSAGE_COLOR); messageStream.setColor(messageColor); errorColor = createColor(store, PREF_CONSOLE_ERROR_COLOR); errorStream.setColor(errorColor); initialized = true; } } private void dump() { synchronized (document) { visible = true; ConsoleDocument.ConsoleLine[] lines = document.getLines(); for (int i = 0; i < lines.length; i++) { ConsoleDocument.ConsoleLine line = lines[i]; appendLine(line.type, line.line); } document.clear(); } } private void appendLine(int type, String line) { HgConsoleHolder.getInstance().showConsole(false); String myLine = line == null? "" : line; synchronized (document) { if (visible) { switch (type) { case ConsoleDocument.COMMAND: commandStream.println(myLine); break; case ConsoleDocument.MESSAGE: messageStream.println(myLine); break; case ConsoleDocument.ERROR: errorStream.println(myLine); break; } } else { document.appendConsoleLine(type, myLine); } } } @Override protected void dispose() { // Here we can't call super.dispose() because we actually want the // partitioner to remain // connected, but we won't show lines until the console is added to the // console manager // again. // Called when console is removed from the console view synchronized (document) { visible = false; } } /** * Clean-up created fonts. */ public void shutdown() { // Call super dispose because we want the partitioner to be // disconnected. super.dispose(); if (commandColor != null) { commandColor.dispose(); } if (messageColor != null) { messageColor.dispose(); } if (errorColor != null) { errorColor.dispose(); } } public void commandInvoked(String line) { appendLine(ConsoleDocument.COMMAND, line); } public void messageLineReceived(String line) { appendLine(ConsoleDocument.MESSAGE, line); } public void errorLineReceived(String line) { appendLine(ConsoleDocument.ERROR, line); } private boolean isDebugTimeEnabled() { return debugTimeEnabled; } public void commandCompleted(long timeInMillis, IStatus status, Throwable exception) { String time = getTimeString(timeInMillis); if (status != null) { if(status.getSeverity() == IStatus.ERROR) { printStatus(status, time, false); } else if(debugEnabled){ printStatus(status, time, true); } else if(isDebugTimeEnabled()){ appendLine(ConsoleDocument.MESSAGE, time); } } else if (exception != null) { String statusText; if (exception instanceof OperationCanceledException) { statusText = Messages.getString("HgConsole.aborted1") + time + Messages.getString("HgConsole.aborted2"); //$NON-NLS-1$ //$NON-NLS-2$ } else { statusText = time; } appendLine(ConsoleDocument.COMMAND, statusText); if (exception instanceof CoreException) { outputStatus(((CoreException) exception).getStatus(), true, 1); } } else if(isDebugTimeEnabled()){ appendLine(ConsoleDocument.MESSAGE, time); } } private void printStatus(IStatus status, String time, boolean includeRoot) { String statusText = status.getMessage(); if(time.length() > 0){ statusText += "(" + time + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } int kind = status.getSeverity() == IStatus.ERROR? ConsoleDocument.ERROR : ConsoleDocument.MESSAGE; appendLine(kind, statusText); outputStatus(status, includeRoot, includeRoot ? 0 : 1); } /** * * @param timeInMillis * @return empty string if time measurement was not enabled or we are failed to measure it */ private String getTimeString(long timeInMillis) { if(!isDebugTimeEnabled()){ return ""; } String time; try { time = String.format(" Done in %1$tM:%1$tS:%1$tL", Long.valueOf(timeInMillis)); } catch (RuntimeException e) { MercurialEclipsePlugin.logError(e); time = ""; } return time; } private void outputStatus(IStatus status, boolean includeParent, int nestingLevel) { int myNestingLevel = nestingLevel; if (includeParent && !status.isOK()) { outputStatusMessage(status, nestingLevel); myNestingLevel++; } // Include a CoreException in the status Throwable t = status.getException(); if (t instanceof CoreException) { outputStatus(((CoreException) t).getStatus(), true, myNestingLevel); } // Include child status IStatus[] children = status.getChildren(); for (int i = 0; i < children.length; i++) { outputStatus(children[i], true, myNestingLevel); } } private void outputStatusMessage(IStatus status, int nesting) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < nesting; i++) { buffer.append(NESTING); } buffer.append(messageLineForStatus(status)); appendLine(ConsoleDocument.COMMAND, buffer.toString()); } public void propertyChange(PropertyChangeEvent event) { String property = event.getProperty(); if(property == null || !property.startsWith("hg.console.")){ return; } // colors IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); if (visible) { if (property.equals(PREF_CONSOLE_COMMAND_COLOR)) { Color newColor = createColor(store, PREF_CONSOLE_COMMAND_COLOR); commandStream.setColor(newColor); commandColor.dispose(); commandColor = newColor; } else if (property.equals(PREF_CONSOLE_MESSAGE_COLOR)) { Color newColor = createColor(store, PREF_CONSOLE_MESSAGE_COLOR); messageStream.setColor(newColor); messageColor.dispose(); messageColor = newColor; } else if (property.equals(PREF_CONSOLE_ERROR_COLOR)) { Color newColor = createColor(store, PREF_CONSOLE_ERROR_COLOR); errorStream.setColor(newColor); errorColor.dispose(); errorColor = newColor; // font } else if (property.equals(PREF_CONSOLE_FONT)) { setFont(((FontRegistry) event.getSource()).get(PREF_CONSOLE_FONT)); } } if (property.equals(PREF_CONSOLE_LIMIT_OUTPUT)) { initLimitOutput(store); } else if (property.equals(PREF_CONSOLE_WRAP)) { initWrapSetting(store); } else if (property.equals(PREF_CONSOLE_DEBUG_TIME)) { debugTimeEnabled = store.getBoolean(PREF_CONSOLE_DEBUG_TIME); } else if (property.equals(PREF_CONSOLE_DEBUG)) { debugEnabled = store.getBoolean(PREF_CONSOLE_DEBUG); } } /** * Returns the NLSd message based on the status returned from the Hg * command. * * @param status * an NLSd message based on the status returned from the Hg * command. */ private String messageLineForStatus(IStatus status) { if (status.getSeverity() == IStatus.ERROR) { return Messages.getString("HgConsole.error") + status.getMessage(); //$NON-NLS-1$ } else if (status.getSeverity() == IStatus.WARNING) { return Messages.getString("HgConsole.warning") + status.getMessage(); //$NON-NLS-1$ } else if (status.getSeverity() == IStatus.INFO) { return Messages.getString("HgConsole.info") + status.getMessage(); //$NON-NLS-1$ } return status.getMessage(); } /** * Returns a color instance based on data from a preference field. */ private Color createColor(IPreferenceStore store, String preference) { Display display = MercurialEclipsePlugin.getStandardDisplay(); RGB rgb = PreferenceConverter.getColor(store, preference); return new Color(display, rgb); } } HgConsoleFactory.java000066400000000000000000000023341173713500500351660ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/console/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.views.console; import org.eclipse.ui.console.IConsoleFactory; /** * Console factory is used to show the console from the Console view * "Open Console" drop-down action. This factory is registered via the * org.eclipse.ui.console.consoleFactory extension point. * * @since 3.1 */ /* * Eclipse creates an instance of this class before calling openConsole so we must make it * stateless even though we want to have at most a single console. */ public class HgConsoleFactory implements IConsoleFactory { public HgConsoleFactory() { } public void openConsole() { HgConsoleHolder.getInstance().showConsole(true); } } HgConsoleHolder.java000066400000000000000000000127331173713500500350000ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/console/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * ijuma - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.views.console; import static com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants.PREF_CONSOLE_SHOW_ON_MESSAGE; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IConsoleListener; import org.eclipse.ui.console.IConsoleManager; import org.eclipse.ui.themes.ITheme; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * This class should only be called from the UI thread as it is not thread-safe. */ public final class HgConsoleHolder implements IConsoleListener, IPropertyChangeListener { private static final String CONSOLE_FONT = "com.vectrace.mercurialeclipse.ui.colorsandfonts.ConsoleFont"; //$NON-NLS-1$ private static final HgConsoleHolder INSTANCE = new HgConsoleHolder(); private volatile HgConsole console; private boolean showOnMessage; private boolean registered; private HgConsoleHolder() { } public static HgConsoleHolder getInstance() { return INSTANCE; } private void init() { if (isInitialized()) { return; } synchronized(this){ if (isInitialized()) { return; } console = new HgConsole(); IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); store.addPropertyChangeListener(this); getConsoleManager().addConsoleListener(this); showOnMessage = store.getBoolean(PREF_CONSOLE_SHOW_ON_MESSAGE); // install font // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=298795 // we must run this stupid code in the UI thread if (Display.getCurrent() != null) { initUIResources(); } else { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { initUIResources(); } }); } } } private void initUIResources() { ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); theme.addPropertyChangeListener(this); JFaceResources.getFontRegistry().addListener(this); setConsoleFont(); } private boolean isInitialized() { return console != null; } public HgConsole showConsole(boolean force) { init(); if (force || showOnMessage) { // register console if(Display.getCurrent() == null){ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { registerConsole(); getConsoleManager().showConsoleView(console); } }); } else { registerConsole(); getConsoleManager().showConsoleView(console); } } return console; } private void registerConsole() { boolean exists = isConsoleRegistered(); if (!exists) { getConsoleManager().addConsoles(new IConsole[] { console }); } } private boolean isConsoleRegistered() { if(registered){ return true; } IConsole[] existing = getConsoleManager().getConsoles(); for (int i = 0; i < existing.length; i++) { if (console == existing[i]) { registered = true; } } return registered; } public HgConsole getConsole() { init(); return console; } public void consolesAdded(IConsole[] consoles) { // noop } public void consolesRemoved(IConsole[] consoles) { for (int i = 0; i < consoles.length; i++) { IConsole c = consoles[i]; if (c == console) { registered = false; console.dispose(); console = null; JFaceResources.getFontRegistry().removeListener(this); MercurialEclipsePlugin.getDefault().getPreferenceStore() .removePropertyChangeListener(this); ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); theme.removePropertyChangeListener(this); break; } } } public void propertyChange(PropertyChangeEvent event) { if(PREF_CONSOLE_SHOW_ON_MESSAGE.equals(event.getProperty())){ IPreferenceStore store = MercurialEclipsePlugin.getDefault().getPreferenceStore(); showOnMessage = store.getBoolean(PREF_CONSOLE_SHOW_ON_MESSAGE); } else if (CONSOLE_FONT.equals(event.getProperty())) { setConsoleFont(); } else { console.propertyChange(event); } } private IConsoleManager getConsoleManager() { return ConsolePlugin.getDefault().getConsoleManager(); } private void setConsoleFont() { if (Display.getCurrent() == null) { PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { public void run() { ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); Font font = theme.getFontRegistry().get(CONSOLE_FONT); console.setFont(font); } }); } else { ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme(); Font font = theme.getFontRegistry().get(CONSOLE_FONT); console.setFont(font); } } } HgConsolePageParticipant.java000066400000000000000000000033011173713500500366250ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/console/******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.views.console; import org.eclipse.ui.IActionBars; import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IConsoleConstants; import org.eclipse.ui.console.IConsolePageParticipant; import org.eclipse.ui.console.actions.CloseConsoleAction; import org.eclipse.ui.part.IPageBookViewPage; /** * Console helper that allows contributing actions to the console view when * the Mercurial console is visible. Added to the console via an extension point * from org.eclipse.ui.console. */ public class HgConsolePageParticipant implements IConsolePageParticipant { private CloseConsoleAction consoleRemoveAction; public void init(IPageBookViewPage page, IConsole console) { consoleRemoveAction = new CloseConsoleAction(console); IActionBars bars = page.getSite().getActionBars(); bars.getToolBarManager().appendToGroup(IConsoleConstants.LAUNCH_GROUP, consoleRemoveAction); } public void dispose() { this.consoleRemoveAction = null; } public void activated() { } public void deactivated() { } public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) { return null; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/console/Messages.java000066400000000000000000000021431173713500500336010ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.views.console; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.views.console.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } messages.properties000066400000000000000000000003601173713500500350340ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/consoleHgConsole.aborted1=Aborted ( HgConsole.aborted2=) HgConsole.error=Error: HgConsole.info=Info: HgConsole.minutes=\ min. HgConsole.unknown=UNKNOWN HgConsole.warning=Warning: HgConsoleFactory.initializingConsole=Initializing Mercurial Console eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/views/messages.properties000066400000000000000000000012721173713500500334540ustar00rootroot00000000000000MergeView.merge.abort=Abort MergeView.merge.complete=Commit MergeView.rebase.abort=Abort MergeView.rebase.complete=Continue MergeView.column.file=File MergeView.column.status=Status MergeView.markResolved=Mark Resolved MergeView.markUnresolved=Mark Unresolved MergeView.mergeFilesOf=Merged files of: MergeView.PleaseCommitMerge=Merge is ready to commit MergeView.PleaseCommitRebase=Rebase step is ready to commit PatchQueueView.repository=Repository: PatchQueueView.applyAll=Apply All PatchQueueView.cannotPopulatePatchViewTable=Cannot populate patch view table PatchQueueView.jobName.populateTable=Populate Patch View Table PatchQueueView.switchTo=Switch To PatchQueueView.unapplyAll=Unapply All eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/000077500000000000000000000000001173713500500300535ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/AddBranchPage.java000066400000000000000000000101501173713500500333160ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.HashSet; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgBranchClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author bastian * */ public class AddBranchPage extends HgWizardPage { private Button forceCheckBox; private Text branchNameTextField; private Button commitCheckBox; private final HgRoot hgRoot; private final Set branchNames; public AddBranchPage(HgRoot hgRoot, String pageName, String title, ImageDescriptor titleImage, String description) { super(pageName, title, titleImage, description); this.hgRoot = hgRoot; branchNames = new HashSet(); } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); SWTWidgetHelper.createLabel(composite, Messages.getString("AddBranchPage.branchNameTextField.title")); //$NON-NLS-1$ try { Branch[] branches = HgBranchClient.getBranches(hgRoot); for (Branch branch : branches) { branchNames.add(branch.getName()); } } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); } branchNameTextField = SWTWidgetHelper.createTextField(composite); branchNameTextField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { validateIfBranchExists(); } }); commitCheckBox = SWTWidgetHelper.createCheckBox(composite, Messages.getString("AddBranchPage.commitCheckBox.title")); //$NON-NLS-1$ commitCheckBox.setToolTipText(Messages.getString("AddBranchPage.commitCheckBox.tooltip")); commitCheckBox.setSelection(true); forceCheckBox = SWTWidgetHelper.createCheckBox(composite, Messages.getString("AddBranchPage.forceCheckBox.title")); //$NON-NLS-1$ forceCheckBox.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { validateIfBranchExists(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); setControl(composite); } @Override public boolean finish(IProgressMonitor monitor) { return super.finish(monitor); } public boolean isForceEnabled() { return forceCheckBox.getSelection(); } public boolean isCommitEnabled() { return commitCheckBox.getSelection(); } public String getBranchName() { return branchNameTextField.getText(); } /** * @return true if branch does not exists yet */ public boolean validateIfBranchExists() { String text = branchNameTextField.getText(); if(branchNames.contains(text)){ if(!forceCheckBox.getSelection()){ setMessage(null, IMessageProvider.WARNING); setErrorMessage("'" + text + "' branch already exists!"); } else { setErrorMessage(null); setMessage("'" + text + "' branch shadows existing branch.", IMessageProvider.WARNING); } return false; } setMessage(null, IMessageProvider.WARNING); setErrorMessage(null); return true; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/AddBranchWizard.java000066400000000000000000000121001173713500500336770ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableContext; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgBranchClient; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.dialogs.CommitDialog.Options; import com.vectrace.MercurialEclipse.menu.CommitHandler; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author bastian */ public class AddBranchWizard extends HgWizard { private final AddBranchPage branchPage; private final HgRoot hgRoot; private class AddBranchOperation extends HgOperation { public AddBranchOperation(IRunnableContext context) { super(context); } @Override protected String getActionDescription() { return Messages.getString("AddBranchWizard.AddBranchOperation.actionDescription"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { boolean commitEnabled = branchPage.isCommitEnabled(); int workSize = commitEnabled ? 3 : 2; monitor.beginTask(Messages.getString("AddBranchWizard.AddBranchOperation.taskName"), workSize); //$NON-NLS-1$ try { String[] dirtyFiles = HgStatusClient.getDirtyFiles(hgRoot); if(dirtyFiles.length > 0){ String message = "There are uncommitted changes in the repository.\n"; message += "If you continue and commit, the changes will go into the new branch!\n"; message += "Continue with creating the branch?\n"; boolean ok = MessageDialog.openConfirm(getShell(), "Add Branch", message); if(!ok){ throw new InterruptedException("Branch creation cancelled because of uncommitted changes!"); } } HgBranchClient.addBranch(hgRoot, branchPage.getBranchName(), HgCommitMessageManager .getDefaultCommitName(hgRoot), branchPage.isForceEnabled()); monitor.worked(1); HgClients.getConsole().printMessage(result, null); Set projects = ResourceUtils.getProjects(hgRoot); String branch = HgBranchClient.getActiveBranch(hgRoot); MercurialTeamProvider.setCurrentBranch(branch, hgRoot); if(commitEnabled){ List projectList = new ArrayList(projects); CommitHandler commitHandler = new CommitHandler(); Options options = new Options(); options.defaultCommitMessage = "Starting '" + branch + "' branch"; options.filesSelectable = false; options.showAmend = false; options.showCloseBranch = false; options.showRevert = false; options.allowEmptyCommit = true; commitHandler.setOptions(options); commitHandler.run(projectList); monitor.worked(1); } for (IProject project : projects) { project.touch(monitor); } monitor.worked(1); } catch (CoreException e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } monitor.done(); } } public AddBranchWizard(HgRoot hgRoot) { super(Messages.getString("AddBranchWizard.windowTitle")); //$NON-NLS-1$ this.hgRoot = hgRoot; setNeedsProgressMonitor(true); branchPage = new AddBranchPage(hgRoot, Messages.getString("AddBranchWizard.branchPage.name"), //$NON-NLS-1$ Messages.getString("AddBranchWizard.branchPage.title"), MercurialEclipsePlugin.getImageDescriptor("wizards/newstream_wizban.gif"), //$NON-NLS-1$ //$NON-NLS-2$ Messages.getString("AddBranchWizard.branchPage.description")); //$NON-NLS-1$ addPage(branchPage); } @Override public boolean performFinish() { branchPage.setErrorMessage(null); AddBranchOperation op = new AddBranchOperation(getContainer()); try { getContainer().run(false, false, op); } catch (Exception e) { branchPage.setErrorMessage(e.getLocalizedMessage()); return false; } return super.performFinish(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/BackoutWizard.java000066400000000000000000000041621173713500500334720ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - modifocations *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian */ public class BackoutWizard extends HgWizard { private HgRoot hgRoot; private ChangeSet selectedChangeSet; private BackoutWizard() { super(Messages.getString("BackoutWizard.title")); //$NON-NLS-1$ setNeedsProgressMonitor(true); } public BackoutWizard(HgRoot hgRoot) { this(); this.hgRoot = hgRoot; } /** * Constructor for wizard with preselected change set * @param hgRoot * @param selectedChangeSet */ public BackoutWizard(HgRoot hgRoot, ChangeSet selectedChangeSet) { this(); this.hgRoot = hgRoot; this.selectedChangeSet = selectedChangeSet; } @Override public void addPages() { super.addPages(); page = createPage( Messages.getString("BackoutWizard.pageName"), //$NON-NLS-1$ Messages.getString("BackoutWizard.pageTitle"), null, Messages.getString("BackoutWizard.pageDescription")); //$NON-NLS-1$ addPage(page); } /** * Creates a ConfigurationWizardPage. */ protected HgWizardPage createPage(String pageName, String pageTitle, String iconPath, String description) { this.page = new BackoutWizardPage(pageName, pageTitle, MercurialEclipsePlugin.getImageDescriptor(iconPath), hgRoot, selectedChangeSet); initPage(description, page); return page; } @Override public boolean performFinish() { return super.performFinish(); } } BackoutWizardPage.java000066400000000000000000000166211173713500500342130ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - modifications *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PartInitException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgBackoutClient; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.CommitMergeHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.team.cache.MercurialStatusCache; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.views.MergeView; /** * @author bastian */ public class BackoutWizardPage extends HgWizardPage { private ChangesetTable changesetTable; private Text messageTextField; private Button mergeCheckBox; private final HgRoot hgRoot; private Text userTextField; private ChangeSet selectedChangeSet; public BackoutWizardPage(String pageName, String title, ImageDescriptor image, HgRoot hgRoot, ChangeSet selectedChangeSet) { super(pageName, title, image); this.hgRoot = hgRoot; this.selectedChangeSet = selectedChangeSet; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); // list view of changesets Group changeSetGroup = SWTWidgetHelper.createGroup(composite, Messages .getString("BackoutWizardPage.changeSetGroup.title"), GridData.FILL_BOTH); //$NON-NLS-1$ changesetTable = new ChangesetTable(changeSetGroup, hgRoot); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 200; gridData.minimumHeight = 50; changesetTable.setLayoutData(gridData); try { changesetTable.highlightParents(HgParentClient.getParents(hgRoot)); } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); } SelectionListener listener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { onChangesetSelected(changesetTable.getSelection()); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; changesetTable.setEnabled(true); // now the options Group optionGroup = SWTWidgetHelper.createGroup(composite, Messages .getString("BackoutWizardPage.optionGroup.title")); //$NON-NLS-1$ SWTWidgetHelper.createLabel(optionGroup, Messages .getString("BackoutWizardPage.userLabel.text")); //$NON-NLS-1$ userTextField = SWTWidgetHelper.createTextField(optionGroup); userTextField.setText(HgCommitMessageManager.getDefaultCommitName(hgRoot)); SWTWidgetHelper.createLabel(optionGroup, Messages .getString("BackoutWizardPage.commitLabel.text")); //$NON-NLS-1$ messageTextField = SWTWidgetHelper.createTextField(optionGroup); // --merge merge with old dirstate parent after backout mergeCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("BackoutWizardPage.mergeCheckBox.text")); //$NON-NLS-1$ mergeCheckBox.setSelection(true); // Hack because initial selection event is not fired { if (selectedChangeSet == null) { selectedChangeSet = changesetTable.getStrategy().getChangeSet(0); } changesetTable.setSelection(selectedChangeSet); onChangesetSelected(selectedChangeSet); } changesetTable.addSelectionListener(listener); setControl(composite); setPageComplete(true); } protected void onChangesetSelected(final ChangeSet backoutRevision) { if (backoutRevision != null) { // Update commit message getShell().getDisplay().asyncExec(new Runnable() { public void run() { messageTextField.setText(Messages.getString( "BackoutWizardPage.defaultCommitMessage") //$NON-NLS-1$ + " " + backoutRevision.toString()); //$NON-NLS-1$ setPageComplete(true); } }); } else { setPageComplete(false); } } @Override public void setPageComplete(boolean complete) { if(complete){ complete = validate(); } super.setPageComplete(complete); } private boolean validate() { ChangeSet backoutRevision = changesetTable.getSelection(); mergeCheckBox.setEnabled(backoutRevision != null && !backoutRevision.isCurrent()); setErrorMessage(null); try { if (backoutRevision == null) { // Do nothing } else if (messageTextField.getText().length() == 0) { setErrorMessage("Please enter a commit message"); } else if(HgStatusClient.isDirty(hgRoot)){ setErrorMessage("Outstanding uncommitted changes! Backout is not possible."); } else { // All ok return true; } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } return false; } /** * @see com.vectrace.MercurialEclipse.wizards.HgWizardPage#finish(org.eclipse.core.runtime.IProgressMonitor) */ @Override public boolean finish(IProgressMonitor monitor) { if (!validate()) { return false; } String msg = messageTextField.getText(); ChangeSet backoutRevision = changesetTable.getSelection(); boolean merge = mergeCheckBox.getSelection() && !backoutRevision.isCurrent(); try { String result = HgBackoutClient.backout(hgRoot, backoutRevision, merge, msg, userTextField.getText()); HgClients.getConsole().printMessage(result, null); if (merge) { MercurialStatusCache.getInstance().refreshStatus(hgRoot, monitor); new CommitMergeHandler().run(hgRoot); } } catch (HgException e) { if (HgBackoutClient.isMergeError(e)) { if (merge) { try { MergeView.showMergeConflict(hgRoot, getShell()); } catch (PartInitException e1) { MercurialEclipsePlugin.logError(e1); } } else { MessageDialog .openInformation(null, "Unresolved conflicts", "You have unresolved conflicts. Use Synchronize View to edit conflicts"); } return true; } MessageDialog.openError(getShell(), Messages .getString("BackoutWizardPage.backoutError"), e //$NON-NLS-1$ .getMessage()); MercurialEclipsePlugin.logError(e); return false; } finally { new RefreshWorkspaceStatusJob(hgRoot, RefreshRootJob.LOCAL_AND_OUTGOING).schedule(); } return true; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/BundleRepoPage.java000066400000000000000000000146611173713500500335620ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgPathsClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author bastian * */ public class BundleRepoPage extends PushPullPage { private Text bundleFileTextField; private Button bundleFileBrowseButton; private String bundleFile; private ChangesetTable baseRevTable; private Button baseRevCheckbox; private ChangeSet baseRevision; public BundleRepoPage(String pageName, String title, ImageDescriptor titleImage, HgRoot hgRoot) { super(hgRoot, pageName, title, titleImage); setDescription("Generate a compressed changegroup file collecting changesets \n" + "not known to be in another repository."); setShowCredentials(true); } @Override public void createControl(Composite parent) { super.createControl(parent); Composite composite = (Composite) getControl(); Composite c = SWTWidgetHelper.createComposite(composite, 3); Group g = SWTWidgetHelper.createGroup(c, "Destination", 3, GridData.FILL_HORIZONTAL); SWTWidgetHelper.createLabel(g, "Bundle file to export to"); bundleFileTextField = SWTWidgetHelper.createTextField(g); bundleFileTextField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { if (bundleFileTextField.getText() != null && bundleFileTextField.getText().length() > 0) { setPageComplete(true); } } }); bundleFileBrowseButton = SWTWidgetHelper.createPushButton(g, "Select destination file...", 1); bundleFileBrowseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { FileDialog dialog = new FileDialog(getShell()); dialog .setText("Please select file to export to or enter the name of the file to be created"); String file = dialog.open(); if (file != null) { bundleFileTextField.setText(file); setErrorMessage(null); setPageComplete(true); } } }); Group baseGroup = SWTWidgetHelper.createGroup(c, "Base revision", 2, GridData.FILL_HORIZONTAL); baseRevCheckbox = SWTWidgetHelper.createCheckBox(baseGroup, "Select a base revision"); baseRevCheckbox.addSelectionListener(new SelectionListener() { private String oldRepo; public void widgetSelected(SelectionEvent e) { baseRevTable.setEnabled(baseRevCheckbox.getSelection()); if (baseRevCheckbox.getSelection()) { this.oldRepo = getUrlText(); getUrlCombo().setText(""); } else { getUrlCombo().setText(oldRepo); } } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }); baseRevTable = new ChangesetTable(baseGroup, getHgRoot()); GridData gd = SWTWidgetHelper.getFillGD(100); gd.heightHint = 100; baseRevTable.setLayoutData(gd); baseRevTable.setEnabled(false); optionGroup.moveBelow(c); optionGroup.setVisible(false); setControl(composite); } @Override public boolean finish(IProgressMonitor monitor) { bundleFile = bundleFileTextField.getText(); baseRevision = baseRevCheckbox.getSelection() ? baseRevTable.getSelection() : null; return super.finish(monitor); } @Override public boolean canFlipToNextPage() { try { String url = getUrlText(); if (url != null && url.length() > 0) { OutgoingPage outgoingPage = (OutgoingPage) getNextPage(); outgoingPage.setHgRoot(getHgRoot()); IHgRepositoryLocation loc = MercurialEclipsePlugin.getRepoManager() .getRepoLocation(url, getUserText(), getPasswordText()); outgoingPage.setLocation(loc); outgoingPage.setSvn(isSvnSelected()); outgoingPage.setForce(isForceSelected()); setErrorMessage(null); return isPageComplete() && (getWizard().getNextPage(this) != null); } } catch (HgException e) { setErrorMessage(e.getLocalizedMessage()); } return false; } @Override public boolean isPageComplete() { boolean isComplete = true; setErrorMessage(null); if (bundleFileTextField == null) { return false; } String bf = bundleFileTextField.getText(); if (bf == null || bf.length() == 0) { isComplete = false; setErrorMessage("No destination file selected. Please provide a destination file."); } return isComplete && super.isPageComplete(); } @Override protected IHgRepositoryLocation getRepoFromRoot() { HgRepositoryLocationManager mgr = MercurialEclipsePlugin.getRepoManager(); IHgRepositoryLocation defaultLocation = mgr.getDefaultRepoLocation(getHgRoot()); Set repos = mgr.getAllRepoLocations(getHgRoot()); if (defaultLocation == null) { for (IHgRepositoryLocation repo : repos) { if (HgPathsClient.DEFAULT_PUSH.equals(repo.getLogicalName()) || HgPathsClient.DEFAULT.equals(repo.getLogicalName())) { defaultLocation = repo; break; } } } return defaultLocation; } public String getBundleFile() { return bundleFile; } public ChangeSet getBaseRevision() { return baseRevision; } } BundleRepoWizard.java000066400000000000000000000065071173713500500340670ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.PlatformObject; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IExportWizard; import org.eclipse.ui.IWorkbench; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.BundleOperation; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; /** * @author Bastian */ public class BundleRepoWizard extends HgWizard implements IExportWizard { private HgRoot root; private IStructuredSelection selection; @SuppressWarnings("hiding") private BundleRepoPage page; private OutgoingPage outgoingPage; public BundleRepoWizard() { super("Export Mercurial Repository as Bundle"); } public void init(IWorkbench workbench, IStructuredSelection s) { this.selection = s; if (this.selection.isEmpty()) { return; } PlatformObject po = (PlatformObject) selection.getFirstElement(); IResource res = (IResource) po.getAdapter(IResource.class); try { root = MercurialTeamProvider.getHgRoot(res); if (root != null) { this.page = new BundleRepoPage("bundleRepoPage", "Export Mercurial Repository as Bundle", null, root); initPage(page.getDescription(), page); addPage(page); outgoingPage = new OutgoingPage("outgoingPage"); initPage(outgoingPage.getDescription(), outgoingPage); addPage(outgoingPage); } else { throw new HgException( "Could not find a Mercurial repository for export."); } } catch (HgException e) { MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); } } @Override public boolean performFinish() { // finish work in each page page.finish(new NullProgressMonitor()); outgoingPage.finish(new NullProgressMonitor()); String bundleFile = page.getBundleFile(); // only use a target rev if checkbox was selected ChangeSet cs = outgoingPage.isRevisionSelected() ? outgoingPage .getRevision() : null; // base will be null if nothing was selected or checkbox is not selected ChangeSet base = page.getBaseRevision(); // can be null or empty String repo = page.getUrlText(); // create operation BundleOperation op = new BundleOperation(getContainer(), root, cs, base, bundleFile, repo); try { // and run it... getContainer().run(true, true, op); } catch (Exception e) { MercurialEclipsePlugin.logError(e); page.setErrorMessage(e.getLocalizedMessage()); outgoingPage.setErrorMessage(e.getLocalizedMessage()); } return super.performFinish(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/ClonePage.java000066400000000000000000000371021173713500500325560ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IPageChangingListener; import org.eclipse.jface.dialogs.PageChangingEvent; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.wizard.IWizardContainer; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.operations.CloneOperation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author bastian * @author Andrei Loskutov */ public class ClonePage extends PushPullPage { private static final String DEFAULT_NAME = "with given name"; private static final String TOOLTIP = "A folder %s will be created,\n" + "and this will be the root folder for the clone content."; private Button pullCheckBox; private Button uncompressedCheckBox; private Text revisionTextField; private final Map destDirectories; private IHgRepositoryLocation lastRepo; private Text directoryTextField; private Button directoryButton; private Button useWorkspace; private Text cloneNameTextField; private static File lastUsedDir; public ClonePage(HgRoot hgRoot, String pageName, String title, ImageDescriptor titleImage) { super(hgRoot, pageName, title, titleImage); destDirectories = new HashMap(); setShowBundleButton(false); setShowCredentials(true); setShowForce(false); setShowSnapFile(false); } @Override public void createControl(Composite parent) { super.createControl(parent); if(getInitialRepo() == null) { setPageComplete(false); } } @Override protected void createExtensionControls() { super.createExtensionControls(); Composite composite = (Composite) getControl(); createDestGroup(composite); createOptionsGroup(composite); hookNextButtonListener(composite); } private static boolean isEmpty(String s){ return s == null || s.trim().length() == 0; } private void hookNextButtonListener(Composite composite) { IWizardContainer container = getWizard().getContainer(); if(!(container instanceof WizardDialog)){ return; } WizardDialog dialog = (WizardDialog) container; dialog.addPageChangingListener(new IPageChangingListener() { public void handlePageChanging(PageChangingEvent event) { if (event.getCurrentPage() == ClonePage.this && event.getTargetPage() != ClonePage.this.getPreviousPage()) { // Only fire if we're transitioning forward from this page. event.doit = nextButtonPressed(); } } }); } private void createDestGroup(Composite composite) { Group g = SWTWidgetHelper.createGroup(composite, Messages .getString("ClonePage.destinationGroup.title"), 3, GridData.FILL_HORIZONTAL); //$NON-NLS-1$ useWorkspace = SWTWidgetHelper.createCheckBox(g, "Checkout as a project(s) in the workspace"); GridData layoutData = new GridData(); layoutData.horizontalSpan = 3; useWorkspace.setLayoutData(layoutData); final String wsRootLocation = ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString(); useWorkspace.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if(useWorkspace.getSelection()){ directoryTextField.setText(wsRootLocation); directoryTextField.setEnabled(false); directoryButton.setEnabled(false); } else { directoryTextField.setText(""); directoryTextField.setEnabled(true); directoryButton.setEnabled(true); } } }); SWTWidgetHelper.createLabel(g, Messages .getString("ClonePage.destinationDirectoryLabel.title")); //$NON-NLS-1$ directoryTextField = SWTWidgetHelper.createTextField(g); if(lastUsedDir != null){ directoryTextField.setText(lastUsedDir.getAbsolutePath()); } else { directoryTextField.setText(wsRootLocation); } directoryTextField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { validateFields(); } }); directoryButton = SWTWidgetHelper.createPushButton(g, Messages .getString("ClonePage.directoryButton.title"), 1); //$NON-NLS-1$ directoryButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DirectoryDialog dialog = new DirectoryDialog(getShell()); if(!isEmpty(getRootName())) { dialog.setFilterPath(getRootName()); } dialog.setMessage(Messages.getString("ClonePage.directoryDialog.message")); //$NON-NLS-1$ String dir = dialog.open(); if (dir != null) { directoryTextField.setText(dir); } validateFields(); } }); if(lastUsedDir == null || wsRootLocation.equals(lastUsedDir.getAbsolutePath())){ useWorkspace.setSelection(true); directoryTextField.setEnabled(false); directoryButton.setEnabled(false); } SWTWidgetHelper.createLabel(g, Messages.getString("ClonePage.cloneDirectoryLabel.title")); //$NON-NLS-1$ cloneNameTextField = SWTWidgetHelper.createTextField(g); cloneNameTextField.setToolTipText(String.format(TOOLTIP, DEFAULT_NAME)); cloneNameTextField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { validateFields(); IHgRepositoryLocation repo = getRepository(); File destinationDirectory = getDestinationDirectory(); cloneNameTextField.setToolTipText(String.format(TOOLTIP, destinationDirectory.getAbsolutePath())); if(repo != null && hasDataLocally(repo)){ // if only the target directory name is changed, simply rename it on // the disk to avoid another remote clone operation File file = destDirectories.get(repo); String cloneName = getCloneName(); if(cloneName.length() > 0 && !file.getName().equals(cloneName)){ if(!destinationDirectory.exists()){ if(file.renameTo(destinationDirectory)) { destDirectories.put(repo, destinationDirectory); } } validateFields(); } } } }); g.moveAbove(optionGroup); } private void createOptionsGroup(Composite composite) { Group g = optionGroup; pullCheckBox = SWTWidgetHelper.createCheckBox(g, Messages .getString("ClonePage.pullCheckBox.title")); //$NON-NLS-1$ uncompressedCheckBox = SWTWidgetHelper.createCheckBox(g, Messages .getString("ClonePage.uncompressedCheckBox.title")); //$NON-NLS-1$ uncompressedCheckBox.setSelection(MercurialEclipsePlugin.getDefault().getPreferenceStore() .getBoolean(MercurialPreferenceConstants.PREF_CLONE_UNCOMPRESSED)); SWTWidgetHelper.createLabel(g, Messages .getString("ClonePage.revisionLabel.title")); //$NON-NLS-1$ revisionTextField = SWTWidgetHelper.createTextField(g); } private String getCloneName() { return cloneNameTextField.getText(); } private String getRootName() { return directoryTextField.getText(); } public File getDestinationDirectory() { String root = getRootName(); File dest = new File(root, getCloneName()); try { return new HgRoot(dest); } catch (IOException e) { MercurialEclipsePlugin.logError(e); return dest; } } @Override protected boolean urlChanged() { boolean dataFetched = false; IHgRepositoryLocation repository = null; if(super.validateFields()){ repository = getRepository(); dataFetched = hasDataLocally(repository); } if(!dataFetched) { cloneNameTextField.setText(guessProjectName(getUrlText())); } if(dataFetched){ File fullPath = destDirectories.get(repository); directoryTextField.setText(fullPath.getParentFile().getAbsolutePath()); cloneNameTextField.setText(fullPath.getName()); } return super.urlChanged(); } /** * Tries to guess project name from given directory/repository url * @param urlText non null * @return never return null, may return empty string */ private String guessProjectName(String urlText) { if(urlText.length() == 0){ return urlText; } urlText = urlText.replace('\\', '/'); while(urlText.endsWith("/")){ urlText = urlText.substring(0, urlText.length() - 1); } // extract last part of path/url (if any) int last = urlText.lastIndexOf('/'); String guess = ""; if(last > 0 && last + 1 < urlText.length()){ guess = urlText.substring(last + 1); // many projects repositories ends with "hg", so try to skip this if("hg".equals(guess)){ // google project names are the first part of the repo url, like // https://anyedittools.googlecode.com/hg/ if(urlText.contains(".googlecode.")){ return guessProjectName(urlText.substring(0, urlText.indexOf(".googlecode."))); } // just try the first part before "hg" return guessProjectName(urlText.substring(0, last)); } } return guess; } private boolean hasDataLocally(IHgRepositoryLocation repo){ if(repo == null){ return false; } File localClone = destDirectories.get(repo); return localClone != null && localClone.exists(); } @Override public void setVisible(boolean visible) { super.setVisible(visible); } public void performCleanup(){ Collection values = destDirectories.values(); for (File file : values) { ResourceUtils.delete(file, true); } } @Override protected boolean validateFields() { boolean ok = super.validateFields(); if(!ok){ setMessage(null, INFORMATION); setPageComplete(false); return false; } boolean destinationNameOk = validateDestinationName(); if(!destinationNameOk) { setPageComplete(false); return false; } IHgRepositoryLocation repository = getRepository(); if(repository == null) { setErrorMessage("Clone repository URL is invalid!"); setPageComplete(false); return false; } File destinationDirectory = getDestinationDirectory(); boolean dataFetched = destinationDirectory.equals(destDirectories.get(repository)); if(destinationDirectory.exists() && !dataFetched){ setErrorMessage("Directory '" + destinationDirectory + "' already exists. Please " + "choose a new, not existing directory!"); setPageComplete(false); return false; } else if (!destinationDirectory.getParentFile().canWrite()) { setErrorMessage("You have no permissions to write into '" + destinationDirectory.getParent() + "'!"); setPageComplete(false); return false; } else { setPageComplete(true); } setErrorMessage(null); setMessage(null, INFORMATION); if(!dataFetched){ setMessage("Ready to start clone", INFORMATION); } else { setMessage(null); } setPageComplete(true); return true; } private boolean validateDestinationName() { boolean rootOk = !isEmpty(getRootName()) && new File(getRootName()).isDirectory(); boolean nameOk = !isEmpty(getCloneName()); if(!rootOk){ setErrorMessage("Please specify existing parent directory for clone"); } else if(!nameOk){ setErrorMessage("Please specify the directory name for clone repository"); } else { setErrorMessage(null); } return rootOk && nameOk; } @Override public boolean canFlipToNextPage() { return isPageComplete(); } @Override public IWizardPage getNextPage() { IWizardPage nextPage = super.getNextPage(); File destinationDirectory = getDestinationDirectory(); rememberLastUsed(destinationDirectory); return nextPage; } private static void rememberLastUsed(File destinationDirectory) { lastUsedDir = destinationDirectory.getParentFile(); } @Override protected String getTimeoutCheckBoxLabel() { return Messages.getString("ClonePage.timeoutCheckBox.title"); } @Override public boolean finish(IProgressMonitor monitor) { boolean ok = super.finish(monitor); if(!ok){ return false; } boolean forest = false; if (isShowForest()) { forest = isForestSelected(); } boolean svn = false; if (isShowSvn()) { svn = isSvnSelected(); } lastRepo = getRepository(); if(lastRepo == null){ setErrorMessage("Clone repository URL is invalid!"); setPageComplete(false); return false; } File destDirectory = getDestinationDirectory(); ok = destDirectory.mkdirs(); if(!ok){ setErrorMessage("Failed to create destination directory '" + destDirectory + "'!"); return false; } MercurialEclipsePlugin.getDefault().getPreferenceStore().setValue( MercurialPreferenceConstants.PREF_CLONE_UNCOMPRESSED, uncompressedCheckBox.getSelection()); try { // run clone boolean pull = pullCheckBox.getSelection(); boolean uncompressed = uncompressedCheckBox.getSelection(); boolean timeout2 = isTimeoutSelected(); String rev = revisionTextField.getText(); boolean noUpdate = true; if(svn || forest){ // TODO allow branch /revision selection for the svn/forest clones noUpdate = false; } CloneOperation cloneOperation = new CloneOperation(getContainer(), destDirectory .getParentFile(), lastRepo, noUpdate, pull, uncompressed, timeout2, rev, destDirectory.getName(), forest, svn); getContainer().run(true, true, cloneOperation); } catch (InvocationTargetException e) { ResourceUtils.delete(destDirectory, true); return handle(e); } catch (InterruptedException e) { // operation cancelled by user ResourceUtils.delete(destDirectory, true); return false; } destDirectories.put(lastRepo, destDirectory); return true; } public IHgRepositoryLocation getLastUsedRepository(){ return lastRepo; } private IHgRepositoryLocation getRepository() { if(getUrlText().length() == 0){ return null; } Properties props = createProperties(); try { return MercurialEclipsePlugin.getRepoManager().getRepoLocation(props); } catch (HgException e) { return null; } } private boolean handle(Exception e) { Throwable t = e.getCause(); if (t == null) { t = e; } if (t instanceof HgException) { setErrorMessage(((HgException) t).getConciseMessage()); } else { setErrorMessage(t.getLocalizedMessage()); } MercurialEclipsePlugin.logError(Messages .getString("CloneRepoWizard.cloneOperationFailed"), e); return false; } private boolean nextButtonPressed() { IHgRepositoryLocation repository = getRepository(); if (hasDataLocally(repository) && getDestinationDirectory().equals(destDirectories.get(repository))) { // simply forward to the next page return true; } // start clone return finish(null); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/CloneRepoWizard.java000066400000000000000000000065721173713500500337770ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Balm Consulting Inc (Peter Hunnisett ) - implementation * VecTrace (Zingo Andersen) - some updates * Stefan Groschupf - logError * Stefan C - Code cleanup * Bastian Doetsch - saving repository to project-specific repos * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.ui.IImportWizard; import org.eclipse.ui.INewWizard; import org.eclipse.ui.IWorkbench; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; /** * This class implements the import wizard extension and the new wizard * extension. */ public class CloneRepoWizard extends HgWizard implements IImportWizard, INewWizard { private final ClonePage clonePage; private final ProjectsImportPage importPage; private IHgRepositoryLocation defaultLocation; private final SelectRevisionPage selectRevisionPage; public CloneRepoWizard() { super(Messages.getString("CloneRepoWizard.title")); //$NON-NLS-1$ clonePage = new ClonePage(null, Messages .getString("CloneRepoWizard.pageName"), //$NON-NLS-1$ Messages.getString("CloneRepoWizard.pageTitle"), null); //$NON-NLS-1$ clonePage.setDescription(Messages .getString("CloneRepoWizard.pageDescription")); //$NON-NLS-1$ initPage(clonePage.getDescription(), clonePage); setNeedsProgressMonitor(true); selectRevisionPage = new SelectRevisionPage("SelectRevisionPage"); importPage = new ProjectsImportPage("ProjectsImportPage"); addPage(clonePage); addPage(selectRevisionPage); addPage(importPage); } @Override public boolean performFinish() { return importPage.createProjects(); } @Override public boolean performCancel() { clonePage.performCleanup(); return super.performCancel(); } @Override public IWizardPage getStartingPage() { return clonePage; } public IHgRepositoryLocation getRepository() { return clonePage.getLastUsedRepository(); } public void init(IWorkbench workbench, IStructuredSelection selection) { setWindowTitle(Messages.getString("CloneRepoWizard.title")); //$NON-NLS-1$ if(!selection.isEmpty()){ Object firstElement = selection.getFirstElement(); if(firstElement instanceof IHgRepositoryLocation){ IHgRepositoryLocation repo = (IHgRepositoryLocation) firstElement; setDefaultLocation(repo); } } if(getDefaultLocation() != null) { clonePage.setInitialRepo(getDefaultLocation()); } } @Override public boolean canFinish() { return getContainer() != null && getContainer().getCurrentPage() instanceof ProjectsImportPage && super.canFinish(); } public void setDefaultLocation(IHgRepositoryLocation defaultLocation) { this.defaultLocation = defaultLocation; } public IHgRepositoryLocation getDefaultLocation() { return defaultLocation; } } ConfigurationWizardMainPage.java000066400000000000000000000436741173713500500362470ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptions&additions * Adam Berkes (Intland) - repository location handling * Zsolt Koppany (Intland) - bug fixes * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.TreeSet; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgPathsClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationParser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * Wizard page for entering information about a Hg repository location. This * wizard can be initialized using setProperties or using setDialogSettings */ public class ConfigurationWizardMainPage extends HgWizardPage { private static final String REPO_SEPARATOR = "----------------"; public static final String PROP_PASSWORD = "password"; public static final String PROP_USER = "user"; public static final String PROP_URL = "url"; private static final int COMBO_HISTORY_LENGTH = 10; /** Dialog store id constant */ private static final String STORE_USERNAME_ID = "ConfigurationWizardMainPage.STORE_USERNAME_ID"; //$NON-NLS-1$ private boolean showCredentials; private boolean showBundleButton; private Combo userCombo; protected Text passwordText; /** url of the repository we want to add */ private Combo urlCombo; /** local repositories button */ private Button browseButton; private Button browseFileButton; private IHgRepositoryLocation initialRepo; private Composite authComposite; private HgRoot hgRoot; private Group urlGroup; /** * @param pageName * the name of the page * @param title * the title of the page * @param titleImage * the image for the page */ public ConfigurationWizardMainPage(String pageName, String title, ImageDescriptor titleImage) { super(pageName, title, titleImage); } /** * Adds an entry to a history, while taking care of duplicate history items * and excessively long histories. The assumption is made that all histories * should be of length * ConfigurationWizardMainPage.COMBO_HISTORY_LENGTH. * * @param history * the current history * @param newEntry * the entry to add to the history * @param limitHistory * number of max entries, -1 if no limit * @return the history with the new entry appended */ private static String[] addToHistory(String[] history, String newEntry, int limitHistory) { ArrayList list = new ArrayList(); if (history != null) { list.addAll(Arrays.asList(history)); } list.remove(newEntry); list.add(0, newEntry); // since only one new item was added, we can be over the limit // by at most one item if (list.size() > COMBO_HISTORY_LENGTH && limitHistory > 0) { list.remove(COMBO_HISTORY_LENGTH); } return list.toArray(new String[list.size()]); } /** * Creates the UI part of the page. * * @param parent * the parent of the created widgets */ public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 1); Listener listener = new Listener() { public void handleEvent(Event event) { urlChanged(); } }; createUrlControl(composite, listener); if (showCredentials) { createAuthenticationControl(composite); } setControl(composite); urlCombo.setFocus(); initializeValues(); boolean ok = validateFields(); setPageComplete(ok); if(ok) { setErrorMessage(null); } } private void createUrlControl(Composite composite, final Listener listener) { Composite urlComposite = SWTWidgetHelper.createComposite(composite, 4); urlGroup = SWTWidgetHelper.createGroup(urlComposite, Messages.getString("ConfigurationWizardMainPage.urlGroup.title"), 4, //$NON-NLS-1$ GridData.FILL_HORIZONTAL); // repository Url SWTWidgetHelper.createLabel(urlGroup, Messages.getString("ConfigurationWizardMainPage.urlLabel.text")); //$NON-NLS-1$ urlCombo = createEditableCombo(urlGroup); urlCombo.addListener(SWT.Modify, listener); browseButton = SWTWidgetHelper.createPushButton(urlGroup, Messages.getString("ConfigurationWizardMainPage.browseButton.text"), 1); //$NON-NLS-1$ browseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { DirectoryDialog dialog = new DirectoryDialog(getShell()); File localDirectory = getLocalDirectory(getUrlText()); if(localDirectory != null) { dialog.setFilterPath(localDirectory.getAbsolutePath()); } dialog.setMessage(Messages.getString("ConfigurationWizardMainPage.dialog.message")); //$NON-NLS-1$ String dir = dialog.open(); if (dir != null) { dir = dir.trim(); getUrlCombo().setText(dir); } } }); if (showBundleButton) { browseFileButton = SWTWidgetHelper.createPushButton(urlGroup, Messages.getString("PullPage.browseFileButton.text"), 1); //$NON-NLS-1$ browseFileButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { FileDialog dialog = new FileDialog(getShell()); dialog.setText(Messages.getString("PullPage.bundleDialog.text")); //$NON-NLS-1$ String file = dialog.open(); if (file != null) { getUrlCombo().setText(file); } } }); } urlCombo.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { IHgRepositoryLocation repo; try { // note that repo will not be null, will be blank // repo if no existing one was found repo = MercurialEclipsePlugin.getRepoManager().getRepoLocation(getUrlText()); } catch (HgException e1) { // Lookup obviously failed, but verification will pick this error up later // no need to report typing error return; } if (getUserCombo() != null) { String user = repo.getUser(); if (user != null && user.length() != 0) { getUserCombo().setText(user); } else { getUserCombo().setText(""); } } if (getPasswordText() != null) { String password = repo.getPassword(); if (password != null && password.length() != 0) { passwordText.setText(password); } else { passwordText.setText(""); } } } }); } public void setUrlGroupEnabled(boolean enable){ if(urlGroup != null) { urlGroup.setEnabled(enable); Control[] children = urlGroup.getChildren(); if(children != null){ for (Control control : children) { control.setEnabled(enable); } } } } private void createAuthenticationControl(Composite composite) { authComposite = SWTWidgetHelper.createComposite(composite, 2); Group g = SWTWidgetHelper.createGroup( authComposite, Messages.getString("ConfigurationWizardMainPage.authenticationGroup.title")); //$NON-NLS-1$ // User name SWTWidgetHelper.createLabel(g, Messages.getString("ConfigurationWizardMainPage.userLabel.text")); //$NON-NLS-1$ userCombo = createEditableCombo(g); // Password SWTWidgetHelper.createLabel(g, Messages.getString("ConfigurationWizardMainPage.passwordLabel.text")); //$NON-NLS-1$ passwordText = SWTWidgetHelper.createPasswordField(g); userCombo.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent arg0) { canFlipToNextPage(); } }); passwordText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent arg0) { canFlipToNextPage(); } }); } protected void setAuthCompositeEnabled(boolean enable){ authComposite.setEnabled(enable); userCombo.setEnabled(enable); passwordText.setEnabled(enable); } /** * Utility method to create an editable combo box * * @param parent * the parent of the combo box * @return the created combo */ protected static Combo createEditableCombo(Composite parent) { Combo combo = new Combo(parent, SWT.NULL); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH; combo.setLayoutData(data); return combo; } /** * @see HgWizardPage#finish */ @Override public boolean finish(IProgressMonitor monitor) { // Set the result to be the current values properties = createProperties(); saveWidgetValues(); return true; } protected Properties createProperties() { Properties result = new Properties(); if (showCredentials) { result.setProperty(PROP_USER, getUserText()); result.setProperty(PROP_PASSWORD, passwordText.getText()); } result.setProperty(PROP_URL, getUrlText()); return result; } /** * Initializes states of the controls. */ private void initializeValues() { // Set remembered values IDialogSettings setts = getDialogSettings(); if (setts != null) { String[] hostNames = updateHostNames(); if (hostNames != null) { for (String hn : hostNames) { urlCombo.add(hn); } } if (showCredentials) { String[] userNames = setts.getArray(STORE_USERNAME_ID); if (userNames != null) { for (String un : userNames) { userCombo.add(un); } } } } if (properties != null) { if (showCredentials) { String user = properties.getProperty(PROP_USER); if (user != null) { userCombo.setText(user); } String password = properties.getProperty(PROP_PASSWORD); if (password != null) { passwordText.setText(password); } } String host = properties.getProperty(PROP_URL); if (host != null) { urlCombo.setText(host); } } } /** * Saves the widget values for the next time */ private void saveWidgetValues() { // Update history IDialogSettings dialogSettings = getDialogSettings(); if (settings != null) { if (showCredentials) { String[] userNames = dialogSettings.getArray(STORE_USERNAME_ID); if (userNames == null) { userNames = new String[0]; } userNames = addToHistory(userNames, getUserText(), COMBO_HISTORY_LENGTH); dialogSettings.put(STORE_USERNAME_ID, userNames); } } } protected String getUserText() { return userCombo.getText().trim(); } protected String getUrlText() { String text = urlCombo.getText(); if(REPO_SEPARATOR.equals(text)){ return ""; } text = HgRepositoryLocationParser.trimLocation(text); return text; } private String[] updateHostNames() { List newHostNames = new ArrayList(); Set repositories; Set all = MercurialEclipsePlugin.getRepoManager().getAllRepoLocations(); if (hgRoot == null) { repositories = new TreeSet(); } else { repositories = MercurialEclipsePlugin.getRepoManager().getAllRepoLocations(hgRoot); } for (IHgRepositoryLocation repoLocation : repositories) { if(repoLocation.getLocation() != null) { newHostNames.add(repoLocation.getLocation()); } } if(repositories.size() > 0) { newHostNames.add(REPO_SEPARATOR); } for (IHgRepositoryLocation repoLocation : all) { String location = repoLocation.getLocation(); if(location != null && !newHostNames.contains(location)) { newHostNames.add(location); } } return newHostNames.toArray(new String[newHostNames.size()]); } /** * Validates the contents of the editable fields and set page completion and * error messages appropriately. Call each time url or username is modified */ protected boolean validateFields() { // first check the url of the repository String url = getUrlText(); if (url.length() == 0) { setErrorMessage(null); return false; } File localDirectory = getLocalDirectory(url); if(localDirectory != null){ if(!localDirectory.exists()){ setErrorMessage("Please provide a valid url or an existing directory!"); return false; } File hgRepo = new File(localDirectory, ".hg"); if(!hgRepo.isDirectory()){ setErrorMessage("Directory " + localDirectory + " does not contain a valid hg repository!"); return false; } } return true; } /** * @param urlString non null * @return true if the given url can be threated as local directory */ @SuppressWarnings("static-method") protected File getLocalDirectory(String urlString) { if (urlString != null) { urlString = urlString.trim(); } if (urlString == null || urlString.length() == 0 || urlString.contains("http:") || urlString.contains("https:") || urlString.contains("ftp:") || urlString.contains("ssh:")) { return null; } File dir = new File(urlString); if (dir.isDirectory()) { return dir; } try { // Supporting file:// URLs URL url = new URL(urlString); return new File(url.getPath()); } catch (Exception e) { return null; } } @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { if (urlCombo != null) { urlCombo.setFocus(); } } } @Override public boolean canFlipToNextPage() { return super.canFlipToNextPage(); } public boolean isShowCredentials() { return showCredentials; } public void setShowCredentials(boolean showCredentials) { this.showCredentials = showCredentials; } protected Combo getUserCombo() { return userCombo; } public String getPasswordText() { return passwordText.getText(); } protected Combo getUrlCombo() { return urlCombo; } public boolean isShowBundleButton() { return showBundleButton; } public void setShowBundleButton(boolean showBundleButton) { this.showBundleButton = showBundleButton; } protected boolean optionChanged() { return urlChanged(); } /** * Triggered if the user has changed repository url. Override to implement additional * checks after it. * @return true, if the filed validation was successful */ protected boolean urlChanged() { boolean ok = validateFields(); setPageComplete(ok); if(ok) { setErrorMessage(null); } return ok; } protected HgRoot getHgRoot() { return hgRoot; } protected void initDefaultLocation() { IHgRepositoryLocation defaultLocation = null; if (getHgRoot() != null) { defaultLocation = getRepoFromRoot(); } if(defaultLocation == null){ defaultLocation = getInitialRepo(); } setRepository(defaultLocation); } protected IHgRepositoryLocation getRepoFromRoot(){ HgRepositoryLocationManager mgr = MercurialEclipsePlugin.getRepoManager(); IHgRepositoryLocation defaultLocation = mgr.getDefaultRepoLocation(getHgRoot()); Set repos = mgr.getAllRepoLocations(getHgRoot()); if (defaultLocation == null) { for (IHgRepositoryLocation repo : repos) { if (HgPathsClient.DEFAULT_PULL.equals(repo.getLogicalName()) || HgPathsClient.DEFAULT.equals(repo.getLogicalName())) { defaultLocation = repo; break; } } } return defaultLocation; } public void setRepository(IHgRepositoryLocation repo) { if (repo == null) { return; } getUrlCombo().setText(repo.getLocation()); String user = repo.getUser(); if (user != null && user.length() != 0) { getUserCombo().setText(user); } String password = repo.getPassword(); if (password != null && password.length() != 0) { passwordText.setText(password); } } @Override public void setProperties(Properties properties) { super.setProperties(properties); if(urlCombo != null && isValid(properties, PROP_URL)){ String[] items = urlCombo.getItems(); if(items != null){ String url = properties.getProperty(PROP_URL); for (int i = 0; i < items.length; i++) { if(url.equals(items[i])){ urlCombo.select(i); break; } } } } if(userCombo != null && isValid(properties, PROP_USER)){ String[] items = userCombo.getItems(); if(items != null){ String user = properties.getProperty(PROP_USER); for (int i = 0; i < items.length; i++) { if(user.equals(items[i])){ userCombo.select(i); break; } } } } if(passwordText != null && isValid(properties, PROP_PASSWORD)){ passwordText.setText(properties.getProperty(PROP_PASSWORD)); } } private static boolean isValid(Properties properties, String key){ String value = properties.getProperty(key); return value != null && value.trim().length() > 0; } public void setInitialRepo(IHgRepositoryLocation initialRepo) { this.initialRepo = initialRepo; } public IHgRepositoryLocation getInitialRepo() { return initialRepo; } public void setHgRoot(HgRoot hgRoot) { this.hgRoot = hgRoot; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/CreateRepoPage.java000066400000000000000000000114541173713500500335510ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.net.URL; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.Path; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author Andrei */ public class CreateRepoPage extends ConfigurationWizardMainPage { private Button createCheckBox; public CreateRepoPage() { super(Messages.getString("NewLocationWizard.repoCreationPage.name"), //$NON-NLS-1$ Messages.getString("NewLocationWizard.repoCreationPage.title"), //$NON-NLS-1$ MercurialEclipsePlugin.getImageDescriptor("wizards/share_wizban.png") //$NON-NLS-1$ ); setShowCredentials(true); setShowBundleButton(false); } @Override public void createControl(Composite parent) { super.createControl(parent); Composite composite = (Composite) getControl(); createCheckBox = SWTWidgetHelper.createCheckBox(composite, "Init Mercurial repository (creates hg root at given location)"); createCheckBox.setSelection(true); createCheckBox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { validateFields(); } }); } @Override protected boolean validateFields() { if(createCheckBox == null){ return super.validateFields(); } // first check the url of the repository String url = getUrlText(); if (url.length() == 0) { setErrorMessage(null); createCheckBox.setEnabled(true); setAuthCompositeEnabled(false); return false; } File localDirectory = getLocalDirectory(url); if(localDirectory != null){ createCheckBox.setEnabled(true); setAuthCompositeEnabled(false); } else { boolean isSsh = url.startsWith("ssh:"); createCheckBox.setEnabled(isSsh); setAuthCompositeEnabled(true); } try { HgRepositoryLocationManager repoManager = MercurialEclipsePlugin.getRepoManager(); IHgRepositoryLocation repoLocation = repoManager.getRepoLocation(url); if(repoManager.getAllRepoLocations().contains(repoLocation)){ setErrorMessage("Repository location already known!"); return false; } } catch (HgException e) { // do not report error here } if(localDirectory != null){ if(!localDirectory.exists() && !createCheckBox.getSelection()){ setErrorMessage("Please give a valid url or an existing directory!"); return false; } File hgRepo = new File(localDirectory, ".hg"); if(!hgRepo.isDirectory() && !createCheckBox.getSelection()){ setErrorMessage("Directory " + localDirectory + " does not contain a valid hg repository!"); return false; } IFile fileHandle = ResourceUtils.getFileHandle(new Path(localDirectory.getAbsolutePath())); if(fileHandle != null && (fileHandle.exists() || fileHandle.getProject() != null)){ setErrorMessage("You can not create new repository inside existing project!"); return false; } } setErrorMessage(null); return true; } /** * @param urlString non null * @return non null file object if the given url can be treated as local directory */ @Override protected File getLocalDirectory(String urlString) { if(urlString == null){ return null; } urlString = urlString.trim(); if (urlString.length() == 0 || urlString.contains("http:") || urlString.contains("https:") || urlString.contains("ftp:") || urlString.contains("ssh:")) { return null; } if (urlString.contains("file:")){ try { // Supporting file:// URLs URL url = new URL(urlString); return new File(url.getPath()); } catch (Exception e) { return null; } } File dir = new File(urlString); if (dir.isFile()) { return null; } return dir; } public File getLocalRepo(){ return getLocalDirectory(getUrlText()); } public boolean shouldInitRepo(){ return createCheckBox.getSelection(); } @Override protected boolean urlChanged() { return super.urlChanged(); } } ExportOptionsPage.java000066400000000000000000000111771173713500500343000ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * steeven - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.ArrayList; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * Last page of import wizard for import options. */ public class ExportOptionsPage extends HgWizardPage implements Listener { private Button chkGit; private Button chkBase; private Button chkText; private Button chkFunction; private Text txtUnified; private Button chkUnified; private Text txtBase; private Button chkNoDate; private Button chkIgnoreAllSpace; private Button chkIgnoreSpaceChange; private Button chkIgnoreBlankLines; public ExportOptionsPage() { super(Messages.getString("ImportPatchWizard.optionsPageName"), Messages //$NON-NLS-1$ .getString("ImportPatchWizard.optionsPageTitle"), null); //$NON-NLS-1$ } protected boolean validatePage() { return true; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); chkGit = SWTWidgetHelper.createCheckBox(composite, Messages .getString("ExportOptionsPage.git")); //$NON-NLS-1$ chkText = SWTWidgetHelper.createCheckBox(composite, Messages .getString("ExportOptionsPage.text")); //$NON-NLS-1$ chkBase = createLabelCheckBox(composite, Messages .getString("ExportOptionsPage.rev")); //$NON-NLS-1$ chkBase.addListener(SWT.Selection, this); txtBase = SWTWidgetHelper.createTextField(composite); chkFunction = SWTWidgetHelper.createCheckBox(composite, Messages .getString("ExportOptionsPage.function")); //$NON-NLS-1$ chkNoDate = SWTWidgetHelper.createCheckBox(composite, Messages .getString("ExportOptionsPage.noDate")); //$NON-NLS-1$ chkIgnoreAllSpace = SWTWidgetHelper.createCheckBox(composite, Messages .getString("ExportOptionsPage.ignoreAllSpace")); //$NON-NLS-1$ chkIgnoreSpaceChange = SWTWidgetHelper.createCheckBox(composite, Messages.getString("ExportOptionsPage.ignoreSpaceChange")); //$NON-NLS-1$ chkIgnoreBlankLines = SWTWidgetHelper.createCheckBox(composite, Messages.getString("ExportOptionsPage.ignoreBlankLines")); //$NON-NLS-1$ chkUnified = createLabelCheckBox(composite, Messages .getString("ExportOptionsPage.context")); //$NON-NLS-1$ chkUnified.addListener(SWT.Selection, this); txtUnified = SWTWidgetHelper.createTextField(composite); setControl(composite); validate(); } public void handleEvent(Event event) { validate(); } private void validate() { txtUnified.setEnabled(chkUnified.getSelection()); txtBase.setEnabled(chkBase.getSelection()); setErrorMessage(null); setPageComplete(true); } /* * (non-Javadoc) * * @see * com.vectrace.MercurialEclipse.wizards.HgWizardPage#finish(org.eclipse * .core.runtime.IProgressMonitor) */ @Override public boolean finish(IProgressMonitor monitor) { // getDialogSettings(); save setttings. return super.finish(monitor); } ArrayList getOptions() { ArrayList list = new ArrayList(); if (chkBase.getSelection()) { list.add("-r " + txtBase.getText()); //$NON-NLS-1$ } if (chkText.getSelection()) { list.add("-a"); //$NON-NLS-1$ } if (chkGit.getSelection()) { list.add("-g"); //$NON-NLS-1$ } if (chkFunction.getSelection()) { list.add("-p"); //$NON-NLS-1$ } if (chkNoDate.getSelection()) { list.add("--nodates"); //$NON-NLS-1$ } if (chkIgnoreAllSpace.getSelection()) { list.add("-w"); //$NON-NLS-1$ } if (chkIgnoreSpaceChange.getSelection()) { list.add("-b"); //$NON-NLS-1$ } if (chkIgnoreBlankLines.getSelection()) { list.add("-B"); //$NON-NLS-1$ } if (chkUnified.getSelection()) { list.add("-U " + txtUnified.getText()); //$NON-NLS-1$ } return list; } public static Button createLabelCheckBox(Composite group, String label) { Button button = new Button(group, SWT.CHECK | SWT.LEFT); button.setText(label); return button; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/ExportPatchPage.java000066400000000000000000000172461173713500500337660ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * steeven - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.ui.CommitFilesChooser; import com.vectrace.MercurialEclipse.ui.LocationChooser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.ui.LocationChooser.Location; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * A wizard page which will allow the user to choose location to export patch. * */ public abstract class ExportPatchPage extends HgWizardPage implements Listener { private LocationChooser locationChooser; // constructors private ExportPatchPage() { super(Messages.getString("ExportPatchWizard.pageName"), Messages //$NON-NLS-1$ .getString("ExportPatchWizard.pageTitle"), null); // TODO icon //$NON-NLS-1$ } // operations protected boolean validatePage() { String msg = locationChooser.validate(); if (msg == null && getSelectedItems().length == 0) { msg = "Please select at least one file to export"; //$NON-NLS-1$ } if (msg == null) { setMessage(null); } setErrorMessage(msg); setPageComplete(msg == null); return msg == null; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 1); Group group = SWTWidgetHelper.createGroup(composite, Messages .getString("ExportPatchWizard.PathLocation")); //$NON-NLS-1$ locationChooser = new LocationChooser(group, true, getDialogSettings(), getFileName()); locationChooser.addStateListener(this); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.horizontalAlignment = SWT.FILL; locationChooser.setLayoutData(data); createItemChooser(composite); setControl(composite); validatePage(); } /** * @return The file name to use, or null to use most recent */ protected abstract String getFileName(); protected abstract void createItemChooser(Composite composite); public abstract Object[] getSelectedItems(); public void handleEvent(Event event) { validatePage(); } public Location getLocation() { return locationChooser.getCheckedLocation(); } @Override public boolean finish(IProgressMonitor monitor) { locationChooser.saveSettings(); return super.finish(monitor); } public static ExportPatchPage create(final List resource) { return new ResourceExportPatchPage(resource); } public static ExportPatchPage create(final ChangeSet cs) { return new ChangeSetExportPatchPage(cs); } // inner types private static final class ResourceExportPatchPage extends ExportPatchPage { private final List resource; private CommitFilesChooser commitFiles; private ResourceExportPatchPage(List resource) { this.resource = resource; } @Override protected void createItemChooser(Composite composite) { // TODO no diff for untracked files, bug? commitFiles = new CommitFilesChooser(composite, true, resource, false, false, false); commitFiles.setLayoutData(new GridData(GridData.FILL_BOTH)); commitFiles.addStateListener(this); } @Override public Object[] getSelectedItems() { List l = commitFiles.getCheckedResources(); return l.toArray(new IResource[l.size()]); } /** * @see com.vectrace.MercurialEclipse.wizards.ExportPatchPage#getFileName() */ @Override protected String getFileName() { return "UncommittedChanges.patch"; } } private static final class ChangeSetExportPatchPage extends ExportPatchPage { private final ChangeSet cs; private ChangeSetExportPatchPage(ChangeSet cs) { this.cs = cs; } /** * @see com.vectrace.MercurialEclipse.wizards.ExportPatchPage#createItemChooser(org.eclipse.swt.widgets.Composite) */ @Override protected void createItemChooser(Composite composite) { Composite c = new Composite(composite, SWT.NONE); GridLayout layout = new GridLayout(); layout.verticalSpacing = 3; layout.horizontalSpacing = 0; layout.marginWidth = 0; layout.marginHeight = 0; c.setLayout(layout); c.setLayoutData(SWTWidgetHelper.getFillGD(150)); Table table = new Table(c, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.READ_ONLY | SWT.HIDE_SELECTION); table.setHeaderVisible(false); table.setLinesVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); table.setLayoutData(data); TableViewer viewer = new TableViewer(table); viewer.setContentProvider(new ArrayContentProvider()); viewer.setLabelProvider(new LabelProvider() { /** * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object) */ @Override public Image getImage(Object element) { if (element instanceof ChangeSet) { return MercurialEclipsePlugin.getImage("elcl16/changeset_obj.gif"); } return super.getImage(element); } /** * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) */ @Override public String getText(Object element) { if (element instanceof ChangeSet) { ChangeSet cset = (ChangeSet) element; StringBuilder sb = new StringBuilder(); sb.append(cset.getChangesetIndex()); sb.append(" [").append(cset.getAuthor()).append(']'); sb.append(" (").append(cset.getAgeDate()).append(')'); if (!StringUtils.isEmpty(cset.getBranch()) && !"default".equals(cset.getBranch())) { sb.append(' ').append(cset.getBranch()).append(':'); } sb.append(' ').append(cset.getSummary()); return sb.toString(); } return super.getText(element); } }); viewer.setComparator(new ViewerComparator()); viewer.setInput(new Object[] { cs }); } @Override public Object[] getSelectedItems() { return new ChangeSet[] { cs }; } /** * @see com.vectrace.MercurialEclipse.wizards.ExportPatchPage#getFileName() */ @Override protected String getFileName() { HgRoot root = cs.getHgRoot(); List projects = (root == null) ? null : MercurialTeamProvider.getKnownHgProjects(root); String sFile = cs.getChangeset().substring(0, 10) + HgPatchClient.PATCH_EXTENSION; if (projects != null) { for (IProject proj : projects) { sFile = proj.getName() + "-" + sFile; } } return sFile; } } } ExportPatchWizard.java000066400000000000000000000135551173713500500342720ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.team.ui.TeamOperation; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.LocationChooser.Location; import com.vectrace.MercurialEclipse.ui.LocationChooser.LocationType; import com.vectrace.MercurialEclipse.utils.ClipboardUtils; public class ExportPatchWizard extends HgWizard { private final ExportPatchPage sourcePage; /** * May be null */ private final ExportOptionsPage optionsPage; private final HgRoot root; private Location location; /** * True for exporting uncommitted changes. False for exporting a changeset. */ private boolean uncommittedMode; // constructors public ExportPatchWizard(List resources, HgRoot root) { this(ExportPatchPage.create(resources), new ExportOptionsPage(), root); uncommittedMode = true; } public ExportPatchWizard(ChangeSet cs) { this(ExportPatchPage.create(cs), null, cs.getHgRoot()); uncommittedMode = false; } private ExportPatchWizard(ExportPatchPage sourcePage, ExportOptionsPage optionsPage, HgRoot root) { super(Messages.getString("ExportPatchWizard.WindowTitle")); //$NON-NLS-1$ setNeedsProgressMonitor(true); this.sourcePage = sourcePage; addPage(sourcePage); initPage(Messages.getString("ExportPatchWizard.pageDescription"), //$NON-NLS-1$ sourcePage); this.optionsPage = optionsPage; if (optionsPage != null) { addPage(optionsPage); initPage(Messages.getString("ExportPatchWizard.optionsPageDescription"), //$NON-NLS-1$ optionsPage); } this.root = root; } // operations @Override public boolean performFinish() { sourcePage.finish(null); try { location = sourcePage.getLocation(); if (location.getLocationType() != LocationType.Clipboard && location.getFile().exists()) { if (!MessageDialog.openConfirm(getShell(), Messages .getString("ExportPatchWizard.OverwriteConfirmTitle"), //$NON-NLS-1$ Messages.getString("ExportPatchWizard.OverwriteConfirmDescription"))) { //$NON-NLS-1$ return false; } } ExportUncomittedOperation operation = (uncommittedMode) ? new ExportUncomittedOperation( getContainer()) : new ExportChangeSetOperation(getContainer()); operation.selectedItems = sourcePage.getSelectedItems(); operation.options = (optionsPage == null) ? null : optionsPage.getOptions(); getContainer().run(true, false, operation); if (operation.result != null) { if (optionsPage != null) { optionsPage.setErrorMessage(operation.result); } sourcePage.setErrorMessage(operation.result); return false; } } catch (Exception e) { MercurialEclipsePlugin.logError(getWindowTitle(), e); MercurialEclipsePlugin.showError(e.getCause()); return false; } return true; } // inner types private class ExportUncomittedOperation extends TeamOperation { public Object[] selectedItems; public List options; public String result; public ExportUncomittedOperation(IRunnableContext context) { super(context); } // operations public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(Messages.getString("ExportPatchWizard.pageTitle"), 1); //$NON-NLS-1$ try { doExport(); if (location.getLocationType() == LocationType.Workspace) { location.getWorkspaceFile().refreshLocal(0, null); } } catch (Exception e) { result = e.getLocalizedMessage(); MercurialEclipsePlugin.logError(Messages.getString("ExportPatchWizard.pageTitle") //$NON-NLS-1$ + " failed:", e); //$NON-NLS-1$ } finally { monitor.done(); } } protected void doExport() throws Exception { List resources = Arrays.asList((IResource[]) selectedItems); if (location.getLocationType() == LocationType.Clipboard) { String sPatch = HgPatchClient.exportPatch(root, resources, options); if (sPatch != null && sPatch.length() > 0) { ClipboardUtils.copyToClipboard(sPatch); } } else { HgPatchClient.exportPatch(root, resources, location.getFile(), options); } } } private class ExportChangeSetOperation extends ExportUncomittedOperation { public ExportChangeSetOperation(IRunnableContext context) { super(context); } /** * @see com.vectrace.MercurialEclipse.wizards.ExportPatchWizard.ExportUncomittedOperation#doExport() */ @Override protected void doExport() throws Exception { ChangeSet cs = (ChangeSet) selectedItems[0]; if (location.getLocationType() == LocationType.Clipboard) { String sPatch = HgPatchClient.exportPatch(root, cs, null); if (sPatch != null && sPatch.length() > 0) { ClipboardUtils.copyToClipboard(sPatch); } } else { HgPatchClient.exportPatch(root, cs, location.getFile(), null); } } } } HgOperationWizard.java000066400000000000000000000065121173713500500342430ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Peberdy implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.lang.reflect.InvocationTargetException; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardPage; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.exception.HgException; /** * Like {@link HgWizard} but finishes with an operation that may throw exceptions. These exceptions * are shown in a consistent way. When an exception occurs the finish is aborted. */ public abstract class HgOperationWizard extends HgWizard { public HgOperationWizard(String windowTitle) { super(windowTitle); } /** * @see com.vectrace.MercurialEclipse.wizards.HgWizard#performFinish() */ @Override public final boolean performFinish() { if (!super.performFinish()) { return false; } setErrorMessage(null); try { HgOperation operation = initOperation(); if (operation == null) { return false; } try { getContainer().run(true, false, operation); } finally { operationFinished(); } return operationSucceeded(operation); } catch (Exception e) { return operationFailed(e); } } /** * Create the operation to finish the wizard. May return null if operation is not ready. In this * case subclasses must show error. * * @return The operation to use */ protected abstract HgOperation initOperation() throws HgException; /** * The operation finished with no exception * * @return Whether the wizard should close */ @SuppressWarnings("unused") protected boolean operationSucceeded(HgOperation operation) throws HgException { return true; } /** * Template method called before {@link #operationFailed(Exception)} or * {@link #operationSucceeded(HgOperation)}. */ protected void operationFinished() { } /** * Called when an exception is thrown by the job. Shows the error to the user. * * @param e * The exception that occurred * @return Whether the wizard should close */ protected boolean operationFailed(Throwable e) { if (e instanceof InvocationTargetException) { e = ((InvocationTargetException) e).getTargetException(); } MercurialEclipsePlugin.logError(e); if (e instanceof HgException) { HgException he = (HgException) e; setErrorMessage(he.getConciseMessage()); if (he.isMultiLine()) { MercurialEclipsePlugin.showError(e); } } else if (e instanceof InterruptedException) { MercurialEclipsePlugin.logError(e); } else { setErrorMessage(e.getLocalizedMessage()); MercurialEclipsePlugin.showError(e); } return false; } protected final void setErrorMessage(String message) { for (IWizardPage curPage : getPages()) { if (curPage instanceof WizardPage) { ((WizardPage) curPage).setErrorMessage(message); } } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/HgWizard.java000066400000000000000000000037351173713500500324450ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.Properties; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.wizard.Wizard; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; /** * @author bastian */ public abstract class HgWizard extends Wizard { protected HgWizardPage page; protected Properties properties; public HgWizard(String windowTitle) { super(); init(windowTitle); } @Override public boolean performFinish() { if (page != null) { return page.finish(new NullProgressMonitor()); } return true; } /** * Initializes the wizard with data. */ private void init(String windowTitle) { IDialogSettings workbenchSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); IDialogSettings section = workbenchSettings.getSection(getClass().getCanonicalName()); if (section == null) { section = workbenchSettings.addNewSection(getClass().getCanonicalName()); } setDialogSettings(section); setWindowTitle(windowTitle); setNeedsProgressMonitor(true); } protected void initPage(String description, HgWizardPage wizardPage) { wizardPage.setDescription(description); if (properties != null) { wizardPage.setProperties(properties); } wizardPage.setDialogSettings(getDialogSettings()); } public void setProperties(Properties properties) { this.properties = properties; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/HgWizardPage.java000066400000000000000000000053131173713500500332340ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Bastian Doetsch - adaptation to hg ******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.Properties; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.wizard.WizardPage; /** * Common superclass for Hg wizard pages. Provides convenience methods for * widget creation. */ public abstract class HgWizardPage extends WizardPage { protected Properties properties; protected IDialogSettings settings; /** * HgWizardPage constructor comment. * * @param pageName * the name of the page */ public HgWizardPage(String pageName) { super(pageName); } /** * HgWizardPage constructor comment. * * @param pageName * the name of the page * @param title * the title of the page * @param titleImage * the image for the page */ public HgWizardPage(String pageName, String title, ImageDescriptor titleImage) { super(pageName, title, titleImage); } /** * HgWizardPage constructor comment. * * @param pageName * the name of the page * @param title * the title of the page * @param titleImage * the image for the page * @param description * the description of the page */ public HgWizardPage(String pageName, String title, ImageDescriptor titleImage, String description) { super(pageName, title, titleImage); setDescription(description); } @SuppressWarnings("static-method") public boolean finish(IProgressMonitor monitor) { return true; } /** * Returns the properties for the repository connection * * @return the properties or null */ public Properties getProperties() { return properties; } /** * Sets the properties for the repository connection * * @param properties * the properties or null */ public void setProperties(Properties properties) { this.properties = properties; } @Override public IDialogSettings getDialogSettings() { return settings; } public void setDialogSettings(IDialogSettings settings) { this.settings = settings; } } ImportOptionsPage.java000066400000000000000000000121421173713500500342620ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * steeven - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * Last page of import wizard for import options. */ public class ImportOptionsPage extends HgWizardPage implements Listener { private Button chkForce; private Button chkStrip; private Button chkBase; private Button chkNoCommit; private Button chkExact; private Text txtUser; private Text txtDate; private SourceViewer txtComments; private Button chkUser; private Button chkDate; private Button chkComments; private Text txtBase; private Text txtStrip; public ImportOptionsPage() { super(Messages.getString("ImportPatchWizard.optionsPageName"), Messages //$NON-NLS-1$ .getString("ImportPatchWizard.optionsPageTitle"), null); //$NON-NLS-1$ } protected boolean validatePage() { return true; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); chkForce = SWTWidgetHelper.createCheckBox(composite, Messages .getString("ImportOptionsPage.force")); //$NON-NLS-1$ chkStrip = createLabelCheckBox(composite, Messages .getString("ImportOptionsPage.strip")); //$NON-NLS-1$ chkStrip.addListener(SWT.Selection, this); txtStrip = SWTWidgetHelper.createTextField(composite); chkBase = createLabelCheckBox(composite, Messages .getString("ImportOptionsPage.base")); //$NON-NLS-1$ chkBase.addListener(SWT.Selection, this); txtBase = SWTWidgetHelper.createTextField(composite); chkNoCommit = SWTWidgetHelper.createCheckBox(composite, Messages .getString("ImportOptionsPage.noCommit")); //$NON-NLS-1$ chkNoCommit.setSelection(true); chkExact = SWTWidgetHelper.createCheckBox(composite, Messages .getString("ImportOptionsPage.exact")); //$NON-NLS-1$ chkUser = createLabelCheckBox(composite, Messages .getString("ImportOptionsPage.user")); //$NON-NLS-1$ chkUser.addListener(SWT.Selection, this); txtUser = SWTWidgetHelper.createTextField(composite); chkDate = createLabelCheckBox(composite, Messages .getString("ImportOptionsPage.date")); //$NON-NLS-1$ chkDate.addListener(SWT.Selection, this); txtDate = SWTWidgetHelper.createTextField(composite); String date = DateFormat.getDateTimeInstance().format(new Date()); txtDate.setText(date); chkComments = createLabelCheckBox(composite, Messages .getString("ImportOptionsPage.comments")); //$NON-NLS-1$ chkComments.addListener(SWT.Selection, this); txtComments = SWTWidgetHelper.createTextArea(composite); setControl(composite); validate(); } public void handleEvent(Event event) { validate(); } private void validate() { txtUser.setEnabled(chkUser.getSelection()); txtDate.setEnabled(chkDate.getSelection()); txtComments.getControl().setEnabled(chkComments.getSelection()); txtBase.setEnabled(chkBase.getSelection()); txtStrip.setEnabled(chkStrip.getSelection()); setErrorMessage(null); setPageComplete(true); } /* * (non-Javadoc) * * @see * com.vectrace.MercurialEclipse.wizards.HgWizardPage#finish(org.eclipse * .core.runtime.IProgressMonitor) */ @Override public boolean finish(IProgressMonitor monitor) { // getDialogSettings(); save setttings. return super.finish(monitor); } ArrayList getOptions() { ArrayList list = new ArrayList(); if (chkStrip.getSelection()) { list.add("-p " + txtStrip.getText()); //$NON-NLS-1$ } if (chkForce.getSelection()) { list.add("-f"); //$NON-NLS-1$ } if (chkBase.getSelection()) { list.add("-b " + txtBase.getText()); //$NON-NLS-1$ } if (chkNoCommit.getSelection()) { list.add("--no-commit"); //$NON-NLS-1$ } if (chkExact.getSelection()) { list.add("--exact"); //$NON-NLS-1$ } if (chkUser.getSelection()) { list.add("-u " + txtUser.getText()); //$NON-NLS-1$ } if (chkDate.getSelection()) { list.add("-d \"" + txtDate.getText() + '\"'); //$NON-NLS-1$ } if (chkComments.getSelection()) { list.add("-m " + txtComments.getDocument().get()); //$NON-NLS-1$ } return list; } public static Button createLabelCheckBox(Composite group, String label) { Button button = new Button(group, SWT.CHECK | SWT.LEFT); button.setText(label); return button; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/ImportPatchPage.java000066400000000000000000000057451173713500500337600ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * steeven - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.LocationChooser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.ui.LocationChooser.Location; /** * A wizard page which will allow the user to choose location to export patch. */ public class ImportPatchPage extends HgWizardPage implements Listener { private LocationChooser locationChooser; private Text txtProject; private final HgRoot hgRoot; public ImportPatchPage(HgRoot hgRoot) { super(Messages.getString("ImportPatchWizard.pageName"), Messages //$NON-NLS-1$ .getString("ImportPatchWizard.pageTitle"), null); // TODO icon //$NON-NLS-1$ this.hgRoot = hgRoot; } protected boolean validatePage() { String msg = locationChooser.validate(); if (msg == null && hgRoot == null) { msg = Messages.getString("ImportPatchPage.InvalidProject"); // possible? //$NON-NLS-1$ } if (msg == null) { setMessage(null); } setErrorMessage(msg); setPageComplete(msg == null); return msg == null; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); Group group = SWTWidgetHelper.createGroup(composite, Messages .getString("ExportPatchWizard.PathLocation"), 2, GridData.FILL_HORIZONTAL); //$NON-NLS-1$ locationChooser = new LocationChooser(group, false, getDialogSettings()); locationChooser.addStateListener(this); locationChooser.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); SWTWidgetHelper.createLabel(composite, Messages .getString("ImportPatchPage.ProjectName")); //$NON-NLS-1$ txtProject = SWTWidgetHelper.createTextField(composite); txtProject.setEditable(false); if (hgRoot != null) { txtProject.setText(hgRoot.getName()); } setControl(composite); validatePage(); } public void handleEvent(Event event) { validatePage(); } public Location getLocation() { return locationChooser.getCheckedLocation(); } @Override public boolean finish(IProgressMonitor monitor) { locationChooser.saveSettings(); return super.finish(monitor); } } ImportPatchWizard.java000066400000000000000000000054561173713500500342640ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.jface.dialogs.MessageDialog; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.dialogs.RejectsDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.ImportPatchOperation; public class ImportPatchWizard extends HgOperationWizard { private final ImportPatchPage sourcePage; private final ImportOptionsPage optionsPage; final HgRoot hgRoot; public ImportPatchWizard(HgRoot hgRoot) { super(Messages.getString("ImportPatchWizard.WizardTitle")); setNeedsProgressMonitor(true); this.hgRoot = hgRoot; sourcePage = new ImportPatchPage(hgRoot); addPage(sourcePage); initPage(Messages.getString("ImportPatchWizard.pageDescription"), sourcePage); optionsPage = new ImportOptionsPage(); addPage(optionsPage); initPage(Messages.getString("ImportPatchWizard.optionsPageDescription"), optionsPage); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#initOperation() */ @Override protected HgOperation initOperation() { sourcePage.finish(null); return new ImportPatchOperation(getContainer(), hgRoot, sourcePage.getLocation(), optionsPage.getOptions()); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#operationSucceeded(HgOperation) */ @Override protected boolean operationSucceeded(HgOperation operation) throws HgException { if (((ImportPatchOperation) operation).isConflict()) { try { new RejectsDialog(getShell(), hgRoot, operation.getResult(), "ImportPatchRejectsDialog.title", "ImportPatchRejectsDialog.conflict") .open(); } catch (HgException e) { // Fallback if couldn't parse rejects MessageDialog.openInformation(getShell(), Messages .getString("ImportPatchWizard.WizardTitle"), Messages .getString("ImportPatchWizard.conflict") + "\n" + operation.getResult()); MercurialEclipsePlugin.logError(e); } } return super.operationSucceeded(operation); } } ImportProjectsFromRepoWizard.java000066400000000000000000000047261173713500500364670ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.IOException; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IImportWizard; import org.eclipse.ui.INewWizard; import org.eclipse.ui.IWorkbench; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgPath; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * This class implements the import wizard extension and the new wizard * extension. */ public class ImportProjectsFromRepoWizard extends HgWizard implements IImportWizard, INewWizard { private ProjectsImportPage importPage; private HgPath initialLocation; public ImportProjectsFromRepoWizard() { super("Import Projects from Mercurial repository"); } @Override public boolean performFinish() { return importPage.createProjects(); } public void init(IWorkbench workbench, IStructuredSelection selection) { setWindowTitle("Import Projects from Mercurial repository"); setNeedsProgressMonitor(true); if(!selection.isEmpty()){ Object firstElement = selection.getFirstElement(); HgPath path = MercurialEclipsePlugin.getAdapter(firstElement, HgPath.class); if(path != null){ setInitialData(path); } else { IResource resource = MercurialEclipsePlugin.getAdapter(firstElement, IResource.class); if(resource != null) { IPath iPath = ResourceUtils.getPath(resource); if(iPath != null && !iPath.isEmpty()) { try { setInitialData(new HgPath(iPath.toOSString())); } catch (IOException e) { MercurialEclipsePlugin.logError(e); } } } } } importPage = new ProjectsImportPage("ProjectsImportPage"); importPage.setDestinationSelectionEnabled(true); addPage(importPage); } public void setInitialData(HgPath path) { initialLocation = path; } public HgPath getInitialPath() { return initialLocation; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/IncomingPage.java000066400000000000000000000276731173713500500332750ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.FileNotFoundException; import java.lang.reflect.InvocationTargetException; import java.util.Collections; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.PlatformUI; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.history.SimpleLabelImageProvider; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.model.ChangeSet.ParentChangeSet; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.NullRevision; import com.vectrace.MercurialEclipse.team.cache.IncomingChangesetCache; import com.vectrace.MercurialEclipse.ui.ChangeSetLabelProvider; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.CompareUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; public class IncomingPage extends HgWizardPage { private TableViewer changeSetViewer; private TableViewer fileStatusViewer; private HgRoot hgRoot; private IHgRepositoryLocation location; protected Button revisionCheckBox; private ChangeSet revision; private SortedSet changesets; private boolean svn; private boolean force; private class GetIncomingOperation extends HgOperation { public GetIncomingOperation(IRunnableContext context) { super(context); } @Override protected String getActionDescription() { return Messages.getString("IncomingPage.getIncomingOperation.description"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(Messages.getString("IncomingPage.getIncomingOperation.beginTask"), 1); //$NON-NLS-1$ monitor.subTask(Messages.getString("IncomingPage.getIncomingOperation.call")); //$NON-NLS-1$ changesets = getIncomingInternal(); monitor.worked(1); monitor.done(); } private SortedSet getIncomingInternal() { if (isSvn()) { return new TreeSet(); } IncomingChangesetCache cache = IncomingChangesetCache.getInstance(); try { cache.clear(hgRoot, false); Set set = cache.getChangeSets(hgRoot, location, null, isForce()); SortedSet revertedSet = new TreeSet(Collections.reverseOrder()); revertedSet.addAll(set); return revertedSet; } catch (HgException e) { MercurialEclipsePlugin.showError(e); return new TreeSet(); } } } protected class IncomingDoubleClickListener implements IDoubleClickListener { public void doubleClick(DoubleClickEvent event) { ChangeSet cs = getSelectedChangeSet(); IStructuredSelection sel = (IStructuredSelection) event.getSelection(); FileStatus clickedFileStatus = (FileStatus) sel.getFirstElement(); if (cs != null && clickedFileStatus != null) { IPath fileAbsPath = hgRoot.toAbsolute(clickedFileStatus.getRootRelativePath()); IFile file = ResourceUtils.getFileHandle(fileAbsPath); if (file != null) { MercurialRevisionStorage remoteRev = new MercurialRevisionStorage( file, cs.getChangesetIndex(), cs.getChangeset(), cs); MercurialRevisionStorage parentRev; String[] parents = cs.getParents(); if(cs.getRevision().getRevision() == 0 || parents.length == 0){ parentRev = new NullRevision(file, cs); } else { String parentId = parents[0]; ChangeSet parentCs = null; for (ChangeSet cset : changesets) { if(parentId.endsWith(cset.getChangeset()) && parentId.startsWith("" + cset.getChangesetIndex())){ parentCs = cset; break; } } if(parentCs == null) { parentCs = new ParentChangeSet(parentId, cs); } if(clickedFileStatus.isCopied()){ IPath fileCopySrcPath = hgRoot.toAbsolute(clickedFileStatus.getRootRelativeCopySourcePath()); IFile copySrc = ResourceUtils.getFileHandle(fileCopySrcPath); parentRev = new MercurialRevisionStorage( copySrc, parentCs.getChangesetIndex(), parentCs.getChangeset(), parentCs); }else{ parentRev = new MercurialRevisionStorage( file, parentCs.getChangesetIndex(), parentCs.getChangeset(), parentCs); } } CompareUtils.openEditor(remoteRev, parentRev, true); // the line below compares the remote changeset with the local copy. // it was replaced with the code above to fix the issue 10364 // CompareUtils.openEditor(file, cs, true, true); } else { // It is possible that file has been removed or part of the // repository but not the project (and has incoming changes) MercurialEclipsePlugin.showError(new FileNotFoundException(Messages.getString("IncomingPage.compare.file.missing"))); } } } } protected IncomingPage(String pageName) { super(pageName); setTitle(Messages.getString("IncomingPage.title")); //$NON-NLS-1$ setDescription(Messages.getString("IncomingPage.description")); //$NON-NLS-1$ } public IHgRepositoryLocation getLocation() { return location; } public void setRevision(ChangeSet revision) { this.revision = revision; } public void setChangesets(SortedSet changesets) { this.changesets = changesets; } @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { try { getInputForPage(); changeSetViewer.setInput(changesets); } catch (InvocationTargetException e) { MercurialEclipsePlugin.logError(e); setErrorMessage(e.getLocalizedMessage()); } catch (InterruptedException e) { MercurialEclipsePlugin.logError(e); setErrorMessage(e.getLocalizedMessage()); } } } protected void getInputForPage() throws InvocationTargetException, InterruptedException { getContainer().run(true, false, new GetIncomingOperation(getContainer())); } public void createControl(Composite parent) { Composite container = SWTWidgetHelper.createComposite(parent, 1); setControl(container); changeSetViewer = new TableViewer(container, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL); changeSetViewer.setContentProvider(new ArrayContentProvider()); changeSetViewer.setLabelProvider(new ChangeSetLabelProvider()); Table table = changeSetViewer.getTable(); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 150; gridData.minimumHeight = 50; table.setLayoutData(gridData); table.setHeaderVisible(true); table.setLinesVisible(true); String[] titles = { Messages.getString("IncomingPage.columnHeader.revision"), //$NON-NLS-1$ Messages.getString("IncomingPage.columnHeader.global"), //$NON-NLS-1$ Messages.getString("IncomingPage.columnHeader.date"), //$NON-NLS-1$ Messages.getString("IncomingPage.columnHeader.author"), //$NON-NLS-1$ Messages.getString("IncomingPage.columnHeader.branch"), //$NON-NLS-1$ "Tags", //$NON-NLS-1$ Messages.getString("IncomingPage.columnHeader.summary") }; //$NON-NLS-1$ final int width = 11; int[] widths = {6 * width, 7 * width, 15 * width, 14 * width, 5 * width, 5 * width, 30 * width}; for (int i = 0; i < titles.length; i++) { TableColumn column = new TableColumn(table, SWT.NONE); column.setText(titles[i]); column.setWidth(widths[i]); } fileStatusViewer = new TableViewer(container, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL); fileStatusViewer.setContentProvider(new ArrayContentProvider()); fileStatusViewer.setLabelProvider(new FileStatusLabelProvider()); table = fileStatusViewer.getTable(); gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 150; gridData.minimumHeight = 50; table.setLayoutData(gridData); table.setHeaderVisible(false); table.setLinesVisible(true); Group group = SWTWidgetHelper.createGroup(container, Messages .getString("IncomingPage.group.title")); //$NON-NLS-1$ revisionCheckBox = SWTWidgetHelper.createCheckBox(group, Messages .getString("IncomingPage.revisionCheckBox.title")); //$NON-NLS-1$ makeActions(); } ChangeSet getSelectedChangeSet() { IStructuredSelection sel = (IStructuredSelection) changeSetViewer .getSelection(); Object firstElement = sel.getFirstElement(); if (firstElement instanceof ChangeSet) { return (ChangeSet) firstElement; } return null; } private void makeActions() { changeSetViewer .addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { ChangeSet change = getSelectedChangeSet(); revision = change; if (change != null) { fileStatusViewer.setInput(change.getChangedFiles()); } else { fileStatusViewer.setInput(new Object[0]); } } }); fileStatusViewer.addDoubleClickListener(getDoubleClickListener()); } private static final class FileStatusLabelProvider extends DecoratingLabelProvider implements ITableLabelProvider { public FileStatusLabelProvider() { super(new SimpleLabelImageProvider(), PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()); } public Image getColumnImage(Object element, int columnIndex) { if (!(element instanceof FileStatus)) { return null; } return getImage(element); } public String getColumnText(Object element, int columnIndex) { if (!(element instanceof FileStatus)) { return null; } return getText(element); } } public void setHgRoot(HgRoot hgRoot) { this.hgRoot = hgRoot; } public HgRoot getHgRoot() { return hgRoot; } public void setLocation(IHgRepositoryLocation repo) { this.location = repo; } public boolean isRevisionSelected() { return revisionCheckBox.getSelection(); } public ChangeSet getRevision() { return revision; } public SortedSet getChangesets() { return changesets; } public void setSvn(boolean svn) { this.svn = svn; } public boolean isSvn() { return svn; } public void setForce(boolean force) { this.force = force; } public boolean isForce() { return force; } protected IDoubleClickListener getDoubleClickListener() { return new IncomingDoubleClickListener(); } } MercurialParticipantSynchronizeWizard.java000066400000000000000000000312221173713500500403760ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.mapping.ResourceMapping; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.IWizard; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.swt.widgets.Display; import org.eclipse.team.core.TeamException; import org.eclipse.team.ui.TeamUI; import org.eclipse.team.ui.synchronize.ISynchronizeParticipant; import org.eclipse.team.ui.synchronize.ISynchronizeParticipantReference; import org.eclipse.team.ui.synchronize.ParticipantSynchronizeWizard; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchWizard; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.synchronize.HgSubscriberMergeContext; import com.vectrace.MercurialEclipse.synchronize.HgSubscriberScopeManager; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeParticipant; import com.vectrace.MercurialEclipse.synchronize.MercurialSynchronizeSubscriber; import com.vectrace.MercurialEclipse.synchronize.RepositorySynchronizationScope; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author bastian * */ public class MercurialParticipantSynchronizeWizard extends ParticipantSynchronizeWizard implements IWorkbenchWizard { private static final String SECTION_NAME = "MercurialParticipantSynchronizeWizard"; private final IWizard importWizard; private ConfigurationWizardMainPage repoPage; private SelectProjectsToSyncPage selectionPage; private IProject [] projects; private MercurialSynchronizeParticipant createdParticipant; public MercurialParticipantSynchronizeWizard() { projects = new IProject[0]; importWizard = new CloneRepoWizard(); IDialogSettings workbenchSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); IDialogSettings section = workbenchSettings.getSection(SECTION_NAME); if (section == null) { section = workbenchSettings.addNewSection(SECTION_NAME); } setDialogSettings(section); } @Override protected IWizard getImportWizard() { return importWizard; } @Override protected String getPageTitle() { return Messages.getString("MercurialParticipantSynchronizeWizard.pageTitle"); //$NON-NLS-1$ } /** * @return a list of selected managed projects, or all managed projects, if there was * no selection. Never returns null, but can return empty list * {@inheritDoc} */ @Override protected IProject[] getRootResources() { return selectionPage != null && selectionPage.isCreated()? selectionPage.getSelectedProjects() : getInitialSelection(); } protected IProject[] getInitialSelection() { return projects; } @Override public void addPages() { // creates selection page, but only if there is something selected. // the point is, that the sync view starts the wizard with ZERO selection and // expects that the first page is somehow created (and it is created by the super class // but only if the getRootResources() returns something). // so in order to support it, we init the selection to ALL projects... if(getInitialSelection().length == 0){ projects = MercurialTeamProvider.getKnownHgProjects().toArray(new IProject[0]); } repoPage = createrepositoryConfigPage(); super.addPages(); addPage(repoPage); } @Override public IWizardPage getStartingPage() { return selectionPage; } private ConfigurationWizardMainPage createrepositoryConfigPage() { ConfigurationWizardMainPage mainPage = new ConfigurationWizardMainPage( Messages.getString("MercurialParticipantSynchronizeWizard.repositoryPage.name"), //$NON-NLS-1$ Messages.getString("MercurialParticipantSynchronizeWizard.repositoryPage.title"), MercurialEclipsePlugin.getImageDescriptor(Messages .getString("MercurialParticipantSynchronizeWizard.repositoryPage.image"))); //$NON-NLS-1$ mainPage.setShowBundleButton(false); mainPage.setShowCredentials(true); mainPage.setDescription(Messages .getString("MercurialParticipantSynchronizeWizard.repositoryPage.description")); //$NON-NLS-1$ mainPage.setDialogSettings(getDialogSettings()); if(projects != null && projects.length > 0){ Map> byRoot = ResourceUtils.groupByRoot(Arrays.asList(projects)); if(byRoot.size() == 1){ mainPage.setHgRoot(byRoot.keySet().iterator().next()); } } return mainPage; } /** * @return properties object if all information needed to synchronize is available, * null if some settings are missing */ public Properties prepareSettings() { IResource[] resources = getRootResources(); Map> byRoot = ResourceUtils.groupByRoot(Arrays.asList(resources)); Set roots = byRoot.keySet(); if(roots.size() == 1){ Properties pageProperties = initProperties(roots.iterator().next()); if(isValid(pageProperties, ConfigurationWizardMainPage.PROP_URL)) { if (isValid(pageProperties, ConfigurationWizardMainPage.PROP_USER)) { if (isValid(pageProperties, ConfigurationWizardMainPage.PROP_PASSWORD)) { return pageProperties; } } else { return pageProperties; } } } return null; } private static boolean isValid(Properties pageProperties, String key){ String value = pageProperties.getProperty(key); return value != null && value.trim().length() > 0; } /** * @param hgRoot non null * @return non null proeprties with possible repository data initialized from given * root (may be empty) */ static Properties initProperties(HgRoot hgRoot) { IHgRepositoryLocation repoLocation = MercurialEclipsePlugin.getRepoManager() .getDefaultRepoLocation(hgRoot); Properties properties = new Properties(); if(repoLocation != null){ if(repoLocation.getLocation() != null) { properties.setProperty(ConfigurationWizardMainPage.PROP_URL, repoLocation.getLocation()); if(repoLocation.getUser() != null) { properties.setProperty(ConfigurationWizardMainPage.PROP_USER, repoLocation.getUser()); if(repoLocation.getPassword() != null) { properties.setProperty(ConfigurationWizardMainPage.PROP_PASSWORD, repoLocation.getPassword()); } } } } return properties; } @Override public boolean performFinish() { boolean performFinish = true; if(repoPage != null) { repoPage.finish(new NullProgressMonitor()); performFinish = super.performFinish(); } else { // UI was not created, so we just need to continue with synchronization Properties properties = prepareSettings(); if(properties != null) { createdParticipant = createParticipant(properties, getInitialSelection()); } else { performFinish = false; } } if(performFinish && createdParticipant != null) { openSyncView(createdParticipant); } return performFinish; } public static void openSyncView(MercurialSynchronizeParticipant participant) { TeamUI.getSynchronizeManager().addSynchronizeParticipants( new ISynchronizeParticipant[] { participant }); // We don't know in which site to show progress because a participant could actually be // shown in multiple sites. participant.run(null /* no site */); } protected MercurialSynchronizeParticipant createParticipant(Properties properties, IProject[] selectedProjects) { String url = properties.getProperty(ConfigurationWizardMainPage.PROP_URL); String user = properties.getProperty(ConfigurationWizardMainPage.PROP_USER); String pass = properties.getProperty(ConfigurationWizardMainPage.PROP_PASSWORD); HgRepositoryLocationManager repoManager = MercurialEclipsePlugin.getRepoManager(); Map> byRoot = ResourceUtils.groupByRoot(Arrays.asList(selectedProjects)); Set roots = byRoot.keySet(); // XXX what if there are zero or more then one root??? if(roots.size() != 1){ MercurialEclipsePlugin.logWarning("Unexpected number of roots (must be 1): ", new Exception( roots.size() + " hg roots")); } HgRoot hgRoot = roots.iterator().next(); IHgRepositoryLocation repo; try { repo = repoManager.getRepoLocation(url, user, pass); if(pass != null && user != null){ if(!pass.equals(repo.getPassword())){ // At least 1 project exists, update location for that project repo = repoManager.updateRepoLocation(hgRoot, url, null, user, pass); } } } catch (HgException e) { MercurialEclipsePlugin.logError(e); repoPage.setErrorMessage(e.getLocalizedMessage()); return null; } try { repoManager.addRepoLocation(hgRoot, repo); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); } return createParticipant(repo, selectedProjects); } public static MercurialSynchronizeParticipant createParticipant(IHgRepositoryLocation repo, IProject[] selectedProjects) { ISynchronizeParticipantReference participant = TeamUI.getSynchronizeManager().get( MercurialSynchronizeParticipant.class.getName(), repo.getLocation()); // do not reuse participants which may already existing, but dispose them // not doing this would lead to the state where many sync. participants would listen // to resource changes and update/request same data/cashes many times // we can not reuse participants because their scope can be different (if there are // more then one project under same repository) if(participant != null){ try { ISynchronizeParticipant participant2 = participant.getParticipant(); TeamUI.getSynchronizeManager().removeSynchronizeParticipants(new ISynchronizeParticipant[]{participant2}); while(Display.getCurrent().readAndDispatch()){ // give Team UI a chance to dispose the sync page, if any } } catch (TeamException e) { MercurialEclipsePlugin.logError(e); } } // Create a new participant for given repo/project pair RepositorySynchronizationScope scope = new RepositorySynchronizationScope(repo, selectedProjects); MercurialSynchronizeSubscriber subscriber = new MercurialSynchronizeSubscriber(scope); ResourceMapping[] selectedMappings = new ResourceMapping[selectedProjects.length]; for (int i = 0; i < selectedProjects.length; i++) { selectedMappings[i] = (ResourceMapping) selectedProjects[i].getAdapter(ResourceMapping.class); } HgSubscriberScopeManager manager = new HgSubscriberScopeManager(selectedMappings, subscriber); HgSubscriberMergeContext ctx = new HgSubscriberMergeContext(subscriber, manager); MercurialSynchronizeParticipant participant2 = new MercurialSynchronizeParticipant(ctx, repo, scope); subscriber.setParticipant(participant2); return participant2; } public void init(IWorkbench workbench, IStructuredSelection selection) { if(selection != null && !selection.isEmpty()){ Object[] array = selection.toArray(); Set roots = new HashSet(); List managed = MercurialTeamProvider.getKnownHgProjects(); for (Object object : array) { IResource iResource = ResourceUtils.getResource(object); if(iResource instanceof IProject){ IProject another = (IProject) iResource; for (IProject project : managed) { if(project.equals(another)) { // add project as a root of resource roots.add(project); } } if(roots.isEmpty()) { roots.add((IProject) iResource); } } } projects = roots.toArray(new IProject[roots.size()]); } } @Override protected void createParticipant() { createdParticipant = createParticipant(repoPage.getProperties(), selectionPage.getSelectedProjects()); } @Override protected SelectProjectsToSyncPage createScopeSelectionPage() { selectionPage = new SelectProjectsToSyncPage(getRootResources()); return selectionPage; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/Messages.java000066400000000000000000000022121173713500500324620ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Balm Consulting Inc (Peter Hunnisett ) - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.MissingResourceException; import java.util.ResourceBundle; public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.wizards.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } NewLocationWizard.java000066400000000000000000000074371173713500500342550ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2003, 2006 Subclipse project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subclipse project committers - initial API and implementation * Andrei Loskutov - bug fixes ******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.util.Properties; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.INewWizard; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PartInitException; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgInitClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgPath; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.repository.RepositoriesView; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; /** * Wizard to add a new location. Uses ConfigurationWizardMainPage for entering * informations about Hg repository location */ public class NewLocationWizard extends HgWizard implements INewWizard { private IHgRepositoryLocation repository; public NewLocationWizard() { super(Messages.getString("NewLocationWizard.name")); //$NON-NLS-1$ } @Override public void addPages() { page = createPage(Messages.getString("NewLocationWizard.repoCreationPage.description")); //$NON-NLS-1$ addPage(page); } /** * @see IWizard#performFinish */ @Override public boolean performFinish() { super.performFinish(); CreateRepoPage createRepoPage = (CreateRepoPage) page; File localRepo = createRepoPage.getLocalRepo(); if(localRepo != null && !HgPath.isHgRoot(localRepo) && createRepoPage.shouldInitRepo()){ try { HgInitClient.init(localRepo); } catch (HgException e) { MercurialEclipsePlugin.logError(e); page.setErrorMessage(e.getMessage()); return false; } } Properties props = page.getProperties(); HgRepositoryLocationManager manager = MercurialEclipsePlugin.getRepoManager(); try { repository = manager.createRepository(props); } catch (HgException ex) { MercurialEclipsePlugin.logError(ex); return false; } try { RepositoriesView view = getRepoView(); view.refreshViewer(repository, true); } catch (PartInitException e) { MercurialEclipsePlugin.logError(e); } if (createRepoPage.shouldInitRepo() && !repository.isLocal() && repository.getLocation().startsWith("ssh:")) { boolean confirm = MessageDialog.openConfirm(getShell(), "Hg init", "Do you really want to run hg init on remote server?"); if(!confirm){ return true; } try { HgInitClient.init(repository); } catch (HgException e) { MercurialEclipsePlugin.logError(e); page.setErrorMessage(e.getMessage()); return false; } } return true; } private RepositoriesView getRepoView() throws PartInitException { IWorkbenchPage activePage = MercurialEclipsePlugin.getActivePage(); return (RepositoriesView) activePage.showView(RepositoriesView.VIEW_ID); } /** * Creates a ConfigurationWizardPage. */ protected HgWizardPage createPage(String description) { page = new CreateRepoPage(); initPage(description, page); return page; } public IHgRepositoryLocation getRepository() { return repository; } public void init(IWorkbench workbench, IStructuredSelection selection) { // noop } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/OutgoingPage.java000066400000000000000000000151071173713500500333120ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian - implementation * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.FileNotFoundException; import java.lang.reflect.InvocationTargetException; import java.util.Collections; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Composite; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.FileStatus; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.team.MercurialRevisionStorage; import com.vectrace.MercurialEclipse.team.NullRevision; import com.vectrace.MercurialEclipse.team.cache.OutgoingChangesetCache; import com.vectrace.MercurialEclipse.utils.CompareUtils; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * @author bastian */ public class OutgoingPage extends IncomingPage { private boolean svn; private class GetOutgoingOperation extends HgOperation { public GetOutgoingOperation(IRunnableContext context) { super(context); } @Override protected String getActionDescription() { return Messages.getString("OutgoingPage.getOutgoingOperation.description"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(Messages.getString("OutgoingPage.getOutgoingOperation.beginTask"), 1); //$NON-NLS-1$ monitor.subTask(Messages.getString("OutgoingPage.getOutgoingOperation.call")); //$NON-NLS-1$ setChangesets(getOutgoingInternal()); monitor.worked(1); monitor.done(); } private SortedSet getOutgoingInternal() { if (isSvn()) { return new TreeSet(); } IHgRepositoryLocation remote = getLocation(); try { Set changesets = OutgoingChangesetCache.getInstance().getChangeSets( getHgRoot(), remote, null, isForce()); SortedSet revertedSet = new TreeSet(Collections.reverseOrder()); revertedSet.addAll(changesets); return revertedSet; } catch (HgException e) { MercurialEclipsePlugin.showError(e); return new TreeSet(); } } } protected class OutgoingDoubleClickListener implements IDoubleClickListener { public void doubleClick(DoubleClickEvent event) { ChangeSet cs = getSelectedChangeSet(); IStructuredSelection sel = (IStructuredSelection) event.getSelection(); FileStatus clickedFileStatus = (FileStatus) sel.getFirstElement(); if (cs == null || clickedFileStatus == null) { return; } IPath hgRoot = new Path(cs.getHgRoot().getPath()); IPath fileRelPath = clickedFileStatus.getRootRelativePath(); IPath fileAbsPath = hgRoot.append(fileRelPath); IFile file = ResourceUtils.getFileHandle(fileAbsPath); if (file != null) { // See issue #10249: Push/Pull diff problem on outgoing/incoming stage // This doesn't work here (seems to work only for incoming? or should be fixed there too?) // CompareUtils.openEditor(file, cs, true, true); MercurialRevisionStorage thisRev = new MercurialRevisionStorage(file, cs.getChangeset()); MercurialRevisionStorage parentRev; String[] parents = cs.getParents(); if(parents.length == 0){ // TODO for some reason, we do not always have right parent info in the changesets // if we are on the different branch then the changeset. So simply enforce the parents resolving try { parents = HgParentClient.getParentNodeIds(file, cs); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } if(cs.getRevision().getRevision() == 0 || parents.length == 0){ parentRev = new NullRevision(file, cs); } else if(clickedFileStatus.isCopied()){ IPath fileCopySrcPath = cs.getHgRoot().toAbsolute(clickedFileStatus.getRootRelativeCopySourcePath()); IFile copySrc = ResourceUtils.getFileHandle(fileCopySrcPath); parentRev = new MercurialRevisionStorage(copySrc, parents[0]); }else{ parentRev = new MercurialRevisionStorage(file, parents[0]); } CompareUtils.openEditor(thisRev, parentRev, true); } else { // It is possible that file has been removed or part of the // repository but not the project (and has incoming changes) MercurialEclipsePlugin.showError(new FileNotFoundException(Messages.getString("IncomingPage.compare.file.missing"))); } } } protected OutgoingPage(String pageName) { super(pageName); setTitle(Messages.getString("OutgoingPage.title")); //$NON-NLS-1$ setDescription(Messages.getString("OutgoingPage.description1")); //$NON-NLS-1$ } @Override public void setChangesets(SortedSet outgoingInternal) { super.setChangesets(outgoingInternal); } @Override public SortedSet getChangesets() { return super.getChangesets(); } @Override protected void getInputForPage() throws InvocationTargetException, InterruptedException { getContainer().run(true, false, new GetOutgoingOperation(getContainer())); } @Override public void createControl(Composite parent) { super.createControl(parent); revisionCheckBox.setText(Messages.getString("OutgoingPage.option.pushUpTo")); //$NON-NLS-1$ } @Override public boolean isSvn() { return svn; } @Override public void setSvn(boolean svn) { this.svn = svn; } @Override protected IDoubleClickListener getDoubleClickListener() { return new OutgoingDoubleClickListener(); } } ProjectsImportPage.java000066400000000000000000001106231173713500500344230ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2004, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Red Hat, Inc - extensive changes to allow importing of Archive Files * Philippe Ombredanne (pombredanne@nexb.com) * - Bug 101180 [Import/Export] Import Existing Project into Workspace default widget is back button , should be text field * Martin Oberhuber (martin.oberhuber@windriver.com) * - Bug 187318[Wizards] "Import Existing Project" loops forever with cyclic symbolic links * Remy Chi Jian Suen (remy.suen@gmail.com) * - Bug 210568 [Import/Export] [Import/Export] - Refresh button does not update list of projects * Andrei Loskutov - bug fixes * - Stripped down all what we do not need in Mercurial *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.IWizard; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.dialogs.IOverwriteQuery; import org.eclipse.ui.dialogs.WorkingSetGroup; import org.eclipse.ui.statushandlers.StatusManager; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * The ProjectsImportPage is the page that allows the user to import * projects from a particular location. * * see org.eclipse.ui.internal.wizards.datatransfer.WizardProjectsImportPage */ public class ProjectsImportPage extends WizardPage implements IOverwriteQuery { private static final String DESCRIPTION = "Select projects to import into the workspace. " + "Checked projects will be imported. Double click on project to change project name."; /** * The name of the folder containing metadata information for the workspace. */ public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$ /** * Enable the possibility of checking both main project and * subprojects. If that property is false the main project * and the subproject are mutually exclusive. * Very untested feature!. * TODO: Set to true and test so that if there is a .project in root * there is still the option of importing sub-projects (with the * constraint that ancestors can't both be imported(?)) */ private static final boolean ENABLE_NESTED_CHECK = false; private final class ProjectLabelProvider extends LabelProvider implements IColorProvider { @Override public String getText(Object element) { return ((ProjectRecord) element).getProjectLabel(); } public Color getBackground(Object element) { return null; } public Color getForeground(Object element) { ProjectRecord projectRecord = (ProjectRecord) element; if(projectRecord.hasConflicts) { return getShell().getDisplay().getSystemColor(SWT.COLOR_GRAY); } return null; } } /** * The project name is initialized the first available of: * - The name in the project file * - The name of the last segment of the path * - The name of the project file with integers appended. */ private static class ProjectRecord { private final File projectSystemFile; final IProjectDescription description; String projectName; String fallbackProjectName; boolean hasConflicts; /** * Create a record for a project based on the info in the file. * * @param file */ ProjectRecord(File file, ProjectNameScope scope) { projectSystemFile = file; description = createDescription(); projectName = scope.getAvailableName(description.getName(), fallbackProjectName); } /** * Creates project description based on the projectFile. * @return never null */ private IProjectDescription createDescription() { IProjectDescription tmpDescription; // If we don't have the project name try again IWorkspace workspace = ResourcesPlugin.getWorkspace(); if (projectSystemFile.isDirectory()) { fallbackProjectName = projectSystemFile.getName(); tmpDescription = workspace.newProjectDescription(fallbackProjectName); // check if the directory matches the default location? // if yes, should NOT set location, as in the "else" branch below File wsRoot = workspace.getRoot().getLocation().toFile(); if(!wsRoot.equals(projectSystemFile) && !wsRoot.equals(projectSystemFile.getParentFile())) { tmpDescription.setLocation(new Path(projectSystemFile.getAbsolutePath())); } } else { IPath path = new Path(projectSystemFile.getPath()); fallbackProjectName = path.segment(path.segmentCount() - 2); try { tmpDescription = workspace.loadProjectDescription(path); if (isDefaultLocation(path)){ // for some strange reasons (bug?) Eclipse disallows to create // projects inside the workspace IF the project description has // a location attribute set... tmpDescription.setLocation(null); } } catch (CoreException e) { // no good, couldn't load tmpDescription = workspace.newProjectDescription(fallbackProjectName); } } return tmpDescription; } /** * Returns whether the given project description file path is in the * default location for a project * * @param path * The path to examine * @return Whether the given path is the default location for a project */ private static boolean isDefaultLocation(IPath path) { // The project description file must at least be within the project, // which is within the workspace location if (path.segmentCount() < 2) { return false; } return path.removeLastSegments(2).toFile().equals( Platform.getLocation().toFile()); } /** * Get the name of the project * * @return String */ public String getProjectName() { return projectName; } public File getDataDir(){ return projectSystemFile.isDirectory() ? projectSystemFile : projectSystemFile.getParentFile(); } /** * Gets the label to be used when rendering this project record in the * UI. * * @return String the label */ public String getProjectLabel() { String path = projectSystemFile.isDirectory() ? projectSystemFile.getAbsolutePath() : projectSystemFile.getParent(); return projectName + " (" + path + ")"; } } private CheckboxTreeViewer projectsList; private ProjectRecord[] selectedProjects; private IProject[] wsProjects; // The last selected path to minimize searches private String lastPath; // The last time that the file or folder at the selected path was modified // to mimize searches private long lastModified; private WorkingSetGroup workingSetGroup; private List createdProjects; /** initial repo path */ private File repositoryRoot; /** cloned repo destination path */ private File destinationDir; private Text destinationDirText; private boolean destinationSelectionEnabled; /** * Creates a new project creation wizard page. */ public ProjectsImportPage(String pageName) { super(pageName); selectedProjects = new ProjectRecord[0]; setPageComplete(false); setTitle("Import Projects"); setDescription(DESCRIPTION); } public void setDestinationSelectionEnabled(boolean enabled){ this.destinationSelectionEnabled = enabled; } private boolean isMainProjectActive(){ /* The main project element could be used if and only if * 1) tryToUseMainProject is set * and * 2) no destination selection is enabled: * the main project is available just when cloning the remote repository; * otherwise is possible create a project with a nested project in his root, * in these cases the behavior is unpredictable and undocumented. * or * 3) There is just one project: the main project */ return !this.destinationSelectionEnabled || selectedProjects.length < 2; } public void createControl(Composite parent) { initializeDialogUnits(parent); Composite workArea = new Composite(parent, SWT.NONE); setControl(workArea); workArea.setLayout(new GridLayout()); workArea.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL)); if(destinationSelectionEnabled) { createRootSelection(workArea); } createProjectsList(workArea); createWorkingSetGroup(workArea); restoreWidgetValues(); Dialog.applyDialogFont(workArea); } private void createRootSelection(Composite workArea) { Composite selectComposite = new Composite(workArea, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 3; layout.marginWidth = 0; layout.makeColumnsEqualWidth = false; selectComposite.setLayout(layout); // GridData GridData data = new GridData(GridData.FILL_HORIZONTAL); selectComposite.setLayoutData(data); SWTWidgetHelper.createLabel(selectComposite, "Root directory:"); destinationDirText = SWTWidgetHelper.createTextField(selectComposite); Button browseButton = SWTWidgetHelper.createPushButton(selectComposite, "Browse...", 1); browseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { String dir; if (destinationDir != null && !destinationDirText.getText().equals(destinationDir.getAbsolutePath())) { dir = destinationDirText.getText(); } else { DirectoryDialog dialog = new DirectoryDialog(getShell()); dialog.setFilterPath(destinationDirText.getText()); dialog.setMessage("Select root directory"); dir = dialog.open(); } if (dir != null) { dir = dir.trim(); setInitialSelection(new File(dir)); } } }); } private void fixFinishState(){ setPageComplete(projectsList.getCheckedElements().length > 0); } private void createWorkingSetGroup(Composite workArea) { String[] workingSetIds = new String[] {"org.eclipse.ui.resourceWorkingSetPage", //$NON-NLS-1$ "org.eclipse.jdt.ui.JavaWorkingSetPage"}; //$NON-NLS-1$ workingSetGroup = new WorkingSetGroup(workArea, null, workingSetIds); } /** * Create the checkbox list for the found projects. */ private void createProjectsList(Composite workArea) { Group listComposite = new Group(workArea, SWT.NONE); listComposite.setText("Projects"); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginWidth = 0; layout.makeColumnsEqualWidth = false; listComposite.setLayout(layout); listComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH)); projectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); gridData.widthHint = convertWidthInCharsToPixels(25); gridData.heightHint = convertHeightInCharsToPixels(10); projectsList.getControl().setLayoutData(gridData); projectsList.setContentProvider(new ITreeContentProvider() { public Object[] getChildren(Object parentElement) { if (hasChildren(parentElement)){ return getSubProjectRecords(); } return null; } public Object[] getElements(Object inputElement) { if (selectedProjects.length == 0){ return new Object[0]; } if (isMainProjectActive()){ Object[] root = new Object[1]; root[0] = selectedProjects[0]; return root; } return getSubProjectRecords(); } public boolean hasChildren(Object element) { return isMainProjectActive() && (element == selectedProjects[0]) && (selectedProjects.length > 1); } public Object getParent(Object element) { return (isMainProjectActive() && (element != selectedProjects[0]))?selectedProjects[0]:null; } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); final ProjectLabelProvider labelProvider = new ProjectLabelProvider(); projectsList.setLabelProvider(labelProvider); projectsList.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { ProjectRecord element = (ProjectRecord) event.getElement(); if (!element.hasConflicts && event.getChecked()){ enableProject(element); }else{ disableProject(element); } } }); projectsList.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); Object element = selection.getFirstElement(); if(!(element instanceof ProjectRecord)){ return; } final ProjectRecord record = (ProjectRecord) element; IInputValidator validator = new IInputValidator() { public String isValid(String newText) { ProjectRecord[] projects = selectedProjects; for (ProjectRecord pr : projects) { if(pr != record && pr.projectName.equals(newText)){ return "A project with same name already exists"; } } if(isProjectInWorkspace(newText)){ return "A project with same name already exists"; } if (newText.length() == 0) { return "Project name cannot be empty"; } return null; } }; InputDialog input = new InputDialog(getShell(), "Clone repository", "Change project name for imported project", record.projectName, validator); int ok = input.open(); if(ok == Window.OK){ record.projectName = input.getValue(); record.hasConflicts = isProjectInWorkspace(record.projectName); } validateSelectedProjects(); if (!record.hasConflicts){ enableProject(record); }else{ disableProject(record); } fixFinishState(); projectsList.refresh(true); } }); projectsList.setInput(this); projectsList.setComparator(new ViewerComparator()); createSelectionButtons(listComposite); } /** * Create the selection buttons in the listComposite. * * @param listComposite */ private void createSelectionButtons(Composite listComposite) { Composite buttonsComposite = new Composite(listComposite, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; buttonsComposite.setLayout(layout); buttonsComposite.setLayoutData(new GridData( GridData.VERTICAL_ALIGN_BEGINNING)); Button selectAll = new Button(buttonsComposite, SWT.PUSH); selectAll.setText("&Select All"); selectAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { enableAllProjects(); } }); Dialog.applyDialogFont(selectAll); setButtonLayoutData(selectAll); Button deselectAll = new Button(buttonsComposite, SWT.PUSH); deselectAll.setText("&Deselect All"); deselectAll.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { disableAllProjects(); } }); Dialog.applyDialogFont(deselectAll); setButtonLayoutData(deselectAll); Button refresh = new Button(buttonsComposite, SWT.PUSH); refresh.setText("R&efresh"); refresh.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if(destinationDir != null) { updateProjectsList(destinationDir.getAbsolutePath()); } } }); Dialog.applyDialogFont(refresh); setButtonLayoutData(refresh); } /** * Set the focus on path fields when page becomes visible. */ @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { IWizardPage previousPage = getPreviousPage(); if(previousPage instanceof ClonePage){ ClonePage page = (ClonePage) previousPage; File directory = page.getDestinationDirectory(); setInitialSelection(directory); } if(previousPage instanceof SelectRevisionPage) { SelectRevisionPage page = (SelectRevisionPage) previousPage; File directory = page.getHgRoot(); setInitialSelection(directory); } else if(getWizard() instanceof ImportProjectsFromRepoWizard){ final ImportProjectsFromRepoWizard impWizard = (ImportProjectsFromRepoWizard) getWizard(); if(impWizard.getInitialPath() != null) { impWizard.getShell().getDisplay().asyncExec( new Runnable() { public void run() { setInitialSelection(impWizard.getInitialPath()); } }); } } } } /** * Update the list of projects based on path. * * @param path */ private void updateProjectsList(final String path) { // on an empty path empty selectedProjects if (path == null || path.length() == 0) { setMessage(DESCRIPTION); selectedProjects = new ProjectRecord[0]; projectsList.refresh(true); projectsList.setCheckedElements(selectedProjects); fixFinishState(); lastPath = path; return; } repositoryRoot = new File(path); long modified = repositoryRoot.lastModified(); if (path.equals(lastPath) && lastModified == modified) { // since the file/folder was not modified and the path did not // change, no refreshing is required return; } lastPath = path; lastModified = modified; try { getContainer().run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { ProjectNameScope namer = new ProjectNameScope(); monitor.beginTask("Searching for projects", 100); selectedProjects = new ProjectRecord[0]; Collection files = new ArrayList(); monitor.worked(10); if (repositoryRoot.isDirectory()) { if (!collectProjectFilesFromDirectory(files, repositoryRoot, null, monitor)) { return; } Iterator filesIterator = files.iterator(); List prj = new ArrayList(); monitor.worked(50); monitor.subTask("Processing results"); if (filesIterator.hasNext()){ /* Check if the first project is the root */ File file = filesIterator.next(); File dir = file.getParentFile(); if (dir.isDirectory() && dir.equals(destinationDir)){ prj.add(new ProjectRecord(file, namer)); }else{ filesIterator = files.iterator(); /* reset iterator */ } } if (prj.isEmpty()){ prj.add(new ProjectRecord(destinationDir, namer)); } while (filesIterator.hasNext()) { File file = filesIterator.next(); prj.add(new ProjectRecord(file, namer)); } selectedProjects = prj.toArray(new ProjectRecord[prj.size()]); } else { monitor.worked(60); } monitor.done(); } }); } catch (InvocationTargetException e) { MercurialEclipsePlugin.logError(e.getMessage(), e.getCause()); } catch (InterruptedException e) { // Nothing to do if the user interrupts. } projectsList.refresh(false); validateSelectedProjects(); defaultEnableProjects(); projectsList.setExpandedElements(selectedProjects); projectsList.refresh(true); } /** * Collect the list of .project files that are under directory into files. * * @param files * @param directory * @param directoriesVisited * Set of canonical paths of directories, used as recursion guard * @param monitor * The monitor to report to * @return boolean true if the operation was completed. */ private boolean collectProjectFilesFromDirectory(Collection files, File directory, Set directoriesVisited, IProgressMonitor monitor) { if (monitor.isCanceled() || ".hg".equals(directory.getName())) { return false; } monitor.subTask("Checking: " + directory.getPath()); File[] contents = directory.listFiles(); if (contents == null) { return false; } // Initialize recursion guard for recursive symbolic links if (directoriesVisited == null) { directoriesVisited = new HashSet(); try { directoriesVisited.add(directory.getCanonicalPath()); } catch (IOException exception) { StatusManager.getManager().handle( MercurialEclipsePlugin.createStatus(exception .getLocalizedMessage(), IStatus.ERROR, IStatus.ERROR, exception)); } } // first look for project description files final String dotProject = IProjectDescription.DESCRIPTION_FILE_NAME; for (int i = 0; i < contents.length; i++) { File file = contents[i]; if (file.isFile() && file.getName().equals(dotProject)) { files.add(file); // don't search sub-directories since we can't have nested // projects return true; } } // no project description found, so recurse into sub-directories for (int i = 0; i < contents.length; i++) { if (contents[i].isDirectory()) { if (!contents[i].getName().equals(METADATA_FOLDER)) { try { String canonicalPath = contents[i].getCanonicalPath(); if (!directoriesVisited.add(canonicalPath)) { // already been here --> do not recurse continue; } } catch (IOException exception) { StatusManager.getManager().handle( MercurialEclipsePlugin.createStatus(exception .getLocalizedMessage(), IStatus.ERROR, IStatus.ERROR, exception)); } collectProjectFilesFromDirectory(files, contents[i], directoriesVisited, monitor); } } } return true; } /** * Create the selected projects * * @return boolean true if all project creations were * successful. */ public boolean createProjects() { saveWidgetValues(); final Object[] selected = projectsList.getCheckedElements(); createdProjects = new ArrayList(); WorkspaceModifyOperation op = new WorkspaceModifyOperation() { @Override protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask("", selected.length); //$NON-NLS-1$ if (monitor.isCanceled()) { throw new OperationCanceledException(); } for (int i = 0; i < selected.length; i++) { createExistingProject((ProjectRecord) selected[i], new SubProgressMonitor(monitor, 1)); } } finally { monitor.done(); } } }; // run the new project creation operation try { getContainer().run(true, true, op); } catch (InterruptedException e) { return false; } catch (InvocationTargetException e) { // one of the steps resulted in a core exception Throwable t = e.getTargetException(); String message = "Creation Problems"; IStatus status; if (t instanceof CoreException) { status = ((CoreException) t).getStatus(); } else { status = MercurialEclipsePlugin.createStatus(message, ERROR, IStatus.ERROR, t); } MercurialEclipsePlugin.logError(t); ErrorDialog.openError(getShell(), message, null, status); return false; } // Adds the projects to the working sets addToWorkingSets(); return true; } private void addToWorkingSets() { IWorkingSet[] selectedWorkingSets = workingSetGroup.getSelectedWorkingSets(); if(selectedWorkingSets == null || selectedWorkingSets.length == 0) { return; // no Working set is selected } IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); for (Iterator i = createdProjects.iterator(); i.hasNext();) { IProject project = i.next(); workingSetManager.addToWorkingSets(project, selectedWorkingSets); } } /** * Create the project described in record. If it is successful return true. * * @param record * @return boolean true if successful * @throws InterruptedException */ private boolean createExistingProject(final ProjectRecord record, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { String projectName = record.getProjectName(); final IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProject project = workspace.getRoot().getProject(projectName); createdProjects.add(project); // See issue 10412: in case the clone is inside the workspace AND the clone directory name doesn't match // the selected project name, we have to rename cloned directory, otherwise // Eclipse will create a new EMPTY project if (record.description.getLocationURI() == null && !projectName.equals(record.getDataDir().getName())) { File newRoot = new File(record.getDataDir().getParentFile(), projectName); boolean caseDiffers = false; try { caseDiffers = newRoot.getCanonicalFile().getName().equals(record.getDataDir().getName()); } catch (IOException e) { } if(!newRoot.exists() || caseDiffers) { // we CAN use renameTo here because src and dest folders are on same file system // renameTo does NOT work on different file systems boolean renamed = record.getDataDir().renameTo(newRoot); if(!renamed){ MercurialEclipsePlugin.logError(new IllegalStateException("Couldn't rename hgroot to project dir")); return false; } } else { MercurialEclipsePlugin.logError(new IllegalStateException("New project data directory doesn't exist")); return false; } } record.description.setName(projectName); try { monitor.beginTask("Creating Projects", 100); project.create(record.description, new SubProgressMonitor(monitor, 30)); project.open(IResource.BACKGROUND_REFRESH, new SubProgressMonitor(monitor, 70)); } catch (CoreException e) { throw new InvocationTargetException(e); } finally { monitor.done(); } try { registerWithTeamProvider(project, monitor); } catch (CoreException e) { try { project.delete(true, new SubProgressMonitor(monitor, 30)); } catch (CoreException ex) { throw new InvocationTargetException(ex); } throw new InvocationTargetException(e); } return true; } private void registerWithTeamProvider(IProject p, IProgressMonitor monitor) throws CoreException { // Register the project with Team. This will bring all the // files that we cloned into the project. monitor.subTask(Messages .getString("CloneRepoWizard.subTask.registeringProject1") + " " + p.getName() //$NON-NLS-1$ + Messages .getString("CloneRepoWizard.subTaskRegisteringProject2")); //$NON-NLS-1$ RepositoryProvider.map(p, MercurialTeamProvider.class.getName()); monitor.worked(1); IWizard wizard = getWizard(); if(!(wizard instanceof CloneRepoWizard)){ return; } IHgRepositoryLocation repo = ((CloneRepoWizard) wizard).getRepository(); // It appears good. Stash the repo location. monitor.subTask(Messages .getString("CloneRepoWizard.subTask.addingRepository.1") + " " + repo //$NON-NLS-1$ + Messages .getString("CloneRepoWizard.subTask.addingRepository.2")); //$NON-NLS-1$ if(destinationDir instanceof HgRoot) { MercurialEclipsePlugin.getRepoManager().addRepoLocation((HgRoot) destinationDir, repo); } monitor.worked(1); } /** * The WizardDataTransfer implementation of this * IOverwriteQuery method asks the user whether the existing * resource at the given path should be overwritten. * * @param pathString * @return the user's reply: one of "YES", "NO", * "ALL", or "CANCEL" */ public String queryOverwrite(String pathString) { Path path = new Path(pathString); String messageString; // Break the message up if there is a file name and a directory // and there are at least 2 segments. if (path.getFileExtension() == null || path.segmentCount() < 2) { messageString = "'" + pathString + "' already exists. Would you like to overwrite it?"; } else { messageString = "Overwrite '" + path.lastSegment() + "' in folder '" + path.removeLastSegments(1).toOSString() + "'?"; } final MessageDialog dialog = new MessageDialog(getContainer() .getShell(), "Question", null, messageString, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.YES_TO_ALL_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.NO_TO_ALL_LABEL, IDialogConstants.CANCEL_LABEL }, 0) { @Override protected int getShellStyle() { // TODO add "| SWT.SHEET" flag as soon as we drop Eclipse 3.4 support return super.getShellStyle()/* | SWT.SHEET*/; } }; String[] response = new String[] { YES, ALL, NO, NO_ALL, CANCEL }; // run in syncExec because callback is from an operation, // which is probably not running in the UI thread. getControl().getDisplay().syncExec(new Runnable() { public void run() { dialog.open(); } }); return dialog.getReturnCode() < 0 ? CANCEL : response[dialog.getReturnCode()]; } /** * Method used for test suite. * * @return CheckboxTreeViewer the viewer containing all the projects found */ public CheckboxTreeViewer getProjectsList() { return projectsList; } /** * Retrieve all the projects in the current workspace. * * @return IProject[] array of IProject in the current workspace */ private IProject[] getProjectsInWorkspace() { if (wsProjects == null) { wsProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); } return wsProjects; } /** * Get the array of project records that can be imported from the * source workspace or archive, selected by the user. * * @return ProjectRecord[] array of projects that can be imported into the * workspace */ private ProjectRecord[] getSubProjectRecords() { List projectRecords = new ArrayList(); for (int i = 1; i < selectedProjects.length; i++) { projectRecords.add(selectedProjects[i]); } return projectRecords.toArray(new ProjectRecord[projectRecords.size()]); } /** * Determine if the project with the given name is in the current workspace. * * @param projectName * String the project name to check * @return boolean true if the project with the given name is in this * workspace */ private boolean isProjectInWorkspace(String projectName) { if (projectName == null) { return false; } IProject[] workspaceProjects = getProjectsInWorkspace(); for (int i = 0; i < workspaceProjects.length; i++) { if (projectName.equalsIgnoreCase(workspaceProjects[i].getName())) { return true; } } return false; } /** * Use the dialog store to restore widget values to the values that they * held last time this wizard was used to completion, or alternatively, * if an initial path is specified, use it to select values. * * Method declared public only for use of tests. */ public void restoreWidgetValues() { // First, check to see if we have resore settings, and // take care of the checkbox // IDialogSettings settings = getDialogSettings(); } /** * Since Finish was pressed, write widget values to the dialog store so that * they will persist into the next invocation of this wizard page. * * Method declared public only for use of tests. */ public void saveWidgetValues() { // IDialogSettings settings = getDialogSettings(); } public void setInitialSelection(File destinationDirectory) { destinationDir = destinationDirectory; if(destinationDirText != null){ destinationDirText.setText(destinationDir.getAbsolutePath()); } updateProjectsList(destinationDir.getAbsolutePath()); } private void enableProject(ProjectRecord record){ if (!record.hasConflicts){ projectsList.setChecked(record, true); if (!ENABLE_NESTED_CHECK){ if (record == selectedProjects[0]){ disableAllSubProjects(); }else{ disableMainProject(); } } }else{ projectsList.setChecked(record, false); } fixFinishState(); } private void disableProject(ProjectRecord record){ projectsList.setChecked(record, false); fixFinishState(); } private void enableAllSubProjects() { for (int i = 1; i < selectedProjects.length; i++) { enableProject(selectedProjects[i]); } } private void disableAllSubProjects() { for (int i = 1; i < selectedProjects.length; i++) { disableProject(selectedProjects[i]); } } private void enableMainProject() { if (isMainProjectActive()){ enableProject(selectedProjects[0]); } } private void disableMainProject() { disableProject(selectedProjects[0]); } private void enableAllProjects() { if (ENABLE_NESTED_CHECK){ enableMainProject(); } enableAllSubProjects(); } private void disableAllProjects() { disableMainProject(); disableAllSubProjects(); } private void defaultEnableProjects(){ if (ENABLE_NESTED_CHECK){ enableAllProjects(); }else{ if (selectedProjects.length > 1){ enableAllSubProjects(); }else if (selectedProjects.length == 1){ enableMainProject(); } } } private void validateProject(ProjectRecord record, boolean value){ if (!value) { record.hasConflicts = true; projectsList.setGrayed(record, true); } else { record.hasConflicts = false; projectsList.setGrayed(record, false); } } /** * If a project with the * same name exists in both the source workspace and the current workspace, * then the hasConflicts flag would be set on that project record. */ private void validateSelectedProjects() { boolean hasConflict = false; for (int i = 0; i < selectedProjects.length; i++) { ProjectRecord record = selectedProjects[i]; boolean v = isProjectInWorkspace(record.getProjectName()); validateProject(record,!v); hasConflict = hasConflict && v; } if(!hasConflict) { setMessage(null, WARNING); setDescription(DESCRIPTION); } else { setMessage( "Some projects cannot be imported because they already exist in the workspace. " + "Double click on project to change project name.", WARNING); } if(selectedProjects.length == 0) { setMessage("No projects are selected to import", WARNING); } } private class ProjectNameScope { private final Set names = new HashSet(); public String getAvailableName(String name, String fallbackName) { if (!isAvailable(name)) { if (isAvailable(fallbackName)) { name = fallbackName; } else { for (int i = 1; i <= 50; i++) { String cur = name + i; if (isAvailable(cur)) { name = cur; break; } } } } names.add(name); return name; } private boolean isAvailable(String name) { return name != null && !names.contains(name) && !isProjectInWorkspace(name); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/PullOperation.java000066400000000000000000000172541173713500500335240ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.operation.IRunnableContext; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.SafeUiJob; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.commands.HgPushPullClient; import com.vectrace.MercurialEclipse.commands.extensions.HgSvnClient; import com.vectrace.MercurialEclipse.commands.extensions.forest.HgFpushPullClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.menu.MergeHandler; import com.vectrace.MercurialEclipse.menu.UpdateHandler; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocation.BundleRepository; class PullOperation extends HgOperation { private final boolean doUpdate; private final HgRoot hgRoot; private final IHgRepositoryLocation repo; private final boolean force; private final ChangeSet pullRevision; private final boolean timeout; private final boolean merge; private String output = ""; //$NON-NLS-1$ private final boolean showCommitDialog; private final File bundleFile; private final boolean forest; private final File snapFile; private final boolean rebase; private final boolean svn; private final boolean doCleanUpdate; public PullOperation(IRunnableContext context, boolean doUpdate, boolean doCleanUpdate, HgRoot hgRoot, boolean force, IHgRepositoryLocation repo, ChangeSet pullRevision, boolean timeout, boolean merge, boolean showCommitDialog, File bundleFile, boolean forest, File snapFile, boolean rebase, boolean svn) { super(context); this.doUpdate = doUpdate; this.doCleanUpdate = doCleanUpdate; this.hgRoot = hgRoot; this.force = force; this.repo = repo; this.pullRevision = pullRevision; this.timeout = timeout; this.merge = merge; this.showCommitDialog = showCommitDialog; this.bundleFile = bundleFile; this.forest = forest; this.snapFile = snapFile; this.rebase = rebase; this.svn = svn; } @Override protected String getActionDescription() { return Messages.getString("PullRepoWizard.pullOperation.description"); //$NON-NLS-1$ } private String performMerge(IProgressMonitor monitor) throws HgException, InterruptedException { String r = Messages.getString("PullRepoWizard.pullOperation.mergeHeader"); //$NON-NLS-1$ monitor.subTask(Messages.getString("PullRepoWizard.pullOperation.merging")); //$NON-NLS-1$ if (HgLogClient.getHeads(hgRoot).length > 1) { SafeUiJob job = new SafeUiJob(Messages.getString("PullRepoWizard.pullOperation.mergeJob.description")) { //$NON-NLS-1$ @Override protected IStatus runSafe(IProgressMonitor m) { try { String res = MergeHandler.determineMergeHeadAndMerge(hgRoot, getShell(), m, true, showCommitDialog); return new Status(IStatus.OK, MercurialEclipsePlugin.ID, res); } catch (CoreException e) { MercurialEclipsePlugin.logError(e); return e.getStatus(); } } }; job.schedule(); job.join(); IStatus jobResult = job.getResult(); if (jobResult.getSeverity() == IStatus.OK) { r += jobResult.getMessage(); } else { throw new HgException(jobResult); } } monitor.worked(1); return r; } private String performPull(final IHgRepositoryLocation repository, IProgressMonitor monitor) throws CoreException { monitor.worked(1); monitor.subTask(Messages.getString("PullRepoWizard.pullOperation.incoming")); //$NON-NLS-1$ String r = Messages.getString("PullRepoWizard.pullOperation.pull.header"); //$NON-NLS-1$ boolean updateSeparately = false; if (svn) { r += HgSvnClient.pull(hgRoot); if (rebase) { r += HgSvnClient.rebase(hgRoot); } } else if (bundleFile == null) { if (forest) { File forestRoot = hgRoot.getParentFile(); r += HgFpushPullClient.fpull(forestRoot, repo, doUpdate, timeout, pullRevision, true, snapFile, false); } else { if (doUpdate) { updateSeparately = true; } r += HgPushPullClient.pull(hgRoot, pullRevision, repo, false, rebase, force, timeout, merge); } } else { if (doUpdate) { updateSeparately = true; } File canonicalBundle = toCanonicalBundle(); BundleRepository bundleRepo = new BundleRepository(canonicalBundle); r += HgPushPullClient.pull(hgRoot, pullRevision, bundleRepo, false, rebase, force, timeout, merge); } monitor.worked(1); saveRepo(monitor); if (updateSeparately) { runUpdate(); } return r; } private File toCanonicalBundle() throws HgException { File canonicalFile = null; try { canonicalFile = bundleFile.getCanonicalFile(); } catch (IOException e) { String message = "Failed to get canonical bundle path for: " + bundleFile; MercurialEclipsePlugin.logError(message, e); throw new HgException(message, e); } return canonicalFile; } private void runUpdate() { new Job("Hg update after pull") { @Override public IStatus run(IProgressMonitor monitor1) { try { // if merge or rebase requested don't ask user what to do // with cross branches boolean handleCrossBranches = !(merge || rebase); UpdateHandler updateHandler = new UpdateHandler(handleCrossBranches); updateHandler.setCleanEnabled(doCleanUpdate); updateHandler.run(hgRoot); return Status.OK_STATUS; } catch (HgException e) { // no point in complaining, since they want to merge/rebase anyway if ((merge || rebase) && e.getMessage().contains("crosses branches")) { return Status.OK_STATUS; } MercurialEclipsePlugin.logError(e); MercurialEclipsePlugin.showError(e); return Status.CANCEL_STATUS; } } }.schedule(); } private boolean saveRepo(IProgressMonitor monitor) { // It appears good. Stash the repo location. monitor.subTask(Messages.getString("PullRepoWizard.pullOperation.addRepo") + repo); //$NON-NLS-1$ try { MercurialEclipsePlugin.getRepoManager().addRepoLocation(hgRoot, repo); } catch (HgException e) { MercurialEclipsePlugin.logError(Messages .getString("PullRepoWizard.addingRepositoryFailed"), e); //$NON-NLS-1$ } monitor.worked(1); return true; } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask(Messages.getString("PullRepoWizard.pullOperation.pulling"), 6); //$NON-NLS-1$ output += performPull(repo, monitor); if (merge) { output += performMerge(monitor); } } catch (CoreException e) { throw new InvocationTargetException(e, e.getMessage()); } monitor.done(); } public String getOutput() { return output; } }eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/PullPage.java000066400000000000000000000210401173713500500324240ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - some updates * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocation; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.ResourceProperties; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * This file implements a wizard page which will allow the user to create a * repository location. */ public class PullPage extends PushPullPage { private Button updateCheckBox; private Button mergeCheckBox; private Button commitDialogCheckBox; private Button rebaseCheckBox; private Button cleanUpdateCheckBox; public PullPage(String pageName, String title, String description, HgRoot hgRoot, ImageDescriptor titleImage) { super(hgRoot, pageName, title, titleImage); setDescription(description); setShowCredentials(true); setShowBundleButton(true); } public boolean isRebaseSelected() { return rebaseCheckBox != null && rebaseCheckBox.getSelection(); } public boolean isShowCommitDialogSelected() { return commitDialogCheckBox.getSelection(); } @Override public boolean canFlipToNextPage() { try { String urlText = getUrlText(); if (urlText != null && urlText.length() != 0) { IncomingPage incomingPage = (IncomingPage) getNextPage(); incomingPage.setHgRoot(getHgRoot()); IHgRepositoryLocation loc = MercurialEclipsePlugin .getRepoManager().getRepoLocation( urlText, getUserText(), getPasswordText()); incomingPage.setLocation(loc); incomingPage.setSvn(isSvnSelected()); incomingPage.setForce(isForceSelected()); return isPageComplete() && (getWizard().getNextPage(this) != null); } } catch (HgException e) { setErrorMessage(e.getLocalizedMessage()); } return false; } @Override public boolean isPageComplete() { return super.isPageComplete() && HgRepositoryLocation.validateLocation(getUrlText()); } @Override public void createControl(Composite parent) { super.createControl(parent); Composite composite = (Composite) getControl(); IDialogSettings prefs = getHgRootDialogSetting(); // now the options Group pullGroup = SWTWidgetHelper .createGroup(composite, Messages.getString("PullPage.pullGroup.label")); //$NON-NLS-1$ updateCheckBox = SWTWidgetHelper.createCheckBox(pullGroup, Messages.getString("PullPage.toggleUpdate.text")); //$NON-NLS-1$ updateCheckBox.setSelection(getSetting(prefs, "update", true)); cleanUpdateCheckBox = SWTWidgetHelper.createCheckBox(pullGroup, Messages.getString("PullPage.toggleCleanUpdate.text")); //$NON-NLS-1$ cleanUpdateCheckBox.setSelection(getSetting(prefs, "cleanupdate", false)); try { if (MercurialUtilities.isCommandAvailable("rebase", //$NON-NLS-1$ ResourceProperties.REBASE_AVAILABLE, "hgext.rebase=")) { //$NON-NLS-1$ rebaseCheckBox = SWTWidgetHelper.createCheckBox(pullGroup, Messages.getString("PullPage.option.rebase")); //$NON-NLS-1$ SelectionListener rebaseCheckBoxListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { if (rebaseCheckBox.getSelection()) { updateCheckBox.setSelection(false); mergeCheckBox.setSelection(false); } } }; SelectionListener updateCheckBoxListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { if (updateCheckBox.getSelection()) { rebaseCheckBox.setSelection(false); } } }; rebaseCheckBox.addSelectionListener(rebaseCheckBoxListener); updateCheckBox.addSelectionListener(updateCheckBoxListener); rebaseCheckBox.setSelection(getSetting(prefs, "rebase", false)); } } catch (HgException e2) { MercurialEclipsePlugin.logError(e2); } this.forceCheckBox.setParent(pullGroup); this.forceCheckBox.setSelection(getSetting(prefs, "force", false)); pullGroup.moveAbove(optionGroup); Group mergeGroup = SWTWidgetHelper.createGroup(composite, Messages.getString("PullPage.option.merge")); //$NON-NLS-1$ this.mergeCheckBox = SWTWidgetHelper.createCheckBox(mergeGroup, Messages.getString("PullPage.option.commitAfterMerge")); //$NON-NLS-1$ this.mergeCheckBox.setSelection(getSetting(prefs, "merge", false)); this.commitDialogCheckBox = SWTWidgetHelper.createCheckBox(mergeGroup, Messages.getString("PullPage.option.editCommitMessage")); //$NON-NLS-1$ this.commitDialogCheckBox.setSelection(true); this.commitDialogCheckBox.setEnabled(false); mergeGroup.moveBelow(pullGroup); SelectionListener mergeCheckBoxListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { commitDialogCheckBox.setEnabled(mergeCheckBox.getSelection()); if (mergeCheckBox.getSelection()) { try { if (HgStatusClient.isDirty(getHgRoot())) { setErrorMessage(Messages.getString("PullPage.error.modifiedResources")); //$NON-NLS-1$ setPageComplete(false); } else { setErrorMessage(null); setPageComplete(true); // you can only rebase OR merge, not both rebaseCheckBox.setSelection(false); } } catch (HgException e1) { setErrorMessage(Messages.getString("PullPage.error.noStatus")); //$NON-NLS-1$ mergeCheckBox.setSelection(false); mergeCheckBox.setEnabled(false); setPageComplete(true); } } else { setErrorMessage(null); setPageComplete(true); } } }; mergeCheckBox.addSelectionListener(mergeCheckBoxListener); setPageComplete(true); setControl(composite); } @Override public boolean finish(IProgressMonitor monitor) { boolean res = super.finish(monitor); IDialogSettings prefs = getHgRootDialogSetting(); if (prefs != null) { prefs.put("update", isUpdateSelected()); prefs.put("cleanupdate", isCleanUpdateSelected()); prefs.put("rebase", isRebaseSelected()); prefs.put("force", isForce()); prefs.put("merge", isMergeSelected()); } return res; } @Override protected String getForceCheckBoxLabel() { return Messages.getString("PullPage.forceCheckBox.title"); //$NON-NLS-1$ } @Override protected String getTimeoutCheckBoxLabel() { return Messages.getString("PullPage.timeoutCheckBox.title"); //$NON-NLS-1$ } public boolean isUpdateSelected() { return updateCheckBox.getSelection(); } public boolean isCleanUpdateSelected() { return cleanUpdateCheckBox.getSelection(); } public boolean isMergeSelected() { return mergeCheckBox.getSelection(); } private static boolean getSetting(IDialogSettings setting, String sKey, boolean bDefault) { if (setting != null && (sKey = setting.get(sKey)) != null) { return Boolean.valueOf(sKey).booleanValue(); } return bDefault; } /** * @return Get or add dialog settings for the current hg root. */ protected IDialogSettings getHgRootDialogSetting() { IDialogSettings s = getDialogSettings(), res = null; Object root = getHgRoot(); if (s != null && root != null && (root = ((HgRoot) root).getAbsolutePath()) != null) { res = s.getSection((String) root); if (res == null) { res = s.addNewSection((String) root); } } return res; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/PullRepoWizard.java000066400000000000000000000105031173713500500336400ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Bastian Doetsch - saving repository to projec specific repos. * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.util.SortedSet; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; public class PullRepoWizard extends HgWizard { private boolean doUpdate; private PullPage pullPage; private IncomingPage incomingPage; private final HgRoot hgRoot; private IHgRepositoryLocation repo; private boolean doCleanUpdate; public PullRepoWizard(HgRoot hgRoot) { super(Messages.getString("PullRepoWizard.title")); //$NON-NLS-1$ this.hgRoot = hgRoot; setNeedsProgressMonitor(true); } @Override public void addPages() { pullPage = new PullPage(Messages .getString("PullRepoWizard.pullPage.name"), //$NON-NLS-1$ Messages.getString("PullRepoWizard.pullPage.title"), //$NON-NLS-1$ Messages.getString("PullRepoWizard.pullPage.description"), //$NON-NLS-1$ hgRoot, null); initPage(pullPage.getDescription(), pullPage); addPage(pullPage); incomingPage = new IncomingPage(Messages .getString("PullRepoWizard.incomingPage.name")); //$NON-NLS-1$ initPage(incomingPage.getDescription(), incomingPage); addPage(incomingPage); } @Override public boolean performFinish() { pullPage.finish(new NullProgressMonitor()); incomingPage.finish(new NullProgressMonitor()); repo = getLocation(); doUpdate = pullPage.isUpdateSelected(); doCleanUpdate = pullPage.isCleanUpdateSelected(); boolean force = pullPage.isForceSelected(); ChangeSet cs = null; if (incomingPage.isRevisionSelected()) { cs = incomingPage.getRevision(); } boolean timeout = pullPage.isTimeoutSelected(); boolean merge = pullPage.isMergeSelected(); boolean rebase = pullPage.isRebaseSelected(); boolean showCommitDialog = pullPage.isShowCommitDialogSelected(); boolean svn = pullPage.isSvnSelected(); boolean forest = false; File snapFile = null; if (pullPage.isShowForest()) { forest = pullPage.isForestSelected(); String snapFileText = pullPage.getSnapFileText(); if (snapFileText.length() > 0) { snapFile = new File(snapFileText); } } File bundleFile = null; SortedSet changesets = incomingPage.getChangesets(); if (changesets != null && changesets.size() > 0) { bundleFile = changesets.first().getBundleFile(); } try { PullOperation pullOperation = new PullOperation(getContainer(), doUpdate, doCleanUpdate, hgRoot, force, repo, cs, timeout, merge, showCommitDialog, bundleFile, forest, snapFile, rebase, svn); getContainer().run(true, false, pullOperation); String output = pullOperation.getOutput(); if (output.length() != 0) { HgClients.getConsole().printMessage(output, null); } } catch (Exception e) { Throwable error = e.getCause() == null? e : e.getCause(); MercurialEclipsePlugin.logError(error); MercurialEclipsePlugin.showError(error); return false; } return true; } private IHgRepositoryLocation getLocation() { try { return MercurialEclipsePlugin.getRepoManager() .fromProperties(hgRoot, pullPage.getProperties()); } catch (HgException e) { MessageDialog.openInformation(getShell(), Messages .getString("PullRepoWizard.malformedURL"), e.getMessage()); //$NON-NLS-1$ MercurialEclipsePlugin.logInfo(e.getMessage(), e); return null; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/PushPullPage.java000066400000000000000000000153111173713500500332700ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Adam Berkes (Intland) - repository location handling * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.ResourceProperties; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author bastian * */ public abstract class PushPullPage extends ConfigurationWizardMainPage { protected Button forceCheckBox; protected Group optionGroup; private boolean force; private boolean timeout; private Button timeoutCheckBox; private Button forestCheckBox; private Combo snapFileCombo; private Button snapFileButton; private Button svnCheckBox; private boolean showForce; private boolean showForest; private boolean showSnapFile; private boolean showSvn; public PushPullPage(HgRoot hgRoot, String pageName, String title, ImageDescriptor titleImage) { super(pageName, title, titleImage); showSnapFile = true; showForce = true; setHgRoot(hgRoot); try { setShowForest(true); setShowSvn(true); } catch (HgException e) { MercurialEclipsePlugin.logError(e); setErrorMessage(e.getMessage()); } } @Override public void createControl(Composite parent) { super.createControl(parent); Composite composite = (Composite) getControl(); // now the options optionGroup = SWTWidgetHelper.createGroup(composite, Messages .getString("PushRepoPage.optionGroup.title")); //$NON-NLS-1$ timeoutCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, getTimeoutCheckBoxLabel()); if (showForce) { forceCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, getForceCheckBoxLabel()); forceCheckBox.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { optionChanged(); } }); } createExtensionControls(); initDefaultLocation(); } protected void createExtensionControls() { if (showForest) { this.forestCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("PushPullPage.option.forest")); //$NON-NLS-1$ if (showSnapFile) { Composite c = SWTWidgetHelper.createComposite(optionGroup, 3); final Label forestLabel = SWTWidgetHelper.createLabel(c, Messages.getString("PushPullPage.snapfile.label")); //$NON-NLS-1$ forestLabel.setEnabled(false); this.snapFileCombo = createEditableCombo(c); snapFileCombo.setEnabled(false); this.snapFileButton = SWTWidgetHelper.createPushButton(c, Messages.getString("PushPullPage.snapfile.browse"), 1); //$NON-NLS-1$ snapFileButton.setEnabled(false); this.snapFileButton .addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { FileDialog dialog = new FileDialog(getShell()); dialog.setText(Messages.getString("PushPullPage.snapfile.select")); //$NON-NLS-1$ String file = dialog.open(); if (file != null) { snapFileCombo.setText(file); } } }); SelectionListener forestCheckBoxListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { forestLabel.setEnabled(forestCheckBox.getSelection()); snapFileButton .setEnabled(forestCheckBox.getSelection()); snapFileCombo.setEnabled(forestCheckBox.getSelection()); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; forestCheckBox.addSelectionListener(forestCheckBoxListener); } } if (showSvn) { svnCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("PushPullPage.option.svn")); //$NON-NLS-1$ } } @SuppressWarnings("static-method") protected String getForceCheckBoxLabel() { return Messages.getString("PushRepoPage.forceCheckBox.text"); //$NON-NLS-1$ } @SuppressWarnings("static-method") protected String getTimeoutCheckBoxLabel() { return Messages.getString("PushRepoPage.timeoutCheckBox.text"); //$NON-NLS-1$ } public boolean isForce() { return force; } public boolean isTimeout() { return timeout; } public boolean isForceSelected() { return forceCheckBox != null && forceCheckBox.getSelection(); } public boolean isTimeoutSelected() { return timeoutCheckBox != null && timeoutCheckBox.getSelection(); } public void setShowForce(boolean showForce) { this.showForce = showForce; } public boolean isShowForest() { return showForest; } protected void setShowForest(boolean showForest) throws HgException { this.showForest = showForest && MercurialUtilities.isCommandAvailable("fpull", //$NON-NLS-1$ ResourceProperties.EXT_FOREST_AVAILABLE, null); } public String getSnapFileText() { return snapFileCombo != null? snapFileCombo.getText() : null; } public boolean isShowSnapFile() { return showSnapFile; } public void setShowSnapFile(boolean showSnapFile) { this.showSnapFile = showSnapFile; } public boolean isForestSelected() { return forestCheckBox.getSelection(); } public boolean isShowSvn() { return showSvn; } protected void setShowSvn(boolean showSvn) throws HgException { this.showSvn = showSvn && MercurialUtilities.isCommandAvailable("svn", //$NON-NLS-1$ ResourceProperties.EXT_HGSUBVERSION_AVAILABLE, null); } public boolean isSvnSelected() { return isShowSvn() && svnCheckBox != null && svnCheckBox.getSelection(); } @Override public boolean finish(IProgressMonitor monitor) { this.force = isForceSelected(); this.timeout = isTimeoutSelected(); return super.finish(monitor); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/PushRepoPage.java000066400000000000000000000050471173713500500332660ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.Set; import org.eclipse.jface.resource.ImageDescriptor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgPathsClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; /** * @author bastian * */ public class PushRepoPage extends PushPullPage { public PushRepoPage(String pageName, String title, ImageDescriptor titleImage, HgRoot hgRoot) { super(hgRoot, pageName, title, titleImage); } @Override public boolean canFlipToNextPage() { try { String urlText = getUrlText(); if (urlText != null && urlText.length() > 0) { OutgoingPage outgoingPage = (OutgoingPage) getNextPage(); outgoingPage.setHgRoot(getHgRoot()); IHgRepositoryLocation loc = MercurialEclipsePlugin .getRepoManager().getRepoLocation(urlText, getUserText(), getPasswordText()); outgoingPage.setLocation(loc); outgoingPage.setSvn(isSvnSelected()); outgoingPage.setForce(isForceSelected()); setErrorMessage(null); return isPageComplete() && (getWizard().getNextPage(this) != null); } } catch (HgException e) { setErrorMessage(e.getLocalizedMessage()); } return false; } @Override protected IHgRepositoryLocation getRepoFromRoot(){ HgRepositoryLocationManager mgr = MercurialEclipsePlugin.getRepoManager(); IHgRepositoryLocation defaultLocation = mgr.getDefaultRepoLocation(getHgRoot()); Set repos = mgr.getAllRepoLocations(getHgRoot()); if (defaultLocation == null) { for (IHgRepositoryLocation repo : repos) { if (HgPathsClient.DEFAULT_PUSH.equals(repo.getLogicalName()) || HgPathsClient.DEFAULT.equals(repo.getLogicalName())) { defaultLocation = repo; break; } } } return defaultLocation; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/PushRepoWizard.java000066400000000000000000000157571173713500500336630ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - implementation * Stefan Groschupf - logError * Stefan C - Code cleanup * Bastian Doetsch - saving repository to project-specific repos * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.net.URISyntaxException; import java.util.Properties; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.MessageDialog; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgPushPullClient; import com.vectrace.MercurialEclipse.commands.extensions.HgSvnClient; import com.vectrace.MercurialEclipse.commands.extensions.forest.HgFpushPullClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.cache.IncomingChangesetCache; import com.vectrace.MercurialEclipse.team.cache.OutgoingChangesetCache; /** * @author zingo * */ public class PushRepoWizard extends HgWizard { private HgRoot hgRoot; private OutgoingPage outgoingPage; /** * Optional message to display when first opening the wizard */ private String message; private PushRepoWizard() { super(Messages.getString("PushRepoWizard.title")); //$NON-NLS-1$ setNeedsProgressMonitor(true); } public PushRepoWizard(HgRoot hgRoot) { this(); this.hgRoot = hgRoot; } @Override public void addPages() { super.addPages(); PushPullPage myPage = new PushRepoPage( Messages.getString("PushRepoWizard.pushRepoPage.name"), //$NON-NLS-1$ Messages.getString("PushRepoWizard.pushRepoPage.title"), null, hgRoot); //$NON-NLS-1$ initPage(Messages.getString("PushRepoWizard.pushRepoPage.description"), //$NON-NLS-1$ myPage); myPage.setShowCredentials(true); page = myPage; addPage(page); outgoingPage = new OutgoingPage("OutgoingPage"); //$NON-NLS-1$ initPage(outgoingPage.getDescription(), outgoingPage); outgoingPage.setHgRoot(hgRoot); addPage(outgoingPage); if (message != null) { page.setMessage(message, IMessageProvider.WARNING); } } @Override public boolean performFinish() { super.performFinish(); Properties props = page.getProperties(); final IHgRepositoryLocation repo; try { repo = MercurialEclipsePlugin.getRepoManager().fromProperties(hgRoot, props); } catch (HgException e){ if(!(e.getCause() instanceof URISyntaxException)){ MercurialEclipsePlugin.logError(e); } return false; } final PushPullPage pushRepoPage = (PushPullPage) page; final int timeout; if (!pushRepoPage.isTimeout()) { timeout = Integer.MAX_VALUE; } else { timeout = HgClients.getTimeOut(MercurialPreferenceConstants.PUSH_TIMEOUT); } final ChangeSet changeset; if (outgoingPage.isRevisionSelected()) { changeset = outgoingPage.getRevision(); } else { changeset = null; } String result = Messages.getString("PushRepoWizard.pushOutput.header"); //$NON-NLS-1$ final boolean svnEnabled = isSvnEnabled(pushRepoPage); final boolean isForest = !svnEnabled && isForestEnabled(pushRepoPage); final String snapFileText = pushRepoPage.getSnapFileText(); class PushOperation extends HgOperation { private String output; public PushOperation() { super(getContainer()); } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask("Pushing...", IProgressMonitor.UNKNOWN); try { if (svnEnabled) { output = HgSvnClient.push(hgRoot); } else if (isForest) { File forestRoot = hgRoot.getParentFile(); File snapFile = null; if (snapFileText.length() > 0) { snapFile = new File(snapFileText); } output = HgFpushPullClient.fpush(forestRoot, repo, changeset, timeout, snapFile); } else { output = HgPushPullClient.push(hgRoot, repo, pushRepoPage.isForce(), changeset, timeout); } } catch (CoreException e){ throw new InvocationTargetException(e, e.getMessage()); } finally { monitor.done(); } } @Override protected String getActionDescription() { return "Pushing " + hgRoot.getName() + " ..."; } public String getOutput() { return output; } } PushOperation pushOperation = new PushOperation(); try { getContainer().run(true, false, pushOperation); result += pushOperation.getOutput(); } catch (Exception e) { Throwable error = e.getCause() == null? e : e.getCause(); MercurialEclipsePlugin.logError(error); MessageDialog.openError(getContainer().getShell(), "Error during push", e.getMessage()); //$NON-NLS-1$ return false; } try { updateAfterPush(result, hgRoot, repo, isForest); } catch (HgException e) { MercurialEclipsePlugin.logError(e); MessageDialog.openError(getContainer().getShell(), "Error on refreshing status after push", e.getMessage()); //$NON-NLS-1$ return false; } return true; } private boolean isForestEnabled(PushPullPage pushRepoPage) { return pushRepoPage.isShowForest() && pushRepoPage.isForestSelected(); } private boolean isSvnEnabled(PushPullPage pushRepoPage) { return pushRepoPage.isShowSvn() && pushRepoPage.isSvnSelected(); } private static void updateAfterPush(String result, HgRoot hgRoot, IHgRepositoryLocation repo, boolean isForest) throws HgException { if (result.length() != 0) { HgClients.getConsole().printMessage(result, null); } // It appears good. Stash the repo location. MercurialEclipsePlugin.getRepoManager().addRepoLocation(hgRoot, repo); if(isForest){ IncomingChangesetCache.getInstance().clear(repo); OutgoingChangesetCache.getInstance().clear(repo); } else { IncomingChangesetCache.getInstance().clear(hgRoot, true); OutgoingChangesetCache.getInstance().clear(hgRoot, true); } } public void setInitialMessage(String message) { this.message = message; if (page != null) { page.setMessage(message, IMessageProvider.WARNING); } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/RebasePage.java000066400000000000000000000164321173713500500327220ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.commands.extensions.HgRebaseClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.team.MercurialUtilities; import com.vectrace.MercurialEclipse.team.ResourceProperties; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author bastian * * Rebase page. Not applicable if a rebase is in progress. */ public class RebasePage extends HgWizardPage { private final HgRoot hgRoot; private ChangesetTable srcTable; private Button sourceRevCheckBox; private Button baseRevCheckBox; private Button destRevCheckBox; private Button collapseRevCheckBox; private Button keepCheckBox; private Button keepBranchesCheckBox; private ChangesetTable destTable; public RebasePage(String pageName, String title, ImageDescriptor titleImage, String description, HgRoot hgRoot) { super(pageName, title, titleImage, description); this.hgRoot = hgRoot; } public void createControl(Composite parent) { Composite comp = SWTWidgetHelper.createComposite(parent, 2); createSrcWidgets(comp); createDestWidgets(comp); createOptionsWidgets(comp); setControl(comp); try { if (!MercurialUtilities.isCommandAvailable("rebase", //$NON-NLS-1$ ResourceProperties.REBASE_AVAILABLE, "hgext.rebase=")) { //$NON-NLS-1$ setErrorMessage(Messages.getString("RebasePage.error.notAvailable")); //$NON-NLS-1$ } } catch (HgException e) { MercurialEclipsePlugin.logError(e); setErrorMessage(e.getLocalizedMessage()); } setPageComplete(true); } @Override public void setPageComplete(boolean complete) { if(complete){ try { if(HgStatusClient.isDirty(hgRoot) && !HgRebaseClient.isRebasing(hgRoot)){ setErrorMessage("Outstanding uncommitted changes! Rebase is not possible."); super.setPageComplete(false); return; } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } super.setPageComplete(complete); } private void createOptionsWidgets(Composite comp) { Group optionGroup = SWTWidgetHelper.createGroup(comp, Messages.getString("RebasePage.optionGroup.label"), 2, //$NON-NLS-1$ GridData.FILL_BOTH); collapseRevCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("RebasePage.option.collapse")); //$NON-NLS-1$ keepBranchesCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("RebasePage.option.keepBranches")); //$NON-NLS-1$ keepCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("RebasePage.option.keep")); //$NON-NLS-1$ if (MercurialEclipsePlugin.getDefault().getPreferenceStore() .getBoolean(MercurialPreferenceConstants.PREF_DEFAULT_REBASE_KEEP_BRANCHES)) { keepBranchesCheckBox.setSelection(true); } } private void createDestWidgets(Composite comp) { Group destGroup = SWTWidgetHelper.createGroup(comp, Messages.getString("RebasePage.destinationGroup.label"), 2, GridData.FILL_BOTH); //$NON-NLS-1$ destRevCheckBox = SWTWidgetHelper.createCheckBox(destGroup, Messages.getString("RebasePage.destinationCheckbox.label")); //$NON-NLS-1$ SelectionListener sl = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { destTable.setEnabled(destRevCheckBox.getSelection()); } }; destRevCheckBox.addSelectionListener(sl); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 150; gridData.minimumHeight = 50; destTable = new ChangesetTable(destGroup, hgRoot); destTable.setLayoutData(gridData); destTable.setEnabled(false); } private void createSrcWidgets(Composite comp) { Group srcGroup = SWTWidgetHelper.createGroup(comp, Messages.getString("RebasePage.sourceGroup.label"), 2, GridData.FILL_BOTH); //$NON-NLS-1$ sourceRevCheckBox = SWTWidgetHelper.createCheckBox(srcGroup, Messages.getString("RebasePage.source.label")); //$NON-NLS-1$ baseRevCheckBox = SWTWidgetHelper.createCheckBox(srcGroup, Messages.getString("RebasePage.base.label")); //$NON-NLS-1$ SelectionListener srcSl = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { srcTable.setEnabled(sourceRevCheckBox.getSelection() || baseRevCheckBox.getSelection()); if (sourceRevCheckBox.getSelection()) { baseRevCheckBox.setSelection(false); } } }; SelectionListener baseSl = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { srcTable.setEnabled(sourceRevCheckBox.getSelection() || baseRevCheckBox.getSelection()); if (baseRevCheckBox.getSelection()) { sourceRevCheckBox.setSelection(false); } } }; sourceRevCheckBox.addSelectionListener(srcSl); baseRevCheckBox.addSelectionListener(baseSl); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 150; gridData.minimumHeight = 50; srcTable = new ChangesetTable(srcGroup, hgRoot); srcTable.setLayoutData(gridData); srcTable.setEnabled(false); } /** * @return may return -1 if nothing is selected */ public int getSelectedSrcIndex() { ChangeSet selection = srcTable.getSelection(); return selection == null? -1 : selection.getChangesetIndex(); } public boolean isSourceRevSelected() { return sourceRevCheckBox.getSelection(); } public boolean isBaseRevSelected() { return baseRevCheckBox.getSelection(); } public boolean isDestRevSelected() { return destRevCheckBox.getSelection(); } public boolean isCollapseRevSelected() { return collapseRevCheckBox.getSelection(); } public boolean isKeepSelected() { return keepCheckBox.getSelection(); } public boolean isKeepBranchesSelected() { return keepBranchesCheckBox.getSelection(); } /** * @return may return -1 if nothing is selected */ public int getSelectedDestIndex() { ChangeSet selection = destTable.getSelection(); return selection == null? -1 : selection.getChangesetIndex(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/RebaseWizard.java000066400000000000000000000053071173713500500333050ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.RebaseOperation; /** * @author bastian */ public class RebaseWizard extends HgOperationWizard { private final HgRoot hgRoot; private RebasePage rebasePage; public RebaseWizard(HgRoot hgRoot) { super(Messages.getString("RebaseWizard.title")); //$NON-NLS-1$ this.hgRoot = hgRoot; setNeedsProgressMonitor(true); } @Override protected HgOperation initOperation() { int srcRev = -1; int baseRev = -1; int destRev = -1; if (rebasePage.isSourceRevSelected()) { srcRev = rebasePage.getSelectedSrcIndex(); } if (rebasePage.isBaseRevSelected()) { baseRev = rebasePage.getSelectedSrcIndex(); } if (rebasePage.isDestRevSelected()) { destRev = rebasePage.getSelectedDestIndex(); } boolean collapse = rebasePage.isCollapseRevSelected(); RebaseOperation op = new RebaseOperation(getContainer(), hgRoot, srcRev, destRev, baseRev, collapse, false, false); op.setKeepBranches(rebasePage.isKeepBranchesSelected()); op.setKeep(rebasePage.isKeepSelected()); return op; } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#operationSucceeded(com.vectrace.MercurialEclipse.actions.HgOperation) */ @Override protected boolean operationSucceeded(HgOperation op) throws HgException { if (op.getResult().length() != 0) { HgClients.getConsole().printMessage(op.getResult(), null); } return super.operationSucceeded(op); } @Override public void addPages() { rebasePage = new RebasePage("RebasePage", Messages.getString("RebaseWizard.rebasePage.title"), //$NON-NLS-1$ //$NON-NLS-2$ MercurialEclipsePlugin .getImageDescriptor("wizards/droplets-50.png"), //$NON-NLS-1$ Messages.getString("RebaseWizard.rebasePage.description"), //$NON-NLS-1$ hgRoot); initPage(rebasePage.getDescription(), rebasePage); addPage(rebasePage); } } SelectProjectsToSyncPage.java000066400000000000000000000164271173713500500355370ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.dialogs.ContainerCheckedTreeViewer; import org.eclipse.ui.model.WorkbenchLabelProvider; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.MercurialTeamProvider; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * The page allows to select projects located inside a hg root by root. * * @author Andrei */ public class SelectProjectsToSyncPage extends WizardPage { /** * @author Andrei */ public class HgRootsContentProvider implements ITreeContentProvider { public void dispose() { // ignore } public void inputChanged(Viewer viewer1, Object oldInput, Object newInput) { // ignore } public Object[] getElements(Object inputElement) { return getChildren(inputElement); } public Object[] getChildren(Object parentElement) { if(parentElement instanceof IWorkspaceRoot){ return roots.toArray(); } List list = byRoot.get(parentElement); return list == null? new Object[0] : list.toArray(); } public Object getParent(Object element) { if(element instanceof HgRoot){ return ResourcesPlugin.getWorkspace().getRoot(); } if(!(element instanceof IProject)){ return null; } Set>> entrySet = byRoot.entrySet(); for (Entry> entry : entrySet) { if(entry.getValue().contains(element)){ return entry.getKey(); } } return null; } public boolean hasChildren(Object element) { if(element instanceof IWorkspaceRoot){ return !roots.isEmpty(); } List list = byRoot.get(element); return list != null; } } private final IProject[] projects; private ContainerCheckedTreeViewer viewer; private final Set roots; private final Map> byRoot; private final HgRootsContentProvider contentProvider; protected SelectProjectsToSyncPage(IProject[] projects) { super("Select projects to Synchronize"); this.projects = projects; byRoot = ResourceUtils.groupByRoot(MercurialTeamProvider.getKnownHgProjects()); roots = Collections.unmodifiableSet(byRoot.keySet()); contentProvider = new HgRootsContentProvider(); } public void createControl(Composite parent) { Composite top = new Composite(parent, SWT.NULL); initializeDialogUnits(top); top.setLayout(new GridLayout()); GridData data = new GridData(GridData.FILL_BOTH); top.setLayoutData(data); setControl(top); Label label = new Label(top, SWT.NULL); label.setText("Available hg roots to Synchronize:"); viewer = createViewer(top); viewer.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { if(event.getChecked()){ Object element = event.getElement(); HgRoot root; if(element instanceof IProject){ root = (HgRoot) contentProvider.getParent(element); } else { root = (HgRoot) element; } Object[] elements = viewer.getCheckedElements(); for (Object object : elements) { if(object instanceof IProject){ HgRoot other = (HgRoot) contentProvider.getParent(object); if(!root.equals(other)) { viewer.setChecked(object, false); } } else { if(!root.equals(object)) { viewer.setChecked(object, false); } } } } setPageComplete(areAnyElementsChecked()); } }); setMessage("Select the projects or entire hg roots to be synchronized.\n" + "You can synchronize only one hg root at time."); } private ContainerCheckedTreeViewer createViewer(Composite parent) { ContainerCheckedTreeViewer treeViewer = new ContainerCheckedTreeViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.BORDER); GridData data = new GridData(GridData.FILL_BOTH); data.heightHint = 200; data.widthHint = 300; treeViewer.getControl().setLayoutData(data); treeViewer.setContentProvider(contentProvider); treeViewer.setLabelProvider(new WorkbenchLabelProvider()); treeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot()); Object[] selectedRoots = ResourceUtils.groupByRoot(Arrays.asList(projects)).keySet().toArray(); if(selectedRoots.length == 1) { // only pre-select projects if they are from the same root treeViewer.setCheckedElements(projects); } treeViewer.setExpandedElements(selectedRoots); return treeViewer; } /** * Allow the finish button to be pressed if there are checked resources. */ protected void updateOKStatus() { if(viewer != null) { setPageComplete(areAnyElementsChecked()); } else { setPageComplete(false); } } private boolean areAnyElementsChecked() { return viewer.getCheckedElements().length > 0; } public boolean isCreated(){ return viewer != null; } protected HgRoot[] getRoots() { return roots.toArray(new HgRoot[roots.size()]); } @SuppressWarnings("unchecked") public IProject[] getSelectedProjects() { Set selected = new HashSet(); Object[] checkedElements = viewer.getCheckedElements(); for (Object object : checkedElements) { if(viewer.getGrayed(object)){ continue; } if(object instanceof IProject){ selected.add((IProject) object); } else { selected.addAll((Collection) byRoot.get(object)); } } return selected.toArray(new IProject[selected.size()]); } public HgRoot getSelectedRoot() { Object[] checkedElements = viewer.getCheckedElements(); for (Object object : checkedElements) { if(object instanceof IProject){ return (HgRoot) contentProvider.getParent(object); } return (HgRoot) object; } return null; } @Override public boolean isPageComplete() { return areAnyElementsChecked(); } @Override public IWizardPage getNextPage() { ConfigurationWizardMainPage nextPage = (ConfigurationWizardMainPage) super.getNextPage(); nextPage.setProperties(MercurialParticipantSynchronizeWizard.initProperties(getSelectedRoot())); return nextPage; } } SelectRevisionPage.java000066400000000000000000000172651173713500500344050ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2010 Andrei Loskutov. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.dialogs.IPageChangingListener; import org.eclipse.jface.dialogs.PageChangingEvent; import org.eclipse.jface.wizard.IWizardContainer; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.widgets.Composite; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgIdentClient; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.dialogs.RevisionChooserPanel; import com.vectrace.MercurialEclipse.dialogs.RevisionChooserPanel.Settings; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.UpdateOperation; import com.vectrace.MercurialEclipse.storage.DataLoader; import com.vectrace.MercurialEclipse.storage.EmptyDataLoader; import com.vectrace.MercurialEclipse.storage.RootDataLoader; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * The page allows to choose the working directory version (revision/tag/head/branch/bookmark) * during the clone repository operation, after cloning te remote repository to the local disk, but * before updating working directory to selected version. * * @author Andrei */ public class SelectRevisionPage extends WizardPage { private RevisionChooserPanel panel; private HgRoot hgRoot; public SelectRevisionPage(String pageName) { super(pageName); setTitle("Select working directory revision"); setDescription("Select the revision to which the working directory will be updated after clone.\n" + "In case nothing is selected, the working directory will be updated to the latest " + "available changeset."); } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 1); setControl(composite); DataLoader loader = getDataLoader(); Settings settings = new Settings(); settings.highlightDefaultBranch = true; panel = new RevisionChooserPanel(composite, loader, settings); hookNextButtonListener(); } private DataLoader getDataLoader() { DataLoader dataLoader; if(hgRoot == null){ dataLoader = new EmptyDataLoader(); } else { dataLoader = new RootDataLoader(getHgRoot()); } return dataLoader; } public HgRoot getHgRoot() { return hgRoot; } public String getRevision(){ if(panel.calculateRevision()){ return panel.getRevision(); } return null; } /** * Set the focus on path fields when page becomes visible. */ @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { IWizardPage previousPage = getPreviousPage(); if(previousPage instanceof ClonePage){ ClonePage page = (ClonePage) previousPage; File directory = page.getDestinationDirectory(); setInitialSelection(directory); } else if(getWizard() instanceof ImportProjectsFromRepoWizard){ final ImportProjectsFromRepoWizard impWizard = (ImportProjectsFromRepoWizard) getWizard(); if(impWizard.getInitialPath() != null) { impWizard.getShell().getDisplay().asyncExec( new Runnable() { public void run() { setInitialSelection(impWizard.getInitialPath()); } }); } } } } public void setInitialSelection(File destinationDirectory) { if(hgRoot != null && hgRoot.equals(destinationDirectory)){ return; } try { hgRoot = new HgRoot(destinationDirectory); panel.update(getDataLoader()); setErrorMessage(null); } catch (IOException e) { MercurialEclipsePlugin.logError(e); setErrorMessage("Failed to find hg root at directory " + destinationDirectory); } } private void hookNextButtonListener() { IWizardContainer container = getWizard().getContainer(); if(!(container instanceof WizardDialog)){ return; } WizardDialog dialog = (WizardDialog) container; dialog.addPageChangingListener(new IPageChangingListener() { public void handlePageChanging(PageChangingEvent event) { if(!event.doit){ return; } if (event.getCurrentPage() == SelectRevisionPage.this && event.getTargetPage() != SelectRevisionPage.this.getPreviousPage()) { // Only fire if we're transitioning forward from this page. event.doit = nextButtonPressed(); } } }); } private boolean nextButtonPressed() { setErrorMessage(null); if(!panel.calculateRevision()){ return false; } String revision = panel.getRevision(); // TODO validate version string boolean ok = validateVersion(revision); if(!ok){ setErrorMessage("Unknown revision: '" + revision + "'!"); return false; } try { String [] revisionRef = new String []{revision}; if (hasDataLocally(revisionRef)) { // simply forward to the next page return true; } revision = revisionRef[0]; } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); setErrorMessage(e1.getLocalizedMessage()); return false; } try { // run update UpdateOperation updateOperation = new UpdateOperation(getContainer(), hgRoot, revision, false, false); getContainer().run(true, true, updateOperation); } catch (InvocationTargetException e) { return handle(e); } catch (InterruptedException e) { // operation cancelled by user return false; } return true; } private boolean handle(Exception e) { if (e.getCause() != null) { setErrorMessage(e.getCause().getLocalizedMessage()); } else { setErrorMessage(e.getLocalizedMessage()); } MercurialEclipsePlugin.logError(Messages .getString("CloneRepoWizard.updateOperationFailed"), e); return false; } private boolean validateVersion(String revision) { // TODO Auto-generated method stub return true; } /** * @param revisionRef one element array which should contain some version to check. * Note! This array will be misused to put in the requested local changeset index * @return true if the working directory is updated to the selected revision * @throws HgException */ private boolean hasDataLocally(String[] revisionRef) throws HgException { String revision = revisionRef[0]; boolean noRevSpecified = false; if(revision == null) { noRevSpecified = true; } else { revision = revision.trim(); if(revision.length() == 0){ noRevSpecified = true; } } ChangeSet expected; if(noRevSpecified){ // take latest available changeset // lookup one (latest) revision only Map> log = HgLogClient.getRootLog(hgRoot, 1, -1, false); Set set = log.get(hgRoot.getIPath()); if(set == null || set.isEmpty()){ return false; } expected = set.iterator().next(); } else { expected = HgLogClient.getChangeset(hgRoot, revision); } if(expected == null){ return false; } String changesetId = HgIdentClient.getCurrentChangesetId(hgRoot); revisionRef[0] = "" + expected.getChangesetIndex(); return expected.getChangeset().equals(changesetId); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/ServeWizard.java000066400000000000000000000036771173713500500332000ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.NullProgressMonitor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian * */ public class ServeWizard extends HgWizard { private HgRoot hgRoot; private ServeWizardPage servePage; private ServeWizard() { super(Messages.getString("ServeWizard.name")); //$NON-NLS-1$ setNeedsProgressMonitor(true); } public ServeWizard(HgRoot hgRoot) { this(); this.hgRoot = hgRoot; } @Override public void addPages() { super.addPages(); servePage = createPage(Messages.getString("ServeWizard.pageName"), Messages.getString("ServeWizard.pageTitle"), Messages //$NON-NLS-1$ //$NON-NLS-2$ .getString("NewLocationWizard.repoCreationPage.image"), //$NON-NLS-1$ Messages.getString("ServeWizard.pageDescription")); //$NON-NLS-1$ addPage(servePage); } /** * Creates a Page. */ protected ServeWizardPage createPage(String pageName, String pageTitle, String iconPath, String description) { this.servePage = new ServeWizardPage(pageName, pageTitle, MercurialEclipsePlugin.getImageDescriptor(iconPath), hgRoot); initPage(description, servePage); return servePage; } @Override public boolean performFinish() { boolean finish = servePage.finish(new NullProgressMonitor()); return finish && super.performFinish(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/ServeWizardPage.java000066400000000000000000000137251173713500500337700ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.commands.HgServeClient; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author bastian * */ public class ServeWizardPage extends HgWizardPage { private final HgRoot hgroot; private Text nameTextField; private Text prefixTextField; private Button defaultCheckBox; private Text portTextField; private Button ipv6CheckBox; private Button stdioCheckBox; private Text webdirConfTextField; public ServeWizardPage(String pageName, String title, ImageDescriptor image, HgRoot hgRoot) { super(pageName, title, image); this.hgroot = hgRoot; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 3); // server settings final Group defaultsGroup = SWTWidgetHelper.createGroup(composite, Messages.getString("ServeWizardPage.defaultsGroup.title")); //$NON-NLS-1$ final Group settingsGroup = SWTWidgetHelper.createGroup(composite, Messages.getString("ServeWizardPage.settingsGroup.title")); //$NON-NLS-1$ settingsGroup.setEnabled(false); this.defaultCheckBox = SWTWidgetHelper.createCheckBox(defaultsGroup, Messages.getString("ServeWizardPage.defaultCheckBox.title")); //$NON-NLS-1$ this.defaultCheckBox.setSelection(true); final Label portLabel = SWTWidgetHelper.createLabel(settingsGroup, Messages.getString("ServeWizardPage.portLabel.title")); //$NON-NLS-1$ portLabel.setEnabled(false); portTextField = SWTWidgetHelper.createTextField(settingsGroup); portTextField.setEnabled(false); portTextField.setText(Messages.getString("ServeWizardPage.portTextField.defaultValue")); //$NON-NLS-1$ portTextField.addVerifyListener(new VerifyListener() { public void verifyText(VerifyEvent e) { String string = e.text; char[] chars = new char[string.length()]; string.getChars(0, chars.length, chars, 0); for (int i = 0; i < chars.length; i++) { if (!('0' <= chars[i] && chars[i] <= '9')) { e.doit = false; return; } } } }); final Label nameLabel = SWTWidgetHelper.createLabel(settingsGroup, Messages.getString("ServeWizardPage.nameLabel.title")); //$NON-NLS-1$ nameLabel.setEnabled(false); this.nameTextField = SWTWidgetHelper.createTextField(settingsGroup); this.nameTextField.setEnabled(false); final Label prefixLabel = SWTWidgetHelper.createLabel(settingsGroup, Messages.getString("ServeWizardPage.prefixLabel.title")); //$NON-NLS-1$ prefixLabel.setEnabled(false); this.prefixTextField = SWTWidgetHelper.createTextField(settingsGroup); this.prefixTextField.setEnabled(false); final Label webdirLabel = SWTWidgetHelper.createLabel(settingsGroup, Messages.getString("ServeWizardPage.webdirLabel.title")); //$NON-NLS-1$ webdirLabel.setEnabled(false); this.webdirConfTextField = SWTWidgetHelper.createTextField(settingsGroup); this.webdirConfTextField.setEnabled(false); this.stdioCheckBox = SWTWidgetHelper.createCheckBox(settingsGroup, Messages.getString("ServeWizardPage.stdioCheckBox.title")); //$NON-NLS-1$ this.stdioCheckBox.setEnabled(false); this.ipv6CheckBox = SWTWidgetHelper.createCheckBox(settingsGroup, Messages.getString("ServeWizardPage.ipv6CheckBox.title")); //$NON-NLS-1$ this.ipv6CheckBox.setEnabled(false); SelectionListener defaultCheckBoxListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { settingsGroup.setEnabled(!defaultCheckBox.getSelection()); portLabel.setEnabled(!defaultCheckBox.getSelection()); portTextField.setEnabled(!defaultCheckBox.getSelection()); nameLabel.setEnabled(!defaultCheckBox.getSelection()); nameTextField.setEnabled(!defaultCheckBox.getSelection()); prefixLabel.setEnabled(!defaultCheckBox.getSelection()); prefixTextField.setEnabled(!defaultCheckBox.getSelection()); webdirLabel.setEnabled(!defaultCheckBox.getSelection()); webdirConfTextField.setEnabled(!defaultCheckBox.getSelection()); stdioCheckBox.setEnabled(!defaultCheckBox.getSelection()); ipv6CheckBox.setEnabled(!defaultCheckBox.getSelection()); } }; this.defaultCheckBox.addSelectionListener(defaultCheckBoxListener); setControl(composite); setPageComplete(true); } @Override public boolean finish(IProgressMonitor monitor) { super.finish(monitor); // call hg try { boolean serveStarted = HgServeClient.serve(hgroot, Integer.parseInt(portTextField .getText()), prefixTextField.getText(), nameTextField .getText(), webdirConfTextField.getText(), stdioCheckBox .getSelection(), ipv6CheckBox.getSelection()); if(!serveStarted){ setErrorMessage("Hg server could not be started. Probably port " + portTextField.getText() + " is already in use"); } return serveStarted; } catch (NumberFormatException e) { setErrorMessage("Invalid port text"); return false; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/SignWizard.java000066400000000000000000000037471173713500500330120ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.wizard.Wizard; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.HgRoot; public class SignWizard extends Wizard { private final SignWizardPage page; public SignWizard(HgRoot hgRoot) { ImageDescriptor image = MercurialEclipsePlugin .getImageDescriptor(Messages.getString("SignWizard.signWizardPage.image")); //$NON-NLS-1$ page = new SignWizardPage(Messages.getString("SignWizard.signWizardPage.name"), Messages.getString("SignWizard.signWizardPage.title"), image, //$NON-NLS-1$ //$NON-NLS-2$ Messages.getString("SignWizard.signWizardPage.description"), hgRoot); //$NON-NLS-1$ IDialogSettings workbenchSettings = MercurialEclipsePlugin.getDefault().getDialogSettings(); IDialogSettings section = workbenchSettings.getSection("SignWizard"); //$NON-NLS-1$ if (section == null) { section = workbenchSettings.addNewSection("SignWizard"); //$NON-NLS-1$ } setDialogSettings(section); } @Override public boolean performFinish() { return page.finish(new NullProgressMonitor()); } @Override public void addPages() { super.addPages(); addPage(page); } @Override public boolean canFinish() { return super.canFinish() && page.isPageComplete(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/SignWizardPage.java000066400000000000000000000157751173713500500336130ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.extensions.HgSignClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author Bastian Doetsch * */ public class SignWizardPage extends HgWizardPage { /** * GnuPG key prefix, from the "gpg --list-secret-keys" command output: * "sec 2048R/XXXXXXXX 2009-09-16 [expires: 2010-09-16]" */ private static final String KEY_PREFIX = "sec"; private final HgRoot hgRoot; private Text userTextField; private Combo keyCombo; private Button localCheckBox; private Button forceCheckBox; private Button noCommitCheckBox; private ChangesetTable changesetTable; private Text messageTextField; private Text passTextField; private boolean gotGPGkeys; public SignWizardPage(String pageName, String title, ImageDescriptor titleImage, String description, HgRoot hgRoot) { super(pageName, title, titleImage, description); this.hgRoot = hgRoot; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); // list view of changesets Group changeSetGroup = SWTWidgetHelper.createGroup( composite, Messages.getString("SignWizardPage.changeSetGroup.title"), //$NON-NLS-1$ GridData.FILL_BOTH); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 200; gridData.minimumHeight = 50; changesetTable = new ChangesetTable(changeSetGroup, hgRoot); changesetTable.setLayoutData(gridData); changesetTable.setEnabled(true); SelectionListener listener = new SelectionListener() { public void widgetSelected(SelectionEvent event) { ChangeSet cs = changesetTable.getSelection(); messageTextField.setText(Messages.getString( "SignWizardPage.messageTextField.text") //$NON-NLS-1$ + " " + cs.toString()); //$NON-NLS-1$ if (gotGPGkeys) { setPageComplete(true); } } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; changesetTable.addSelectionListener(listener); // now the fields for user data Group userGroup = SWTWidgetHelper.createGroup(composite, Messages.getString("SignWizardPage.userGroup.title")); //$NON-NLS-1$ SWTWidgetHelper.createLabel(userGroup, Messages.getString("SignWizardPage.userLabel.text")); //$NON-NLS-1$ userTextField = SWTWidgetHelper.createTextField(userGroup); userTextField.setText(HgCommitMessageManager.getDefaultCommitName(hgRoot)); SWTWidgetHelper.createLabel(userGroup, Messages.getString("SignWizardPage.keyLabel.text")); //$NON-NLS-1$ keyCombo = SWTWidgetHelper.createCombo(userGroup); SWTWidgetHelper.createLabel(userGroup, Messages.getString("SignWizardPage.passphraseLabel.text")); //$NON-NLS-1$ passTextField = SWTWidgetHelper.createTextField(userGroup); // passTextField.setEchoChar('*'); passTextField .setText(Messages.getString("SignWizardPage.passTextField.text")); //$NON-NLS-1$ passTextField.setEnabled(false); // now the options Group optionGroup = SWTWidgetHelper.createGroup(composite, Messages.getString("SignWizardPage.optionGroup.title")); //$NON-NLS-1$ localCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("SignWizardPage.localCheckBox.text")); //$NON-NLS-1$ forceCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("SignWizardPage.forceCheckBox.text")); //$NON-NLS-1$ noCommitCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("SignWizardPage.noCommitCheckBox.text")); //$NON-NLS-1$ SWTWidgetHelper.createLabel(optionGroup, Messages.getString("SignWizardPage.commitLabel.text")); //$NON-NLS-1$ messageTextField = SWTWidgetHelper.createTextField(optionGroup); messageTextField.setText(Messages.getString("SignWizardPage.messageTextField.defaultText")); //$NON-NLS-1$ populateKeyCombo(keyCombo); setControl(composite); } private void populateKeyCombo(Combo combo) { try { String keys = HgSignClient.getPrivateKeyList(hgRoot); if (keys.indexOf("\n") == -1) { //$NON-NLS-1$ combo.add(keys); } else { String[] items = keys.split("\n"); //$NON-NLS-1$ for (String string : items) { string = string.trim(); if (string.startsWith(KEY_PREFIX)) { string = string.substring(KEY_PREFIX.length()).trim(); if(string.length() > 0) { combo.add(string); } } } } gotGPGkeys = true; } catch (HgException e) { gotGPGkeys = false; combo.add(Messages.getString("SignWizardPage.errorLoadingGpgKeys")); //$NON-NLS-1$ setPageComplete(false); MercurialEclipsePlugin.logError(e); } if(combo.getItemCount() > 0) { combo.setText(combo.getItem(0)); } } @Override public boolean finish(IProgressMonitor monitor) { ChangeSet cs = changesetTable.getSelection(); String key = keyCombo.getText(); if(cs == null){ setErrorMessage("Please select one changeset"); return false; } if(key.trim().length() == 0 || key.indexOf(" ") < 0){ setErrorMessage("Please select valid key"); return false; } key = key.substring(key.indexOf("/") + 1, key.indexOf(" ")); //$NON-NLS-1$ //$NON-NLS-2$ String msg = messageTextField.getText(); String user = userTextField.getText(); String pass = passTextField.getText(); boolean local = localCheckBox.getSelection(); boolean force = forceCheckBox.getSelection(); boolean noCommit = noCommitCheckBox.getSelection(); try { HgSignClient.sign(hgRoot, cs, key, msg, user, local, force, noCommit, pass); } catch (HgException e) { MessageDialog.openInformation(getShell(), Messages.getString("SignWizardPage.errorSigning"), //$NON-NLS-1$ e.getMessage()); MercurialEclipsePlugin.logError(e); return false; } return true; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/StripWizard.java000066400000000000000000000040011173713500500331730ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - modifications *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author bastian */ public class StripWizard extends HgWizard { private final HgRoot hgRoot; private final ChangeSet changeSet; /** * Constructor for wizard with preselected change set */ public StripWizard(HgRoot hgRoot, ChangeSet changeSet) { super(Messages.getString("StripWizard.title")); //$NON-NLS-1$ setNeedsProgressMonitor(true); this.hgRoot = hgRoot; this.changeSet = changeSet; } @Override public void addPages() { super.addPages(); page = createPage( Messages.getString("StripWizard.page.name"), //$NON-NLS-1$ Messages.getString("StripWizard.pageTitle"), //$NON-NLS-1$ null, Messages.getString("StripWizard.page.description.1") //$NON-NLS-1$ + Messages.getString("StripWizard.page.description.2")); //$NON-NLS-1$ addPage(page); } /** * Creates a ConfigurationWizardPage. */ protected HgWizardPage createPage(String pageName, String pageTitle, String iconPath, String description) { this.page = new StripWizardPage(pageName, pageTitle, MercurialEclipsePlugin.getImageDescriptor(iconPath), hgRoot, changeSet); initPage(description, page); return page; } @Override public boolean performFinish() { return super.performFinish(); } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/StripWizardPage.java000066400000000000000000000116761173713500500340100ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes * Ilya Ivanov (Intland) - modofications *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.HgParentClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.commands.extensions.HgStripClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; /** * @author bastian */ public class StripWizardPage extends HgWizardPage { private ChangesetTable changesetTable; private Button keepCheckBox; private ChangeSet stripRevision; private final HgRoot hgRoot; private Button backupCheckBox; private Button forceCheckBox; private final ChangeSet changeSet; public StripWizardPage(String pageName, String title, ImageDescriptor image, HgRoot hgRoot, ChangeSet changeSet) { super(pageName, title, image); this.hgRoot = hgRoot; this.changeSet = changeSet; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); // list view of changesets Group changeSetGroup = SWTWidgetHelper.createGroup(composite, Messages.getString("StripWizardPage.changeSetGroup.title"), GridData.FILL_BOTH); //$NON-NLS-1$ changesetTable = new ChangesetTable(changeSetGroup, hgRoot); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 200; gridData.minimumHeight = 50; changesetTable.setLayoutData(gridData); SelectionListener listener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { stripRevision = changesetTable.getSelection(); setPageComplete(true); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; try { changesetTable.highlightParents(HgParentClient.getParents(hgRoot)); } catch (HgException e1) { MercurialEclipsePlugin.logError(e1); } changesetTable.addSelectionListener(listener); changesetTable.setEnabled(true); changesetTable.setSelection(changeSet); // now the options Group optionGroup = SWTWidgetHelper.createGroup(composite, Messages.getString("StripWizardPage.optionsGroup.title")); //$NON-NLS-1$ // backup backupCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("StripWizardPage.backupCheckBox.title")); //$NON-NLS-1$ backupCheckBox.setSelection(true); keepCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages .getString("StripWizardPage.keep.title")); //$NON-NLS-1$ keepCheckBox.setSelection(false); forceCheckBox = SWTWidgetHelper.createCheckBox(optionGroup, Messages.getString("StripWizardPage.force.title")); //$NON-NLS-1$ forceCheckBox.addSelectionListener(listener); setControl(composite); setPageComplete(true); } @Override public void setPageComplete(boolean complete) { if(complete){ try { setErrorMessage(null); if(HgStatusClient.isDirty(hgRoot) && !forceCheckBox.getSelection()){ setErrorMessage("Outstanding uncommitted changes! Strip is not possible."); super.setPageComplete(false); return; } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } super.setPageComplete(complete); } @Override public boolean finish(IProgressMonitor monitor) { super.finish(monitor); stripRevision = changesetTable.getSelection(); try { String result = HgStripClient.strip(hgRoot, keepCheckBox.getSelection(), backupCheckBox .getSelection(), forceCheckBox.getSelection(), stripRevision); HgClients.getConsole().printMessage(result, null); } catch (HgException e) { MessageDialog.openError(getShell(), Messages.getString("StripWizardPage.errorCallingStrip"), e //$NON-NLS-1$ .getMessage()); MercurialEclipsePlugin.logError(e); return false; } return true; } } TransplantOptionsPage.java000066400000000000000000000205561173713500500351460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * @author bastian */ public class TransplantOptionsPage extends HgWizardPage { private final HgRoot hgRoot; private boolean merge; private String mergeNodeId; private boolean prune; private String pruneNodeId; private String filter; private boolean filterChangesets; private Button filterChangesetsCheckBox; private Text filterTextField; private ChangesetTable mergeNodeIdTable; private Button mergeCheckBox; private Button pruneCheckBox; private ChangesetTable pruneNodeIdTable; public TransplantOptionsPage(String pageName, String title, ImageDescriptor titleImage, HgRoot hgRoot) { super(pageName, title, titleImage); this.hgRoot = hgRoot; } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); addOtherOptionsGroup(composite); setControl(composite); setPageComplete(true); validatePage(); } @Override public void setPageComplete(boolean complete) { if(complete){ try { if(HgStatusClient.isDirty(hgRoot)){ setErrorMessage("Outstanding uncommitted changes! Transplant is not possible."); super.setPageComplete(false); return; } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } super.setPageComplete(complete); } private void addOtherOptionsGroup(Composite composite) { createMergeGroup(composite); createPruneGroup(composite); createFilterGroup(composite); } private void createFilterGroup(Composite composite) { Group filterGroup = SWTWidgetHelper.createGroup(composite, Messages .getString("TransplantOptionsPage.filtergroup.title")); //$NON-NLS-1$ filterChangesetsCheckBox = SWTWidgetHelper.createCheckBox(filterGroup, Messages.getString("TransplantOptionsPage.filterCheckBox.title")); //$NON-NLS-1$ SelectionListener filterChangesetsCheckBoxListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { filterChangesets = filterChangesetsCheckBox.getSelection(); filterTextField.setEnabled(filterChangesets); validatePage(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; filterChangesetsCheckBox.addSelectionListener(filterChangesetsCheckBoxListener); SWTWidgetHelper.createLabel(filterGroup, Messages.getString("TransplantOptionsPage.filterLabel.title")); //$NON-NLS-1$ filterTextField = SWTWidgetHelper.createTextField(filterGroup); filterTextField.setEnabled(false); ModifyListener filterListener = new ModifyListener() { public void modifyText(ModifyEvent e) { filter = filterTextField.getText().trim(); validatePage(); } }; filterTextField.addModifyListener(filterListener); } private void createPruneGroup(Composite composite) { // prune Group pruneGroup = SWTWidgetHelper.createGroup(composite, Messages .getString("TransplantOptionsPage.pruneGroup.title")); //$NON-NLS-1$ pruneCheckBox = SWTWidgetHelper.createCheckBox(pruneGroup, Messages .getString("TransplantOptionsPage.pruneCheckBox.title")); //$NON-NLS-1$ SelectionListener pruneCheckBoxListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { prune = pruneCheckBox.getSelection(); pruneNodeIdTable.setEnabled(prune); populatePruneNodeIdTable(); validatePage(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; pruneCheckBox.addSelectionListener(pruneCheckBoxListener); pruneNodeIdTable = new ChangesetTable(pruneGroup, hgRoot); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 200; gridData.minimumHeight = 50; pruneNodeIdTable.setLayoutData(gridData); pruneNodeIdTable.setEnabled(false); SelectionListener pruneTableListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { ChangeSet changeSet = pruneNodeIdTable.getSelection(); pruneNodeId = changeSet == null? null : changeSet.getChangeset(); validatePage(); } }; pruneNodeIdTable.addSelectionListener(pruneTableListener); } private void createMergeGroup(Composite composite) { // other options Group mergeGroup = SWTWidgetHelper.createGroup(composite, Messages .getString("TransplantOptionsPage.mergeGroup.title")); //$NON-NLS-1$ // merge at revision mergeCheckBox = SWTWidgetHelper.createCheckBox(mergeGroup, Messages .getString("TransplantOptionsPage.mergeCheckBox.title")); //$NON-NLS-1$ SelectionListener mergeCheckBoxListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { merge = mergeCheckBox.getSelection(); mergeNodeIdTable.setEnabled(merge); populateMergeNodeIdTable(); validatePage(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; mergeCheckBox.addSelectionListener(mergeCheckBoxListener); mergeNodeIdTable = new ChangesetTable(mergeGroup, hgRoot); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 200; gridData.minimumHeight = 50; mergeNodeIdTable.setLayoutData(gridData); mergeNodeIdTable.setEnabled(false); SelectionListener mergeTableListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { ChangeSet changeSet = mergeNodeIdTable.getSelection(); mergeNodeId = changeSet == null? null : changeSet.getChangeset(); validatePage(); } }; mergeNodeIdTable.addSelectionListener(mergeTableListener); populateMergeNodeIdTable(); } private void validatePage() { boolean valid = true; try { if (merge) { valid &= !StringUtils.isEmpty(mergeNodeId); if(!valid){ setErrorMessage("Please select merge changeset!"); return; } } if (prune) { valid &= !StringUtils.isEmpty(pruneNodeId); if(!valid){ setErrorMessage("Please select prune changeset!"); return; } } if (filterChangesets) { valid &= !StringUtils.isEmpty(filter); if(!valid){ setErrorMessage("Please enter changeset filter!"); return; } } } finally { if(valid){ setErrorMessage(null); } if(isPageComplete() ^ valid) { setPageComplete(valid); } } } private void populatePruneNodeIdTable() { pruneNodeIdTable.setStrategy(new ChangesetTable.PrefetchedStrategy( ((TransplantPage) getPreviousPage()).getChangesets())); } private void populateMergeNodeIdTable() { mergeNodeIdTable.setStrategy(new ChangesetTable.PrefetchedStrategy( ((TransplantPage) getPreviousPage()).getChangesets())); } public boolean isMerge() { return merge; } public String getMergeNodeId() { return mergeNodeId; } public boolean isPrune() { return prune; } public String getPruneNodeId() { return pruneNodeId; } public boolean isFilterChangesets() { return filterChangesets; } public String getFilter() { return filter; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/TransplantPage.java000066400000000000000000000315571173713500500336540ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Adam Berkes (Intland) - various fixes * Andrei Loskutov - bugfixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.SortedSet; import java.util.Timer; import java.util.TimerTask; import java.util.TreeSet; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.HgBranchClient; import com.vectrace.MercurialEclipse.commands.HgStatusClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; import com.vectrace.MercurialEclipse.team.cache.IncomingChangesetCache; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.ui.ChangesetTable.PrefetchedStrategy; import com.vectrace.MercurialEclipse.utils.StringUtils; /** * @author bastian * */ public class TransplantPage extends ConfigurationWizardMainPage { /** changesets sorted in the ascending revision order */ private final SortedSet selectedChangesets; private boolean branch; private boolean all; private String branchName; private ChangesetTable changesetTable; private Button branchCheckBox; private Combo branchNameCombo; private Button allCheckBox; public TransplantPage(String pageName, String title, ImageDescriptor titleImage, HgRoot hgRoot) { super(pageName, title, titleImage); setHgRoot(hgRoot); selectedChangesets = new TreeSet(); } @Override public void createControl(Composite parent) { super.createControl(parent); Composite composite = (Composite) getControl(); ModifyListener urlModifyListener = new ModifyListener() { public void modifyText(ModifyEvent e) { try { HgRepositoryLocationManager repoManager = MercurialEclipsePlugin.getRepoManager(); getIncoming(repoManager.getRepoLocation(getUrlText())); } catch (HgException e1) { clearChangesets(); // bad URI? setErrorMessage(e1.getMessage()); setPageComplete(false); return; } } }; getUrlCombo().addModifyListener(urlModifyListener); addBranchGroup(composite); addChangesetGroup(composite); if (MercurialEclipsePlugin.getDefault().getPreferenceStore().getBoolean( MercurialPreferenceConstants.PREF_DEFAULT_TRANSPLANT_FROM_LOCAL_BRANCHES)) { setUseLocalBranch(true); } setPageComplete(true); validatePage(); } @Override public void setPageComplete(boolean complete) { if(complete){ try { if(HgStatusClient.isDirty(getHgRoot())){ setErrorMessage("Outstanding uncommitted changes! Transplant is not possible."); super.setPageComplete(false); return; } } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } super.setPageComplete(complete); } /** * @see com.vectrace.MercurialEclipse.wizards.ConfigurationWizardMainPage#finish(org.eclipse.core.runtime.IProgressMonitor) */ @Override public boolean finish(IProgressMonitor monitor) { MercurialEclipsePlugin.getDefault().getPreferenceStore().setValue( MercurialPreferenceConstants.PREF_DEFAULT_TRANSPLANT_FROM_LOCAL_BRANCHES, branchCheckBox.getSelection()); return super.finish(monitor); } private void validatePage() { boolean valid = true; setMessage(null, IMessageProvider.WARNING); try { if (branch) { valid &= !StringUtils.isEmpty(branchName); if(!valid){ setErrorMessage("Please select local branch!"); return; } // if (!all) { // valid &= selectedChangesets.size() == 1 // && Branch.same(branchName, selectedChangesets.first().getBranch()); // if(!valid){ // setErrorMessage("Please select exact one changeset if transplanting " // + "not all changesets from the local branch!"); // return; // } // } if (valid && !all && selectedChangesets.size() == 0) { setMessage("No changeset selected.", IMessageProvider.WARNING); return; } } else { valid &= !StringUtils.isEmpty(getUrlText()); if(!valid){ setErrorMessage("Please provide valid repository location!"); return; } valid &= selectedChangesets.size() > 0; if(!valid){ setErrorMessage("Please select at least one changeset!"); return; } } } finally { if(valid){ setErrorMessage(null); } if(isPageComplete() ^ valid) { setPageComplete(valid); } } } private void addBranchGroup(Composite composite) { createBranchCheckBox(composite); // now the branch group Group branchGroup = SWTWidgetHelper.createGroup(composite, Messages .getString("TransplantPage.branchGroup.title")); //$NON-NLS-1$ createAllCheckBox(branchGroup); createBranchNameCombo(branchGroup); } private void createBranchNameCombo(Group branchGroup) { SWTWidgetHelper.createLabel(branchGroup, Messages .getString("TransplantPage.branchLabel.title")); //$NON-NLS-1$ branchNameCombo = SWTWidgetHelper.createCombo(branchGroup); branchNameCombo.setEnabled(false); populateBranchNameCombo(); SelectionListener branchNameComboListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { branchName = branchNameCombo.getText(); if (Branch.isDefault(branchName)) { branchName = Branch.DEFAULT; } getLocalFromBranch(branchName); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; branchNameCombo.addSelectionListener(branchNameComboListener); } private void createAllCheckBox(Group branchGroup) { allCheckBox = SWTWidgetHelper.createCheckBox(branchGroup, Messages .getString("TransplantPage.allCheckBox.title")); //$NON-NLS-1$ allCheckBox.setEnabled(false); SelectionListener allCheckBoxListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { all = allCheckBox.getSelection(); changesetTable.setEnabled(!all); if(all){ changesetTable.clearSelection(); selectedChangesets.clear(); } validatePage(); } }; allCheckBox.addSelectionListener(allCheckBoxListener); } private void createBranchCheckBox(Composite parent) { branchCheckBox = SWTWidgetHelper.createCheckBox(parent, Messages .getString("TransplantPage.branchCheckBox.title")); //$NON-NLS-1$ SelectionListener branchCheckBoxListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { setUseLocalBranch(branchCheckBox.getSelection()); validatePage(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; branchCheckBox.addSelectionListener(branchCheckBoxListener); } protected void setUseLocalBranch(boolean useLocalBranch) { this.branch = useLocalBranch; if (branchCheckBox.getSelection() != useLocalBranch) { branchCheckBox.setSelection(useLocalBranch); } setUrlGroupEnabled(!useLocalBranch); getUserCombo().setEnabled(!useLocalBranch); passwordText.setEnabled(!useLocalBranch); allCheckBox.setEnabled(useLocalBranch); branchNameCombo.setEnabled(useLocalBranch); clearChangesets(); getUrlCombo().deselectAll(); if (useLocalBranch) { branchName = null; branchNameCombo.deselectAll(); } } private void addChangesetGroup(Composite composite) { // table of changesets Group changeSetGroup = SWTWidgetHelper.createGroup( composite, Messages.getString("TransplantPage.changesetGroup.title"), GridData.FILL_BOTH); //$NON-NLS-1$ GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 200; gridData.minimumHeight = 50; changesetTable = new ChangesetTable(changeSetGroup, true); changesetTable.setLayoutData(gridData); changesetTable.setEnabled(true); SelectionListener changeSetTableListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { setErrorMessage(null); selectedChangesets.clear(); ChangeSet[] changeSets = changesetTable.getSelections(); if(changeSets != null && changeSets.length != 0) { selectedChangesets.addAll(Arrays.asList(changeSets)); } validatePage(); } }; changesetTable.addSelectionListener(changeSetTableListener); } private void populateBranchNameCombo() { try { Branch[] branches = HgBranchClient.getBranches(getHgRoot()); for (Branch myBranch : branches) { branchNameCombo.add(myBranch.getName()); } } catch (HgException e) { MercurialEclipsePlugin.showError(e); MercurialEclipsePlugin.logError(e); } } public boolean isBranch() { return branch; } public SortedSet getSelectedChangesets() { return selectedChangesets; } public String getBranchName() { return branchName; } public boolean isAll() { return all; } public ChangeSet[] getChangesets() { ChangesetTable.Strategy strategy = changesetTable.getStrategy(); if (strategy == null) { return new ChangeSet[0]; } return strategy.getFetched(); } private void getIncoming(final IHgRepositoryLocation repoLocation) { clearChangesets(); FetchChangesetsOperation op = new FetchChangesetsOperation() { @Override protected Set fetchChanges(IProgressMonitor monitor) throws HgException { return IncomingChangesetCache.getInstance().getChangeSets( getHgRoot(), repoLocation, null); } }; try { getContainer().run(true, true, op); SortedSet changesets = new TreeSet(Collections.reverseOrder()); changesets.addAll(op.getChanges()); changesetTable.setStrategy(new PrefetchedStrategy(changesets.toArray(new ChangeSet[changesets.size()]))); validatePage(); } catch (InvocationTargetException e) { setErrorMessage(Messages.getString("TransplantPage.errorLoadChangesets") + ": " + e.getCause().getMessage()); //$NON-NLS-1$ setPageComplete(false); MercurialEclipsePlugin.logError(e.getCause()); } catch (InterruptedException e) { MercurialEclipsePlugin.logError(e); validatePage(); } } private void getLocalFromBranch(final String branchName1) { clearChangesets(); changesetTable.setStrategy(new ChangesetTable.BranchStrategy(getHgRoot(), branchName1)); } private void clearChangesets() { changesetTable.setStrategy(null); selectedChangesets.clear(); } private abstract static class FetchChangesetsOperation implements IRunnableWithProgress { Set changes = new HashSet(); Set getChanges(){ return changes; } public final void run(final IProgressMonitor monitor) throws InvocationTargetException { monitor.beginTask("Retrieving changesets...", IProgressMonitor.UNKNOWN); //$NON-NLS-1$ // Timer which is used to monitor the monitor cancellation Timer t = new Timer("Fetch data watcher", false); // only start timer if the operation is NOT running in the UI thread if(Display.getCurrent() == null){ final Thread threadToCancel = Thread.currentThread(); t.scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (monitor.isCanceled() && !threadToCancel.isInterrupted()) { threadToCancel.interrupt(); } } }, 500, 50); } try { changes = fetchChanges(monitor); } catch (HgException e) { throw new InvocationTargetException(e); } finally { t.cancel(); } } protected abstract Set fetchChanges(IProgressMonitor monitor) throws HgException; } } TransplantWizard.java000066400000000000000000000105011173713500500341430ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Bastian Doetsch implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import org.eclipse.core.runtime.NullProgressMonitor; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.extensions.HgTransplantClient; import com.vectrace.MercurialEclipse.commands.extensions.HgTransplantClient.TransplantOptions; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.Branch; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; import com.vectrace.MercurialEclipse.operations.TransplantOperation; import com.vectrace.MercurialEclipse.storage.HgRepositoryLocationManager; /** * @author bastian * */ public class TransplantWizard extends HgOperationWizard { private final HgRoot hgRoot; public TransplantWizard(HgRoot hgRoot) { super(Messages.getString("TransplantWizard.title")); //$NON-NLS-1$ setNeedsProgressMonitor(true); this.hgRoot = hgRoot; } @Override public void addPages() { super.addPages(); TransplantPage transplantPage = new TransplantPage(Messages.getString("TransplantWizard.transplantPage.name"), //$NON-NLS-1$ Messages.getString("TransplantWizard.transplantPage.title"), null, hgRoot); //$NON-NLS-1$ initPage(Messages.getString("TransplantWizard.transplantPage.description"), //$NON-NLS-1$ transplantPage); transplantPage.setShowCredentials(true); page = transplantPage; addPage(page); TransplantOptionsPage optionsPage = new TransplantOptionsPage( Messages.getString("TransplantWizard.optionsPage.name"), Messages.getString("TransplantWizard.optionsPage.title"), null, hgRoot); //$NON-NLS-1$ initPage(Messages.getString("TransplantWizard.optionsPage.description"), optionsPage); //$NON-NLS-1$ addPage(optionsPage); } /** * @throws HgException * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#initOperation() */ @Override protected HgOperation initOperation() throws HgException { page.finish(new NullProgressMonitor()); HgRepositoryLocationManager repoManager = MercurialEclipsePlugin.getRepoManager(); TransplantOptions options = createOptions(); IHgRepositoryLocation repo; if (options.branch) { repo = null; } else { repo = repoManager.fromProperties(hgRoot, page.getProperties()); } return new TransplantOperation(getContainer(), hgRoot, options, repo); } @Override protected boolean operationSucceeded(HgOperation operation) throws HgException { TransplantOperation top = (TransplantOperation) operation; // It appears good. Stash the repo location. if (top.getRepo() != null) { MercurialEclipsePlugin.getRepoManager().addRepoLocation(hgRoot, top.getRepo()); } return super.operationSucceeded(operation); } private HgTransplantClient.TransplantOptions createOptions() { HgTransplantClient.TransplantOptions options = new HgTransplantClient.TransplantOptions(); TransplantPage transplantPage = (TransplantPage) page; TransplantOptionsPage optionsPage = (TransplantOptionsPage) page.getNextPage(); options.all = transplantPage.isAll(); options.branch = transplantPage.isBranch(); if (options.branch && Branch.isDefault(transplantPage.getBranchName())) { // branch name, as command parameter is default if empty options.branchName = Branch.DEFAULT; } else { options.branchName = transplantPage.getBranchName(); } options.filter = optionsPage.getFilter(); options.filterChangesets = optionsPage.isFilterChangesets(); options.merge = optionsPage.isMerge(); options.mergeNodeId = optionsPage.getMergeNodeId(); options.nodes = transplantPage.getSelectedChangesets(); options.prune = optionsPage.isPrune(); options.pruneNodeId = optionsPage.getPruneNodeId(); return options; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/messages.properties000066400000000000000000000424661173713500500340140ustar00rootroot00000000000000ImportOptionsPage.base=Base path ImportOptionsPage.comments=Comments: ImportOptionsPage.date=Date: ImportOptionsPage.exact=Apply patch to the nodes from which it was generated ImportOptionsPage.force=Force ImportOptionsPage.noCommit=Don't commit, just update the working directory ImportOptionsPage.strip=Strip dir parts (numeric) ImportOptionsPage.user=User: ImportPatchWizard.WizardTitle=Import Patch Wizard ImportPatchWizard.pageName=ImportPatchPage ImportPatchWizard.pageTitle=Import changes ImportPatchWizard.pageDescription=Select a patch file to import from ImportPatchWizard.conflict=A conflict occurred applying the patch: ExportOptionsPage.context=Context: ExportOptionsPage.function=Show which function each change is in ExportOptionsPage.git=Git extended diff format ExportOptionsPage.ignoreAllSpace=Ignore white space when comparing lines ExportOptionsPage.ignoreBlankLines=Ignore changes whose lines are all blank ExportOptionsPage.ignoreSpaceChange=Ignore changes in the amount of white space ExportOptionsPage.noDate=Don't include dates in diff headers ExportOptionsPage.rev=Revision ExportOptionsPage.text=Treat all files as text ExportPatchWizard.Clipboard=&Clipboard ExportPatchWizard.pageName=ExportPage ExportPatchWizard.pageTitle=Export changes ExportPatchWizard.pageDescription=Select a patch file to export to ExportPatchWizard.FileSystem=&File System ExportPatchWizard.InvalidFileName=Please input valid file name or choose clipboard ExportPatchWizard.InvalidPathFile=Please choose patch file ImportPatchPage.InvalidProject=Please choose valid project ImportPatchPage.ProjectName=Import patch to hg root: CompareAction.label=Compare With Current CompareWithEachOtherAction.label=Compare With Each Other CompareWithPreviousAction.label=Compare With Previous CompareWithOtherAction.label=Compare With ... ChangePathsTableProvider.action=Action ChangePathsTableProvider.path=Affected paths HistoryView.affectedPathsHorizontalLayout=&Horizontal Layout HistoryView.affectedPathsVerticalLayout=&Vertical Layout HistoryView.copy=&Copy HistoryView.selectAll=Select &All HistoryView.showComments=Show Comments HistoryView.showDiffs=Show Diffs HistoryView.showTags=Show All Tags HistoryView.wrapComments=Wrap Comments HistoryView.showAffectedPaths=Show Affected Paths BackoutWizard.title=Backout Wizard BackoutWizard.pageName=Backout BackoutWizard.pageTitle=Backout BackoutWizard.pageDescription=With backout you can reverse changes that have been committed earlier BackoutWizardPage.changeSetGroup.title=Please select the changeset to back out from BackoutWizardPage.defaultCommitMessage=Backed out of changeset BackoutWizardPage.optionGroup.title=Please choose the options BackoutWizardPage.userLabel.text=User BackoutWizardPage.commitLabel.text=Commit message BackoutWizardPage.mergeCheckBox.text=Merge with old dirstate parent after backout BackoutWizardPage.backoutError=Error while backing out: CloneRepoWizard.pageName=CreateRepoPage CloneRepoWizard.title=Mercurial clone repository wizard CloneRepoWizard.pageTitle=Clone repository CloneRepoWizard.pageDescription=Create a clone from another hg repository (local or remote). CloneRepoWizard.refreshJob.name=Refreshing status and changeset information after clone... ClonePage.noUpdateCheckBox.title=Do not update the new working directory ClonePage.destinationGroup.title=Clone destination ClonePage.directoryButton.title=Browse... ClonePage.timeoutCheckBox.title=Abort clone when a timeout occurs ClonePage.directoryDialog.message=Please select parent directory for clone. CloneRepoWizard.malformedURL=Malformed URL: ClonePage.pullCheckBox.title=Use pull protocol to copy metadata CloneRepoWizard.project=Project CloneRepoWizard.alreadyExists=\ already exists CloneRepoWizard.operation.name=Cloning... CloneRepoWizard.updateOperation.name=Updating... ClonePage.revisionLabel.title=Last revision in the cloned repo CloneRepoWizard.cloneOperationFailed=Clone operation failed CloneRepoWizard.updateOperationFailed=Update operation failed CloneRepoWizard.description.comment=Cloned from CloneRepoWizard.actionDescription.1=Clone repository CloneRepoWizard.actionDescription.2=\ to ClonePage.uncompressedCheckBox.title=Use uncompressed transfer (fast over LAN) ClonePage.cloneDirectoryLabel.title=Clone directory name CloneRepoWizard.subTaskParentDirectory.name=Determining parent directory: CloneRepoWizard.subTaskCloneDirectory.name=Determining clone directory: CloneRepoWizard.subTask.invokingMercurial=Invoking Mercurial.... CloneRepoWizard.subTask.registeringProject1=Registering CloneRepoWizard.subTaskRegisteringProject2=\ at Mercurial team provider... CloneRepoWizard.subTask.addingRepository.1=Adding repository CloneRepoWizard.subTask.addingRepository.2=\ to repository manager... ClonePage.destinationDirectoryLabel.title=Parent directory ClonePage.seachProjectFilesCheckBox.title0=Search for .project files in clone and use them to create projects. ConfigurationWizardMainPage.urlGroup.title=Repository location ConfigurationWizardMainPage.urlLabel.text=URL ConfigurationWizardMainPage.browseButton.text=Local... ConfigurationWizardMainPage.dialog.message=Select directory. ConfigurationWizardMainPage.authenticationGroup.title=Authentication ConfigurationWizardMainPage.userLabel.text=Username ConfigurationWizardMainPage.passwordLabel.text=Password ImportPatchWizard.optionsPageDescription=Options for importing patch ImportPatchWizard.optionsPageName=Options ImportPatchWizard.optionsPageTitle=Patch options ExportPatchWizard.optionsPageDescription=Options for export ExportPatchWizard.OverwriteConfirmDescription=Are you sure to overwrite existing file? ExportPatchWizard.OverwriteConfirmTitle=Overwrite Confirm ExportPatchWizard.PathLocation=Patch Location IncomingPage.fileStatusTable.columnTitle.status=Status IncomingPage.fileStatusTable.columnTitle.path=Path IncomingPage.unknownElement=Unknown Element: IncomingPage.notApplicable=N/A IncomingPage.title=Incoming changesets IncomingPage.description=Click on a changeset to see changed files. Double-click on a file to compare against parent revision. IncomingPage.columnHeader.revision=Revision IncomingPage.columnHeader.global=Global IncomingPage.columnHeader.date=Date IncomingPage.columnHeader.author=Author IncomingPage.columnHeader.branch=Branch IncomingPage.columnHeader.summary=Summary IncomingPage.getIncomingOperation.beginTask=Getting incoming changesets... IncomingPage.getIncomingOperation.call=Calling Mercurial... IncomingPage.getIncomingOperation.description=Getting incoming changesets... IncomingPage.group.title=Options IncomingPage.revisionCheckBox.title=Pull only the selected revision and all of its ancestors IncomingPage.compare.file.missing=File doesn't exist or not part of the Eclipse project! MercurialHistoryPage.columnHeader.branch=Branch MercurialHistoryPage.columnHeader.changeset=Changeset MercurialHistoryPage.columnHeader.date=Date MercurialHistoryPage.columnHeader.graph=Graph MercurialHistoryPage.columnHeader.summary=Summary MercurialHistoryPage.columnHeader.tag=Tag MercurialHistoryPage.columnHeader.user=User MercurialHistoryPage.file=File ' MercurialHistoryPage.hasUncommittedChanges=' has uncommited changes.\nDo you really want to revert? MercurialHistoryPage.openCurrentVersion=Open Current Version MercurialHistoryPage.showSelectedFileHistory=Show History for Selected File MercurialHistoryPage.openSelectedVersion=Open Selected Version MercurialHistoryPage.replaceCurrentWithSelected=Replace Current With Selected MercurialHistoryPage.restoreDeletedFile=Restore Deleted File MercurialHistoryPage.undoMove=Undo Move MercurialHistoryPage.UncommittedChanges=Uncommited Changes MercurialHistoryPage.updateAction.name=Switch Repository to Selected Changeset MercurialParticipantSynchronizeWizard.pageTitle=Mercurial MercurialParticipantSynchronizeWizard.repositoryPage.name=RepositoryPage MercurialParticipantSynchronizeWizard.repositoryPage.title=Choose repository MercurialParticipantSynchronizeWizard.repositoryPage.image=wizards/share_wizban.png MercurialParticipantSynchronizeWizard.repositoryPage.description=Please choose the repository location to monitor. NewLocationWizard.name=New Mercurial Repository Location Setup NewLocationWizard.repoCreationPage.name=RepoCreationPage NewLocationWizard.repoCreationPage.title=Create new Mercurial repository location NewLocationWizard.repoCreationPage.image=wizards/share_wizban.png NewLocationWizard.repoCreationPage.description=Enter a new remote or local location or create a new local Mercurial repository. PullPage.forceCheckBox.title=Pull even when remote repository is unrelated PullPage.timeoutCheckBox.title=Abort pull when a timeout occurs PullPage.browseFileButton.text=Bundle... PullPage.bundleDialog.text=Select a bundle to pull from PullPage.error.modifiedResources=Please commit modified resources before trying to merge. PullPage.error.noStatus=Couldn't get status from Mercurial. Merge disabled. PullPage.option.commitAfterMerge=Merge and, if there are no conflicts, commit after update PullPage.option.editCommitMessage=Edit commit message before committing merge. PullPage.option.merge=Merge options PullPage.option.rebase=Rebase after pull PullPage.pullGroup.label=Pull options PullPage.toggleUpdate.text=Update after pull PullPage.toggleCleanUpdate.text=Clean update (override local changes) PullRepoWizard.pullPage.name=PullRepoPage PullRepoWizard.pullPage.title=Pull changes from a repository PullRepoWizard.title=Pull changes from a repository PullRepoWizard.malformedURL=URL is malformed. PullRepoWizard.incomingPage.name=Incoming PullRepoWizard.pullPage.description=Select a repository location to pull from PullRepoWizard.addingRepositoryFailed=Adding repository to persistent storage failed. PullRepoWizard.pullOperation.addRepo=Adding repository PullRepoWizard.pullOperation.commit=Committing... PullRepoWizard.pullOperation.commit.header=Output of Commit:\n PullRepoWizard.pullOperation.description=Pulling... PullRepoWizard.pullOperation.incoming=Pulling incoming changesets... PullRepoWizard.pullOperation.mergeHeader=Output of Merge:\n PullRepoWizard.pullOperation.mergeJob.description=Merging... PullRepoWizard.pullOperation.mergeStatus=Getting merge status... PullRepoWizard.pullOperation.merging=Merging... PullRepoWizard.pullOperation.pull.header=Output of Pull:\n PullRepoWizard.pullOperation.pulling=Pulling... PushPullPage.option.forest=Repository is a forest PushPullPage.option.svn=Use Subversion extension PushPullPage.snapfile.browse=Browse... PushPullPage.snapfile.label=Snapfile PushPullPage.snapfile.select=Please select snapfile PushRepoPage.optionGroup.title=Options PushRepoPage.timeoutCheckBox.text=Abort push when a timeout occurs PushRepoPage.forceCheckBox.text=Force Push PushRepoWizard.project=Project PushRepoWizard.notExists=\ doesn't exists why push? PushRepoWizard.malformedUrl=Malformed URL: PushRepoWizard.pushOutput.header=Push output:\n PushRepoWizard.pushRepoPage.description=Push changes to another repository. PushRepoWizard.pushRepoPage.title=Push changes to a repository PushRepoWizard.title=Push changes to a repository PushRepoWizard.pushRepoPage.name=PushRepoPage SignWizard.signWizardPage.image=wizards/cleanmanifest_wiz.png SignWizard.signWizardPage.name=Sign changesets SignWizard.signWizardPage.title=Sign changesets SignWizard.signWizardPage.description=Cryptographically sign changesets SignWizardPage.userGroup.title=Please enter the information needed for signing. SignWizardPage.userLabel.text=User SignWizardPage.keyLabel.text=Key SignWizardPage.passTextField.text=Look out for the gpg agent that will ask you. SignWizardPage.optionGroup.title=Please choose the options SignWizardPage.localCheckBox.text=Make the signature local SignWizardPage.forceCheckBox.text=Sign even if the sigfile is modified SignWizardPage.commitLabel.text=Commit message SignWizardPage.changeSetGroup.title=Please select the changeset to sign. SignWizardPage.messageTextField.text=Signed changeset SignWizardPage.passphraseLabel.text=Passphrase SignWizardPage.noCommitCheckBox.text=Do not commit the sigfile after signing SignWizardPage.messageTextField.defaultText=Signed changeset SignWizardPage.errorLoadingGpgKeys=Couldn't load keys. See log for details. SignWizardPage.errorSigning=Error while signing: TransplantOptionsPage.filtergroup.title=Filter TransplantOptionsPage.filterCheckBox.title=Filter changesets TransplantOptionsPage.filterLabel.title=Filter TransplantOptionsPage.pruneGroup.title=Prune / Skip TransplantOptionsPage.pruneCheckBox.title=Skip over a revision TransplantOptionsPage.mergeGroup.title=Merge TransplantWizard.transplantPage.title=Transplant changesets TransplantPage.errorLoadChangesets=Couldn't get changesets TransplantPage.branchGroup.title=Transplant from a local branch TransplantPage.branchLabel.title=Local Branch TransplantPage.allCheckBox.title=Transplant all revisions from local branch. If you select a revision, the branch \ will be rebased up to the selected revision onto your current working directory. TransplantWizard.optionsPage.title=Transplant options TransplantPage.branchCheckBox.title=Transplant changesets from local branch TransplantPage.changesetGroup.title=Select changesets to transplant TransplantWizard.transplantPage.name=TransplantPage TransplantPage.errorNotSequential=You must select a sequence of changesets. TransplantWizard.optionsPage.name=TransplantOptionsPage TransplantOptionsPage.mergeCheckBox.title=Merge at a revision TransplantWizard.optionsPage.description=Select options to use for transplant. TransplantWizard.title=Transplant Wizard TransplantWizard.transplantPage.description=Transplant changesets either from another repository or from local branch. StripWizard.page.name=StripPage StripWizard.pageTitle=Strip changeset StripWizard.title=Strip Wizard StripWizard.page.description.1=Strip removes a revision, and all of its descendants, from the repository. It undoes the effects of the removed\n StripWizard.page.description.2=revisions from the repository, and updates the working directory to the first parent of the removed revision. StripWizardPage.changeSetGroup.title=Please select start changeset to strip StripWizardPage.optionsGroup.title=Options StripWizardPage.keep.title=Do not modify working copy during strip StripWizardPage.backupCheckBox.title=Save backup bundle. StripWizardPage.force.title=Force removal of changesets, discard uncommitted changes (no backup) StripWizardPage.errorCallingStrip=Error while calling strip ServeWizard.name=Serve repository wizard ServeWizard.pageName=ServeWizardPage ServeWizard.pageTitle=Serve repository ServeWizard.pageDescription=Start a local HTTP repository browser and pull server. ServeWizardPage.defaultsGroup.title=Defaults ServeWizardPage.settingsGroup.title=Server settings ServeWizardPage.defaultCheckBox.title=Use defaults ServeWizardPage.portLabel.title=Port to listen on (default: 8000) ServeWizardPage.portTextField.defaultValue=8000 ServeWizardPage.nameLabel.title=Name to show in webpages (default: server root) ServeWizardPage.prefixLabel.title=Prefix path to serve from (default: working dir) ServeWizardPage.webdirLabel.title=Name of the webdir config file (serve more than one repo) ServeWizardPage.stdioCheckBox.title=For remote clients ServeWizardPage.ipv6CheckBox.title=Use IPv6 in addition to IPv4 AddBranchPage.branchNameTextField.title=Branch name AddBranchWizard.AddBranchOperation.taskName=Adding branch... AddBranchWizard.branchPage.description=Set the working directory branch name AddBranchPage.forceCheckBox.title=Set branch name even if it shadows an existing branch AddBranchPage.commitCheckBox.title=Commit to persist the branch immediately AddBranchPage.commitCheckBox.tooltip=The branch will not exist in the repository until the next commit AddBranchPage.dirtyFilesWarning=Commit to persist a branch immediately AddBranchWizard.AddBranchOperation.actionDescription=Add branch AddBranchWizard.windowTitle=Add Branch Wizard AddBranchWizard.branchPage.name=AddBranchPage AddBranchWizard.branchPage.title=Add branch to repository CreateProjectOperation.taskDescription=Creating project... CreateProjectOperation.beginTask=Creating project... CreateProjectOperation.subTaskReadingProjectFile=Reading .project file... CreateProjectOperation.subTaskCreatingProjectFile=Creating .project file... ExportPatchWizard.WindowTitle=Export Patch Wizard ExportPatchWizard.Workspace=&Workspace LocationChooser.clipboardEmpty=Clipboard Empty OutgoingPage.description1=Click on a changeset to see changed files. Double-click on a file to compare against parent revision. OutgoingPage.getOutgoingOperation.beginTask=Getting outgoing changesets... OutgoingPage.getOutgoingOperation.call=Calling Mercurial... OutgoingPage.getOutgoingOperation.description=Retrieving outoing changesets... OutgoingPage.option.pushUpTo=Push only the selected revision and all of its ancestors OutgoingPage.title=Outgoing changesets RebasePage.base.label=Rebase from the base of the selected revision RebasePage.destinationCheckbox.label=Rebase onto the selected revision RebasePage.destinationGroup.label=Select destination revision RebasePage.error.notAvailable=Rebase not available. Please update to a newer Mercurial version. RebasePage.option.collapse=Collapse the rebased revisions RebasePage.optionGroup.label=Options RebasePage.option.keepBranches=Retain the branch name RebasePage.option.keep=Retain the rebased history RebasePage.source.label=Rebase from the selected revision RebasePage.sourceGroup.label=Select source revision RebaseWizard.rebasePage.description=Move changeset (and descendants) to a different branch. RebaseWizard.rebasePage.title=Rebase RebaseWizard.title=Rebase wizard eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/000077500000000000000000000000001173713500500304705ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/Messages.java000066400000000000000000000021351173713500500331030ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * @author bastian * */ public final class Messages { private static final String BUNDLE_NAME = "com.vectrace.MercurialEclipse.wizards.mq.messages"; //$NON-NLS-1$ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle .getBundle(BUNDLE_NAME); private Messages() { } public static String getString(String key) { try { return RESOURCE_BUNDLE.getString(key); } catch (MissingResourceException e) { return '!' + key + '!'; } } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/QDeletePage.java000066400000000000000000000110341173713500500334520ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import java.util.List; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQAppliedClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Patch; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.wizards.HgWizardPage; /** * @author bastian * */ public class QDeletePage extends HgWizardPage { private final boolean showRevSelector; private final HgRoot root; private ListViewer patchViewer; private ChangesetTable changesetTable; private Button revCheckBox; private Button keepCheckBox; public QDeletePage(String pageName, String title, ImageDescriptor titleImage, String description, HgRoot root, boolean showRevSelector) { super(pageName, title, titleImage, description); this.root = root; this.showRevSelector = showRevSelector; } /** * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 2); Group g = SWTWidgetHelper.createGroup(composite, Messages.getString("QDeletePage.patchGroup.title")); //$NON-NLS-1$ IBaseLabelProvider labelProvider = new LabelProvider() { @Override public String getText(Object element) { return element.toString(); } }; this.patchViewer = SWTWidgetHelper.createListViewer(g, Messages.getString("QDeletePage.patchViewer.title"), 100, //$NON-NLS-1$ labelProvider); populatePatchViewer(); g = SWTWidgetHelper.createGroup(composite, Messages.getString("QDeletePage.optionGroup.title")); //$NON-NLS-1$ this.keepCheckBox = SWTWidgetHelper.createCheckBox(g, Messages.getString("QDeletePage.keepCheckBox.title")); //$NON-NLS-1$ if (showRevSelector) { this.revCheckBox = SWTWidgetHelper.createCheckBox(g, Messages.getString("QDeletePage.revCheckBox.title")); //$NON-NLS-1$ SelectionListener revListener = new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } public void widgetSelected(SelectionEvent e) { changesetTable.setEnabled(revCheckBox.getSelection()); patchViewer.getControl().setEnabled(!revCheckBox.getSelection()); } }; revCheckBox.addSelectionListener(revListener); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 150; gridData.minimumHeight = 50; this.changesetTable = new ChangesetTable(g, root); this.changesetTable.setLayoutData(gridData); this.changesetTable.setEnabled(false); } setControl(composite); } /** * */ private void populatePatchViewer() { try { List patches = HgQAppliedClient.getUnappliedPatches(root); for (Patch patch : patches) { patchViewer.add(patch); } } catch (HgException e) { MercurialEclipsePlugin.logError(e); setErrorMessage(e.getLocalizedMessage()); } } /** * @return the patchViewer */ public ListViewer getPatchViewer() { return patchViewer; } /** * @return the revCheckBox */ public Button getRevCheckBox() { return revCheckBox; } /** * @return the keepCheckBox */ public Button getKeepCheckBox() { return keepCheckBox; } public ChangeSet getSelectedChangeset() { if (changesetTable == null) { return null; } return changesetTable.getSelection(); } } QDeleteWizard.java000066400000000000000000000074131173713500500337650ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import java.lang.reflect.InvocationTargetException; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.viewers.IStructuredSelection; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQDeleteClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.model.Patch; import com.vectrace.MercurialEclipse.views.PatchQueueView; import com.vectrace.MercurialEclipse.wizards.HgOperationWizard; /** * @author bastian * */ public class QDeleteWizard extends HgOperationWizard { private static class DeleteOperation extends HgOperation { private final boolean isKeep; private final HgRoot root; private final List patches; private final ChangeSet changeset; @SuppressWarnings("unchecked") public DeleteOperation(IRunnableContext context, HgRoot root, QDeletePage page) { super(context); IStructuredSelection selection = (IStructuredSelection) page.getPatchViewer().getSelection(); this.patches = selection.toList(); this.root = root; this.isKeep = page.getKeepCheckBox().getSelection(); this.changeset = page.getSelectedChangeset(); } /** * @see com.vectrace.MercurialEclipse.actions.HgOperation#getActionDescription() */ @Override protected String getActionDescription() { return Messages.getString("QDeleteWizard.deleteAction.description"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(Messages.getString("QDeleteWizard.deleteAction.beginTask"), 2); //$NON-NLS-1$ monitor.worked(1); monitor.subTask(Messages.getString("QDeleteWizard.subTask.callMercurial")); //$NON-NLS-1$ try { HgQDeleteClient.delete(root, isKeep, changeset, patches); monitor.worked(1); monitor.done(); } catch (HgException e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } } } private final HgRoot root; public QDeleteWizard(HgRoot root, boolean showRevSelector) { super(Messages.getString("QDeleteWizard.title")); //$NON-NLS-1$ this.root = root; setNeedsProgressMonitor(true); page = new QDeletePage(Messages.getString("QDeleteWizard.pageName"), Messages.getString("QDeleteWizard.pageTitle"), null, //$NON-NLS-1$ //$NON-NLS-2$ Messages.getString("QDeleteWizard.pageDescription"), root, showRevSelector); //$NON-NLS-1$ initPage(Messages.getString("QDeleteWizard.pageDescription"), page); //$NON-NLS-1$ addPage(page); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#initOperation() */ @Override protected HgOperation initOperation() { return new DeleteOperation(getContainer(), root, (QDeletePage) page); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#operationFinished() */ @Override protected void operationFinished() { PatchQueueView.getView().populateTable(); } } QImportWizard.java000066400000000000000000000052121173713500500340300ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.operations.QImportOperation; import com.vectrace.MercurialEclipse.views.PatchQueueView; import com.vectrace.MercurialEclipse.wizards.HgOperationWizard; /** * @author bastian * */ public class QImportWizard extends HgOperationWizard { private final HgRoot root; public QImportWizard(HgRoot root) { super(Messages.getString("QImportWizard.title")); //$NON-NLS-1$ this.root = root; setNeedsProgressMonitor(true); page = new QImportWizardPage( Messages.getString("QImportWizard.pageName"), //$NON-NLS-1$ Messages.getString("QImportWizard.page.title"), //$NON-NLS-1$ Messages.getString("QImportWizard.page.description"), //$NON-NLS-1$ root, null); initPage(page.getDescription(), page); addPage(page); } @Override protected HgOperation initOperation() { final QImportWizardPage importPage = (QImportWizardPage) page; ChangeSet[] changesets = importPage.getRevisions(); boolean existing = importPage.isExisting(); IPath patchFile = null; if (changesets == null) { if (importPage.getPatchFile().getText().length()==0) { importPage.setErrorMessage(Messages.getString("QImportWizard.page.error.mustSelectChangesetOrFile")); //$NON-NLS-1$ return null; } patchFile = new Path(importPage.getPatchFile().getText()); if (!patchFile.toFile().exists() && !existing) { importPage.setErrorMessage(Messages.getString("QImportWizard.page.error.patchFileNotExists")); //$NON-NLS-1$ return null; } } boolean force = importPage.getForceCheckBox().getSelection(); return new QImportOperation(getContainer(), patchFile, changesets, existing, force, root); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#operationFinished() */ @Override protected void operationFinished() { super.operationFinished(); PatchQueueView.getView().populateTable(); } } QImportWizardPage.java000066400000000000000000000164201173713500500346300ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/******************************************************************************* * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VecTrace (Zingo Andersen) - some updates * Stefan C - Code cleanup * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import java.io.File; import java.io.IOException; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Text; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.ui.ChangesetTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.wizards.HgWizardPage; public class QImportWizardPage extends HgWizardPage { private Button revCheckBox; private ChangesetTable changesetTable; private ChangeSet[] revisions; private final HgRoot root; private Text patchFile; private Button browseButton; private Button forceCheckBox; private Label patchFileLabel; private Group patchNameGroup; private boolean existing; public QImportWizardPage(String pageName, String title, String description, HgRoot root, ImageDescriptor titleImage) { super(pageName, title, titleImage, description); this.root = root; Assert.isNotNull(root); } public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 3); createPatchNameGroup(composite); createOptionGroup(composite); createRevisionTable(composite); setPageComplete(true); setControl(composite); } private void createOptionGroup(Composite composite) { Group g = SWTWidgetHelper.createGroup(composite, Messages .getString("QImportWizardPage.optionsGroup.title")); //$NON-NLS-1$ this.forceCheckBox = SWTWidgetHelper.createCheckBox(g, Messages .getString("QImportWizardPage.forceCheckBox.title")); //$NON-NLS-1$ } private void createPatchNameGroup(Composite composite) { this.patchNameGroup = SWTWidgetHelper .createGroup( composite, Messages .getString("QImportWizardPage.patchNameGroup.title"), 3, GridData.FILL_HORIZONTAL); //$NON-NLS-1$ this.patchFileLabel = SWTWidgetHelper.createLabel(patchNameGroup, Messages.getString("QImportWizardPage.patchFileLabel.title")); //$NON-NLS-1$ this.patchFile = SWTWidgetHelper.createTextField(patchNameGroup); this.patchFile.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { if (patchFile.getText().length() > 0) { try { File file = new File(patchFile.getText()); checkExisting(file); } catch (Exception e1) { setErrorMessage(e1.getCause().getLocalizedMessage()); } } } }); this.browseButton = SWTWidgetHelper.createPushButton(patchNameGroup, Messages.getString("QImportWizardPage.browseButton.title"), 1); //$NON-NLS-1$ browseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { try { FileDialog dialog = new FileDialog(getShell()); dialog .setText(Messages .getString("QImportWizardPage.browseFileDialog.title")); //$NON-NLS-1$ String fileName = dialog.open(); if (fileName != null) { File file = new File(fileName); checkExisting(file); patchFile.setText(file.getCanonicalPath()); } } catch (Exception e1) { String msg = e1.getLocalizedMessage(); if (e1.getCause() != null) { msg = e1.getCause().getLocalizedMessage(); setErrorMessage(msg); MercurialEclipsePlugin.logError(e1); } } } }); } private void checkExisting(File file) throws IOException { setMessage(null); setErrorMessage(null); File patchDir = new File(root, ".hg" + File.separator + "patches"); //$NON-NLS-1$ //$NON-NLS-2$ File[] patches = patchDir.listFiles(); if (patches != null) { for (File patch : patches) { if (patch.getName().equals(file.getName()) || patch.getCanonicalPath().equals(file.getCanonicalPath())) { setMessage(Messages .getString("QImportWizardPage.message.Existing")); //$NON-NLS-1$ existing = true; } } } } private void createRevisionTable(Composite composite) { Group revGroup = SWTWidgetHelper.createGroup(composite, Messages .getString("QImportWizardPage.revGroup.title"), //$NON-NLS-1$ GridData.FILL_BOTH); this.revCheckBox = SWTWidgetHelper.createCheckBox(revGroup, Messages .getString("QImportWizardPage.revCheckBox.title")); //$NON-NLS-1$ Listener revCheckBoxListener = new Listener() { public void handleEvent(Event event) { updateRevSelection(); } }; this.revCheckBox.setSelection(getDialogSettings().getBoolean("importRev")); this.revCheckBox.addListener(SWT.Selection, revCheckBoxListener); GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 150; gridData.minimumHeight = 50; this.changesetTable = new ChangesetTable(revGroup, root, true); this.changesetTable.setLayoutData(gridData); this.changesetTable.setEnabled(false); SelectionListener listener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { setPageComplete(true); revisions = changesetTable.getSelections(); } public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } }; this.changesetTable.addSelectionListener(listener); updateRevSelection(); } protected void updateRevSelection() { // en-/disable patch file text field changesetTable.setEnabled(revCheckBox.getSelection()); patchFile.setEnabled(!revCheckBox.getSelection()); browseButton.setEnabled(!revCheckBox.getSelection()); patchFileLabel.setEnabled(!revCheckBox.getSelection()); patchNameGroup.setEnabled(!revCheckBox.getSelection()); } @Override public boolean finish(IProgressMonitor monitor) { boolean bFinish = super.finish(monitor); if (bFinish) { getDialogSettings().put("importRev", revCheckBox.getSelection()); } return bFinish; } public ChangeSet[] getRevisions() { return revisions; } public Button getRevCheckBox() { return revCheckBox; } public Text getPatchFile() { return patchFile; } public Button getForceCheckBox() { return forceCheckBox; } public boolean isExisting() { return existing; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/QInitWizard.java000066400000000000000000000064231173713500500335450ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQInitClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.views.PatchQueueView; import com.vectrace.MercurialEclipse.wizards.HgOperationWizard; /** * @author bastian * */ public class QInitWizard extends HgOperationWizard { private static class InitOperation extends HgOperation { private final boolean isRepository; private final IResource resource; /** * @param context */ public InitOperation(IRunnableContext context, IResource resource, QInitWizardPage page) { super(context); this.isRepository = page.getCheckBox().getSelection(); this.resource = resource; } /** * @see com.vectrace.MercurialEclipse.actions.HgOperation#getActionDescription() */ @Override protected String getActionDescription() { return Messages.getString("QInitWizard.InitAction.description"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(Messages.getString("QInitWizard.beginTask"), 2); //$NON-NLS-1$ monitor.worked(1); monitor.subTask(Messages.getString("QInitWizard.subTask.callMercurial")); //$NON-NLS-1$ try { HgQInitClient.init(resource, isRepository); monitor.worked(1); monitor.done(); } catch (HgException e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } } } private final IResource resource; public QInitWizard(IResource resource) { super(Messages.getString("QInitWizard.title")); //$NON-NLS-1$ this.resource = resource; setNeedsProgressMonitor(true); page = new QInitWizardPage( Messages.getString("QInitWizard.pageName"), //$NON-NLS-1$ Messages.getString("QInitWizard.pageTitle"), //$NON-NLS-1$ null, null); initPage(Messages.getString("QInitWizard.pageDescription"), page); //$NON-NLS-1$ addPage(page); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#initOperation() */ @Override protected HgOperation initOperation() { return new InitOperation(getContainer(), resource, (QInitWizardPage) page); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#operationFinished() */ @Override protected void operationFinished() { super.operationFinished(); PatchQueueView.getView().populateTable(); } } QInitWizardPage.java000066400000000000000000000033011173713500500342530ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.wizards.HgWizardPage; /** * @author bastian * */ public class QInitWizardPage extends HgWizardPage { private Button checkBox; public QInitWizardPage(String pageName, String title, ImageDescriptor titleImage, String description) { super(pageName, title, titleImage, description); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ public void createControl(Composite parent) { Composite composite = SWTWidgetHelper.createComposite(parent, 1); Group g = SWTWidgetHelper.createGroup(composite, Messages.getString("QInitWizardPage.group.title")); //$NON-NLS-1$ this.checkBox = SWTWidgetHelper.createCheckBox(g, Messages.getString("QInitWizardPage.checkBox.nestedRepo")); //$NON-NLS-1$ setControl(composite); } /** * @return the checkBox */ public Button getCheckBox() { return checkBox; } } eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/QNewWizard.java000066400000000000000000000124611173713500500333720ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import java.lang.reflect.InvocationTargetException; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgAddClient; import com.vectrace.MercurialEclipse.commands.HgRemoveClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQNewClient; import com.vectrace.MercurialEclipse.dialogs.CommitDialog; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.ui.CommitFilesChooser; import com.vectrace.MercurialEclipse.views.PatchQueueView; import com.vectrace.MercurialEclipse.wizards.HgOperationWizard; /** * @author bastian * */ public class QNewWizard extends HgOperationWizard { protected static abstract class FileOperation extends HgOperation { protected final HgRoot root; protected final String message; protected final String user; protected final String date; protected final List resourcesToRemove; protected final List allResources; protected final List resourcesToAdd; public FileOperation(IRunnableContext context, HgRoot root, QNewWizardPage page) { super(context); this.root = root; this.message = page.getCommitTextDocument().get(); this.user = page.getUserTextField().getText(); this.date = page.getDate().getText(); CommitFilesChooser fileChooser = page.getFileChooser(); this.resourcesToAdd = fileChooser.getCheckedResources(CommitDialog.FILE_UNTRACKED); this.resourcesToRemove = fileChooser.getCheckedResources(CommitDialog.FILE_DELETED); this.allResources = fileChooser.getCheckedResources(); } protected void addRemoveFiles(IProgressMonitor pm) throws HgException { // add new resources pm.subTask("Removing selected untracked resources to repository."); HgAddClient.addResources(resourcesToAdd, pm); pm.worked(1); // remove deleted resources pm.subTask("Removing selected deleted resources from repository."); HgRemoveClient.removeResources(resourcesToRemove); pm.worked(1); } protected void saveCommitMessage() { if (message != null && message.length() > 0) { MercurialEclipsePlugin.getCommitMessageManager().saveCommitMessage(message); } } } private static class NewOperation extends FileOperation { private final String patchName; public NewOperation(IRunnableContext context, HgRoot root, QNewWizardPage page) { super(context, root, page); this.patchName = page.getPatchNameTextField().getText(); } /** * @see com.vectrace.MercurialEclipse.actions.HgOperation#getActionDescription() */ @Override protected String getActionDescription() { return Messages.getString("QNewWizard.actionDescription"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(Messages.getString("QNewWizard.beginTask"), 6); //$NON-NLS-1$ monitor.worked(1); try { addRemoveFiles(monitor); monitor.subTask(Messages.getString("QNewWizard.subTask.callMercurial")); //$NON-NLS-1$ HgQNewClient.createNewPatch(root, message, allResources, user, date, patchName); monitor.worked(2); saveCommitMessage(); monitor.done(); } catch (HgException e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } } } private final HgRoot root; public QNewWizard(HgRoot root) { super(Messages.getString("QNewWizard.title")); //$NON-NLS-1$ this.root = root; setNeedsProgressMonitor(true); page = new QNewWizardPage( Messages.getString("QNewWizard.pageName"), Messages.getString("QNewWizard.pageTitle"), //$NON-NLS-1$ //$NON-NLS-2$ null, null, root, true); initPage(Messages.getString("QNewWizard.pageDescription"), //$NON-NLS-1$ page); addPage(page); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#initOperation() */ @Override protected HgOperation initOperation() { return new NewOperation(getContainer(), root, (QNewWizardPage) page); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#operationFinished() */ @Override protected void operationFinished() { super.operationFinished(); PatchQueueView.getView().populateTable(); new RefreshWorkspaceStatusJob(root, RefreshRootJob.LOCAL_AND_OUTGOING).schedule(); } } QNewWizardPage.java000066400000000000000000000160331173713500500341070ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Philip Graf bug fix *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import static com.vectrace.MercurialEclipse.ui.SWTWidgetHelper.*; import java.util.ArrayList; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.source.AnnotationModel; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.editors.text.TextSourceViewerConfiguration; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.texteditor.spelling.SpellingAnnotation; import com.vectrace.MercurialEclipse.commands.HgPatchClient; import com.vectrace.MercurialEclipse.dialogs.CommitDialog; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.storage.HgCommitMessageManager; import com.vectrace.MercurialEclipse.ui.CommitFilesChooser; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.utils.ResourceUtils; import com.vectrace.MercurialEclipse.wizards.HgWizardPage; /** * @author bastian * * TODO: this is a lot like the {@link CommitDialog}, merge more code with it. */ public class QNewWizardPage extends HgWizardPage { private static final String PROP_COUNTER = "qnewCounter"; protected final HgRoot root; private Text patchNameTextField; private Text userTextField; private Text date; private final boolean showPatchName; private SourceViewer commitTextBox; private SourceViewerDecorationSupport decorationSupport; private IDocument commitTextDocument; private CommitFilesChooser fileChooser; public QNewWizardPage(String pageName, String title, ImageDescriptor titleImage, String description, HgRoot root, boolean showPatchName) { super(pageName, title, titleImage, description); Assert.isNotNull(root); this.root = root; this.showPatchName = showPatchName; this.commitTextDocument = new Document(); } /** * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite) */ public void createControl(Composite parent) { Composite composite = createComposite(parent, 1); //Group g = createGroup(composite, Messages.getString("QNewWizardPage.patchDataGroup.title")); //$NON-NLS-1$ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.minimumHeight = 150; composite.setLayoutData(data); if (showPatchName) { createLabel(composite, Messages.getString("QNewWizardPage.patchNameLabel.title")); //$NON-NLS-1$ this.patchNameTextField = createTextField(composite); this.patchNameTextField.setText("patch-" + getCount() + HgPatchClient.PATCH_EXTENSION); } createLabel(composite, Messages.getString("QNewWizardPage.userNameLabel.title")); //$NON-NLS-1$ userTextField = createTextField(composite); userTextField.setText(getUser()); createLabel(composite, Messages.getString("QNewWizardPage.dateLabel.title")); //$NON-NLS-1$ date = createTextField(composite); createLabel(composite, Messages .getString("QNewWizardPage.commitMessageLabel.title")); //$NON-NLS-1$ commitTextBox = new SourceViewer(composite, null, SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.WRAP); commitTextBox.getTextWidget().setLayoutData(data); // set up spell-check annotations decorationSupport = new SourceViewerDecorationSupport(commitTextBox, null, new DefaultMarkerAnnotationAccess(), EditorsUI .getSharedTextColors()); AnnotationPreference pref = EditorsUI.getAnnotationPreferenceLookup() .getAnnotationPreference(SpellingAnnotation.TYPE); decorationSupport.setAnnotationPreference(pref); decorationSupport.install(EditorsUI.getPreferenceStore()); commitTextBox.configure(new TextSourceViewerConfiguration(EditorsUI .getPreferenceStore())); AnnotationModel annotationModel = new AnnotationModel(); commitTextBox.setDocument(commitTextDocument, annotationModel); commitTextBox.getTextWidget().addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { decorationSupport.uninstall(); } }); CommitDialog.createOldCommitCombo(composite, commitTextDocument, commitTextBox); Group g = SWTWidgetHelper.createGroup(composite, "Add changes to patch:", 1, GridData.FILL_BOTH); //$NON-NLS-1$ // TODO: Resource calculation wrong for repos below root fileChooser = new CommitFilesChooser(g, true, new ArrayList(ResourceUtils .getProjects(root)), true, true, false); setControl(composite); } /** * @return The name for the commit user field */ protected String getUser() { return HgCommitMessageManager.getDefaultCommitName(root); } /** * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean) */ @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible && commitTextBox != null) { commitTextBox.getTextWidget().setFocus(); commitTextBox.getTextWidget().selectAll(); } } /** * @see com.vectrace.MercurialEclipse.wizards.HgWizardPage#finish(org.eclipse.core.runtime.IProgressMonitor) */ @Override public boolean finish(IProgressMonitor monitor) { if (showPatchName) { getDialogSettings().put(PROP_COUNTER, getCount() + 1); } return super.finish(monitor); } private int getCount() { try { return getDialogSettings().getInt(PROP_COUNTER); } catch(NumberFormatException e) { return 1; } } /** * @return the patchNameTextField */ public Text getPatchNameTextField() { return patchNameTextField; } /** * @return the date */ public Text getDate() { return date; } /** * @return the userTextField */ public Text getUserTextField() { return userTextField; } /** * @return the commitTextDocument */ public IDocument getCommitTextDocument() { return commitTextDocument; } /** * @param commitTextDocument * the commitTextDocument to set */ public void setCommitTextDocument(IDocument commitTextDocument) { this.commitTextDocument = commitTextDocument; } public CommitFilesChooser getFileChooser() { return fileChooser; } } QRefreshWizard.java000066400000000000000000000136761173713500500341710ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mq/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian - implementation * Philip Graf - load current commit text * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards.mq; import java.lang.reflect.InvocationTargetException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.Document; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import com.vectrace.MercurialEclipse.MercurialEclipsePlugin; import com.vectrace.MercurialEclipse.actions.HgOperation; import com.vectrace.MercurialEclipse.commands.HgLogClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQHeaderClient; import com.vectrace.MercurialEclipse.commands.extensions.mq.HgQRefreshClient; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.ChangeSet; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.team.cache.LocalChangesetCache; import com.vectrace.MercurialEclipse.team.cache.RefreshRootJob; import com.vectrace.MercurialEclipse.team.cache.RefreshWorkspaceStatusJob; import com.vectrace.MercurialEclipse.ui.ChangesetInfoTray.ChangedFilesTable; import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper; import com.vectrace.MercurialEclipse.views.PatchQueueView; import com.vectrace.MercurialEclipse.wizards.HgOperationWizard; import com.vectrace.MercurialEclipse.wizards.mq.QNewWizard.FileOperation; /** * @author bastian */ public class QRefreshWizard extends HgOperationWizard { private static class RefreshOperation extends FileOperation { public RefreshOperation(IRunnableContext context, HgRoot root, QNewWizardPage page) { super(context, root, page); } @Override protected String getActionDescription() { return Messages.getString("QRefreshWizard.actionDescription"); //$NON-NLS-1$ } /** * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(Messages.getString("QRefreshWizard.beginTask"), 6); //$NON-NLS-1$ monitor.worked(1); try { addRemoveFiles(monitor); monitor.subTask(Messages.getString("QRefreshWizard.subTask.callMercurial")); //$NON-NLS-1$ HgQRefreshClient.refresh(root, message, allResources, user, date); monitor.worked(2); saveCommitMessage(); monitor.worked(1); } catch (HgException e) { throw new InvocationTargetException(e, e.getLocalizedMessage()); } finally { monitor.done(); } } } private static class QRefreshWizardPage extends QNewWizardPage { private ChangeSet currentChangeset; public QRefreshWizardPage(String pageName, String title, ImageDescriptor titleImage, String description, HgRoot root, boolean showPatchName) { super(pageName, title, titleImage, description, root, showPatchName); try { currentChangeset = LocalChangesetCache.getInstance().getChangesetForRoot(root); } catch (HgException e) { MercurialEclipsePlugin.logError(e); setErrorMessage("Couldn't fetch current changeset"); } } /** * @see com.vectrace.MercurialEclipse.wizards.mq.QNewWizardPage#createControl(org.eclipse.swt.widgets.Composite) */ @Override public void createControl(Composite parent) { super.createControl(parent); // TODO: should get this from the cache if (currentChangeset != null && !currentChangeset.hasFileStatus()) { try { currentChangeset = HgLogClient.getChangeset(root, currentChangeset .getChangeset(), true); } catch (HgException e) { MercurialEclipsePlugin.logError(e); } } if (currentChangeset != null && currentChangeset.hasFileStatus()) { Group g = SWTWidgetHelper.createGroup((Composite) getControl(), "Already in patch:", 1, GridData.FILL_BOTH); //$NON-NLS-1$ new ChangedFilesTable(g, currentChangeset).getViewer().setInput(currentChangeset); } } /** * @see com.vectrace.MercurialEclipse.wizards.mq.QNewWizardPage#getUser() */ @Override protected String getUser() { return currentChangeset.getAuthor(); } } private final HgRoot root; public QRefreshWizard(HgRoot root) { super(Messages.getString("QRefreshWizard.title")); //$NON-NLS-1$ this.root = root; setNeedsProgressMonitor(true); page = new QRefreshWizardPage( Messages.getString("QRefreshWizard.pageName"), Messages.getString("QRefreshWizard.pageTitle"), //$NON-NLS-1$ //$NON-NLS-2$ null, null, root, false); initPage(Messages.getString("QRefreshWizard.pageDescription"), page); //$NON-NLS-1$ try { ((QNewWizardPage) page).setCommitTextDocument(new Document(HgQHeaderClient .getHeader(root))); } catch (HgException e) { MercurialEclipsePlugin.logWarning("Cannot read header of current patch.", e); } addPage(page); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#initOperation() */ @Override protected HgOperation initOperation() { return new RefreshOperation(getContainer(), root, (QNewWizardPage) page); } /** * @see com.vectrace.MercurialEclipse.wizards.HgOperationWizard#operationFinished() */ @Override protected void operationFinished() { super.operationFinished(); PatchQueueView.getView().populateTable(); new RefreshWorkspaceStatusJob(root, RefreshRootJob.LOCAL_AND_OUTGOING).schedule(); } } messages.properties000066400000000000000000000066411173713500500343450ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/com/vectrace/MercurialEclipse/wizards/mqQDeletePage.patchGroup.title=Select unapplied patches to remove from queue QDeleteWizard.pageTitle=Delete patch from queue QDeletePage.patchViewer.title= QDeletePage.optionGroup.title=Options QDeletePage.keepCheckBox.title=Keep patch file QDeleteWizard.subTask.callMercurial=Calling Mercurial... QDeletePage.revCheckBox.title=Remove patch changeset from queue and promote to repository QDeleteWizard.deleteAction.description=Deleting patch from queue... QDeleteWizard.deleteAction.beginTask=Starting delete... QDeleteWizard.title=Mercurial Queue Delete Patch Wizard QDeleteWizard.pageName=QDeletePage QDeleteWizard.pageDescription=Stop managing the patch with Mercurial Queues QInitWizard.InitAction.description=Initializing queue repository... QInitWizardPage.checkBox.nestedRepo=Create a separate nested repository for patches QInitWizard.beginTask=Initializing queue repository QInitWizard.subTask.callMercurial=Calling Mercurial... QInitWizard.title=Mercurial Queue Initialization Wizard QInitWizard.pageName=QInitPage QInitWizard.pageTitle=Initialize queue repository QInitWizard.pageDescription=Initialize a new mercurial queue repository QInitWizardPage.group.title=Initialize a new queue repository QNewWizard.actionDescription=Creating patch... QNewWizard.beginTask=Initializing queue repository QNewWizard.subTask.callMercurial=Creating new patch... QNewWizardPage.patchDataGroup.title=Patch data QNewWizardPage.patchNameLabel.title=Patch name QNewWizardPage.userNameLabel.title=User name QNewWizardPage.dateLabel.title=Date QNewWizardPage.commitMessageLabel.title=Message QNewWizardPage.forceCheckBox.title=Import uncommitted changes into patch QNewWizardPage.gitCheckBox.title=Use git extended diff format QNewWizardPage.includeLabel.title=Include names matching the given patterns QNewWizardPage.excludeLabel.title=Exclude names matching the given patterns QNewWizard.title=Mercurial Queue New Patch Wizard QNewWizard.pageName=QNewPage QNewWizard.pageTitle=Create new patch QNewWizard.pageDescription=Creates a new patch on top of the currently applied patch (if any) QRefreshWizard.actionDescription=Refreshing queue... QRefreshWizard.beginTask=Starting refresh... QRefreshWizard.subTask.callMercurial=Refreshing patch... QRefreshWizard.title=Mercurial Queues Refresh Wizard QRefreshWizard.pageName=QRefreshPage QRefreshWizard.pageTitle=Update the current patch QRefreshWizard.pageDescription= QImportWizard.title=QImport wizard QImportWizard.pageName=qImportWizardPage QImportWizard.page.title=Import patch to Mercurial Queue QImportWizard.page.description=Place an existing patch or revision under Mercurial Queue control QImportWizardPage.optionsGroup.title=Options QImportWizardPage.gitCheckBox.title=Use git extended diff format QImportWizardPage.browseButton.title=Browse... QImportWizardPage.message.Existing=Found existing patch in patch directory. Import will use --existing. QImportWizardPage.revGroup.title=Select revisions to be converted to a patch QImportWizardPage.revCheckBox.title=Place existing revisions under mq control QImportWizard.page.error.mustSelectChangesetOrFile=You must either select changesets or provide a patch file. QImportWizard.page.error.patchFileNotExists=Given patch file does not exist. QImportWizardPage.forceCheckBox.title=Overwrite existing patch files QImportWizardPage.patchNameGroup.title=Please enter patch name QImportWizardPage.patchFileLabel.title=Patch file QImportWizardPage.browseFileDialog.title=Please select patch file eclipse-mercurialeclipse-1.9.4/plugin/src/org/000077500000000000000000000000001173713500500213555ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/org/eclipse/000077500000000000000000000000001173713500500230015ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/org/eclipse/core/000077500000000000000000000000001173713500500237315ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/org/eclipse/core/resources/000077500000000000000000000000001173713500500257435ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/src/org/eclipse/core/resources/FileInfoMatcherDescription.java000066400000000000000000000002551173713500500340130ustar00rootroot00000000000000package org.eclipse.core.resources; /** * Place holder for compiling ME with Eclipse 3.5 but running with Eclipse 3.7 API */ public class FileInfoMatcherDescription { } eclipse-mercurialeclipse-1.9.4/plugin/src/org/eclipse/core/resources/IBuildConfiguration.java000066400000000000000000000002511173713500500325040ustar00rootroot00000000000000package org.eclipse.core.resources; /** * Place holder for compiling ME with Eclipse 3.5 but running with Eclipse 3.7 API */ public interface IBuildConfiguration { } eclipse-mercurialeclipse-1.9.4/plugin/src/org/eclipse/core/resources/IResourceFilterDescription.java000066400000000000000000000002601173713500500340560ustar00rootroot00000000000000package org.eclipse.core.resources; /** * Place holder for compiling ME with Eclipse 3.5 but running with Eclipse 3.7 API */ public interface IResourceFilterDescription { } eclipse-mercurialeclipse-1.9.4/plugin/styles/000077500000000000000000000000001173713500500213225ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/styles/log_style000066400000000000000000000000761173713500500232510ustar00rootroot00000000000000changeset = log_style.tmpl tag = '{tag}_,_' last_tag = '{tag}'eclipse-mercurialeclipse-1.9.4/plugin/styles/log_style.tmpl000066400000000000000000000003731173713500500242240ustar00rootroot00000000000000

{desc|escape|tabindent}
eclipse-mercurialeclipse-1.9.4/plugin/styles/log_style_fast000066400000000000000000000001421173713500500242600ustar00rootroot00000000000000changeset = log_style_fast.tmpl start_files = '' file = '\n' end_files = '' eclipse-mercurialeclipse-1.9.4/plugin/styles/log_style_fast.tmpl000066400000000000000000000004141173713500500252350ustar00rootroot00000000000000

{desc|escape|tabindent} {files}
eclipse-mercurialeclipse-1.9.4/plugin/styles/log_style_with_files000066400000000000000000000006541173713500500254700ustar00rootroot00000000000000changeset = log_style_with_files.tmpl start_file_adds = '' file_add = '\n' end_file_adds = '' start_file_dels = '' file_del = '\n' end_file_dels = '' start_file_mods = '' file_mod = '\n' end_file_mods = '' start_file_copies = '' file_copy = '\n' end_file_copies = '' tag = '{tag}_,_' last_tag = '{tag}' eclipse-mercurialeclipse-1.9.4/plugin/styles/log_style_with_files.tmpl000066400000000000000000000005211173713500500264340ustar00rootroot00000000000000

{desc|escape|tabindent} {file_adds} {file_dels} {file_mods} {file_copies}
eclipse-mercurialeclipse-1.9.4/plugin/test/000077500000000000000000000000001173713500500207565ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/000077500000000000000000000000001173713500500215345ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/000077500000000000000000000000001173713500500233305ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/000077500000000000000000000000001173713500500265605ustar00rootroot00000000000000AbstractMercurialTestCase.java000066400000000000000000000201411173713500500344050ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.List; import junit.framework.TestCase; import com.vectrace.MercurialEclipse.commands.HgClients; import com.vectrace.MercurialEclipse.commands.TestConfiguration; import com.vectrace.MercurialEclipse.utils.ResourceUtils; /** * Base class for test cases * * @author bastian */ public abstract class AbstractMercurialTestCase extends TestCase { public static final List CLONE_REPO_TEST1_CMD = new ArrayList(); public static final List CLONE_REPO_TEST2_CMD = new ArrayList(); public static final String TEST1_LOCAL_NAME = "mercurialeclipse_tests_TEST1"; public static final String TEST2_LOCAL_NAME = "mercurialeclipse_tests_TEST2"; public static final String TEST1_REPO = "http://freehg.org/u/bastiand/mercurialeclipse_test1/"; public static final String TEST2_REPO = "http://freehg.org/u/bastiand/mercurialeclipse_test2/"; static { CLONE_REPO_TEST1_CMD.add("hg"); CLONE_REPO_TEST1_CMD.add("clone"); CLONE_REPO_TEST1_CMD.add(TEST1_REPO); CLONE_REPO_TEST1_CMD.add(TEST1_LOCAL_NAME); CLONE_REPO_TEST2_CMD.add("hg"); CLONE_REPO_TEST2_CMD.add("clone"); CLONE_REPO_TEST2_CMD.add(TEST2_REPO); CLONE_REPO_TEST2_CMD.add(TEST2_LOCAL_NAME); } /** * */ public AbstractMercurialTestCase() { } /** * @param name * @throws IOException * @throws InterruptedException */ public AbstractMercurialTestCase(String name) throws IOException, InterruptedException { super(name); } public static boolean deleteDirectory(File path) { return ResourceUtils.delete(path, true); } public static boolean move(File srcDir, File destDir){ boolean ok = srcDir.renameTo(destDir); if(ok){ return true; } // we have different file systems here, so stupid Sun JDK can't move files around // we have to copy & move files manually... How stupid is this??? ok = copyDir(srcDir, destDir); if(!ok){ return false; } return ResourceUtils.delete(srcDir, true); } /** * Copies recursively source to destination directory * @param sourceDir must exist * @param destDir may not exist * @return true if everything was copied, false if at least one child was not copied */ public static boolean copyDir(File sourceDir, File destDir) { if(!destDir.exists()) { boolean ok = destDir.mkdirs(); if(!ok && !destDir.exists()){ MercurialEclipsePlugin.logError("Could not create directory '" + destDir, null); return false; } } File[] children = sourceDir.listFiles(); for(File source : children) { String name = source.getName(); File dest = new File(destDir, name); if(source.isDirectory()) { boolean ok = copyDir(source, dest); if(!ok){ return false; } } boolean ok = copyFile(source, dest); if(!ok){ return false; } } return true; } /** * Single file copy operation. * @param source - should be file only * @param destination - should be already created * @return true if source was successfully copied */ public static boolean copyFile(File source, File destination) { if (source == null || destination == null) { MercurialEclipsePlugin.logError("Could not copy file '" + source + "' to '" + destination + "'", null); return false; } /* * prevent from overhead on identical files - this works fine * only if source and destination are on the same partition (=> the * same filesystem). If both files are on different partitions, then * 1) the file size could differ because of different chunk size * 2) the file time could differ because of different timestamp * formats on different file systems (e.g. NTFS and FAT) */ if (destination.lastModified() == source.lastModified() && destination.length() == source.length()) { return true; } boolean success = true; FileInputStream fin = null; // Streams to the two files. FileOutputStream fout = null; // These are closed in the finally block. try { // Open a stream to the input file and get a channel from it fin = new FileInputStream(source); FileChannel in = fin.getChannel(); // Now get the output channel FileChannel out; fout = new FileOutputStream(destination); // open file stream out = fout.getChannel(); // get its channel // Query the size of the input file long numbytes = in.size(); // Bulk-transfer all bytes from one channel to the other. // This is a special feature of FileChannel channels. // See also FileChannel.transferFrom( ) // TransferTo does not work under certain Linux kernel's // with java 1.4.2, see bug // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5056395 // in.transferTo(0, numbytes, out); out.transferFrom(in, 0, numbytes); } catch (IOException e) { MercurialEclipsePlugin.logError("Could not copy file '" + source + "' to '" + destination + "'", e); success = false; } finally { // Always close input and output streams. Doing this closes // the channels associated with them as well. if (fin != null) { try { fin.close(); } catch (IOException e) { MercurialEclipsePlugin.logError("Could not close file stream for file '" + source + "'", e); success = false; } } if (fout != null) { try { fout.close(); boolean modified = destination.setLastModified(source.lastModified()); if(!modified){ MercurialEclipsePlugin.logError("Could not update last modified stamp for file '" + destination + "'", null); } } catch (IOException e) { MercurialEclipsePlugin.logError("Could not close file stream for file '" + destination + "'", e); success = false; } } } return success; } /** * @throws IOException * @throws InterruptedException */ protected String executeCommand(List cmd) throws IOException, InterruptedException { ProcessBuilder builder = new ProcessBuilder(cmd); builder.redirectErrorStream(true); Process process = builder.start(); LineNumberReader err = null; StringBuilder result = new StringBuilder(""); try { err = new LineNumberReader(new InputStreamReader( process.getInputStream())); int ret = process.waitFor(); String line = err.readLine(); while (line != null) { result.append("\n"); result.append(line); line = err.readLine(); } if (ret != 0) { throw new RuntimeException( "Cannot clone test repository. Err-Output:".concat(result.toString())); } } finally { if (err != null) { err.close(); } } return result.toString(); } /* * (non-Javadoc) * * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); TestConfiguration cfg = new TestConfiguration(); HgClients.initialize(cfg, cfg, cfg); // clean up test1 repo deleteDirectory(new File(TEST1_LOCAL_NAME)); // clean up test2 repo deleteDirectory(new File(TEST2_LOCAL_NAME)); // set up test repository 1 String result = executeCommand(CLONE_REPO_TEST1_CMD); System.out.println(result); // set up test repository 2 result = executeCommand(CLONE_REPO_TEST2_CMD); System.out.println(result); } /* * (non-Javadoc) * * @see junit.framework.TestCase#tearDown() */ @Override protected void tearDown() throws Exception { super.tearDown(); // clean up test1 repo deleteDirectory(new File(TEST1_REPO)); // clean up test2 repo deleteDirectory(new File(TEST2_REPO)); } } eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/annotations/000077500000000000000000000000001173713500500311155ustar00rootroot00000000000000AnnotateCommandTest.java000066400000000000000000000036561173713500500356230ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/annotations/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.annotations; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.List; import java.util.Locale; import java.util.TimeZone; import com.vectrace.MercurialEclipse.commands.HgAnnotateClient; import junit.framework.TestCase; public class AnnotateCommandTest extends TestCase { public static final DateFormat DATE_FORMAT = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy Z", Locale.ENGLISH); static { DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); } private List createFromStdOut(String name) { return HgAnnotateClient.createFromStdOut( getClass().getResourceAsStream(name + ".out")).getAnnotateBlocks(); } public void test1() { List blocks = createFromStdOut("annotate1"); assertEquals(48, blocks.size()); checkBlock(blocks, 0, "zingo", "146:16cd70529433", "Tue Feb 05 20:17:52 2008 +0000", 0, 0); checkBlock(blocks, 1, "zingo", "151:893d61d581c6", "Thu Mar 27 21:47:06 2008 +0000", 1, 5); } private void checkBlock(List blocks, int i, String user, String rev, String date, int startLine, int endLine){ AnnotateBlock block = blocks.get(i); assertEquals(user, block.getUser()); assertEquals(rev, block.getRevision().toString()); assertEquals(startLine, block.getStartLine()); assertEquals(endLine, block.getEndLine()); assertEquals(date, DATE_FORMAT.format(block.getDate())); } } eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/annotations/annotate1.out000066400000000000000000000220771173713500500335500ustar00rootroot00000000000000 zingo 146 16cd70529433 Tue Feb 05 21:17:52 2008 +0100: /******************************************************************************* zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * Copyright (c) 2006-2008 VecTrace (Zingo Andersen) and others. zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * All rights reserved. This program and the accompanying materials zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * are made available under the terms of the Eclipse Public License v1.0 zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * which accompanies this distribution, and is available at zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * http://www.eclipse.org/legal/epl-v10.html zingo 146 16cd70529433 Tue Feb 05 21:17:52 2008 +0100: * zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * Contributors: zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * VecTrace (Zingo Andersen) - implementation zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * Software Balm Consulting Inc (Peter Hunnisett ) - some updates zingo 151 893d61d581c6 Thu Mar 27 22:47:06 2008 +0100: * StefanC - some updates zingo 146 16cd70529433 Tue Feb 05 21:17:52 2008 +0100: *******************************************************************************/ zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: package com.vectrace.MercurialEclipse.team; zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: jerome+hg 204 c5395616db77 Sun Mar 23 20:15:59 2008 +0100: import org.eclipse.core.resources.IResource; Peter 64 894d3a9c2e02 Thu Nov 16 22:53:26 2006 -0600: import org.eclipse.core.resources.team.IMoveDeleteHook; zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: import org.eclipse.core.runtime.CoreException; zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: import org.eclipse.team.core.RepositoryProvider; zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: import org.eclipse.team.core.history.IFileHistoryProvider; zingo 119 e479e7717c86 Sat Sep 08 23:32:36 2007 +0200: zingo 120 19ad87ea98db Sun Sep 09 13:09:40 2007 +0200: import com.vectrace.MercurialEclipse.history.MercurialHistoryProvider; zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: /** zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: * @author zingo zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: * zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: */ zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: public class MercurialTeamProvider extends RepositoryProvider zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: { Peter 64 894d3a9c2e02 Thu Nov 16 22:53:26 2006 -0600: stch 135 35121497ff05 Tue Nov 20 12:19:40 2007 +0100: public static final String ID = "com.vectrace.MercurialEclipse.team.MercurialTeamProvider"; zingo 120 19ad87ea98db Sun Sep 09 13:09:40 2007 +0200: MercurialHistoryProvider FileHistoryProvider; zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: /** zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: * zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: */ zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: public MercurialTeamProvider() zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: { zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: super(); zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: FileHistoryProvider = null; //Delay creation until needed new MercurialFileHistoryProvider(); zingo 71 864aa7a8ce1a Fri Dec 22 23:46:50 2006 +0100: // System.out.println("MercurialTeamProvider.MercurialTeamProvider()"); zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: } zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: /* (non-Javadoc) zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: * @see org.eclipse.team.core.RepositoryProvider#configureProject() zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: */ zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: //@Override stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: @Override stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: public void configureProject() throws CoreException zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: { jerome+hg 204 c5395616db77 Sun Mar 23 20:15:59 2008 +0100: getProject().refreshLocal(IResource.DEPTH_INFINITE, null); jerome+hg 204 c5395616db77 Sun Mar 23 20:15:59 2008 +0100: getProject().getFolder(".hg").setTeamPrivateMember(true); zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: } zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: /* (non-Javadoc) zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: * @see org.eclipse.core.resources.IProjectNature#deconfigure() zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: */ zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: public void deconfigure() throws CoreException zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: { zingo 15 02a39822c7be Fri May 19 23:04:24 2006 +0200: // System.out.println("MercurialTeamProvider.deconfigure()"); zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: } zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: /* (non-Javadoc) zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: * @see org.eclipse.team.core.RepositoryProvider#getID() zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: */ zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: //@Override stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: @Override stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: public String getID() zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: { zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: String ID; zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: ID=getClass().getName(); zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: // System.out.println("MercurialTeamProvider.getID() ID="+ID+" RepositoryPath=" + getRepositoryPath()); zingo 6 30f3620e3a2a Tue Feb 07 23:57:53 2006 +0200: return ID; zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: } zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: @Override stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: public IMoveDeleteHook getMoveDeleteHook() Peter 64 894d3a9c2e02 Thu Nov 16 22:53:26 2006 -0600: { zingo 71 864aa7a8ce1a Fri Dec 22 23:46:50 2006 +0100: // System.out.println("MercurialTeamProvider.getMoveDeleteHook()"); Peter 64 894d3a9c2e02 Thu Nov 16 22:53:26 2006 -0600: return new HgMoveDeleteHook(); Peter 64 894d3a9c2e02 Thu Nov 16 22:53:26 2006 -0600: } zingo 79 3590e08abad7 Mon Jan 01 22:43:34 2007 +0100: zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: /* (non-Javadoc) zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: * @see org.eclipse.team.core.RepositoryProvider#getFileHistoryProvider() zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: */ stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: @Override stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: public IFileHistoryProvider getFileHistoryProvider() zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: { zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: if( FileHistoryProvider == null) zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: { zingo 120 19ad87ea98db Sun Sep 09 13:09:40 2007 +0200: FileHistoryProvider = new MercurialHistoryProvider(); zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: } zingo 119 e479e7717c86 Sat Sep 08 23:32:36 2007 +0200: // System.out.println("getFileHistoryProvider()"); zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: return FileHistoryProvider; zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: } zingo 103 3c5806534308 Sun Jul 22 21:50:14 2007 +0200: zingo 79 3590e08abad7 Mon Jan 01 22:43:34 2007 +0100: /* (non-Javadoc) zingo 79 3590e08abad7 Mon Jan 01 22:43:34 2007 +0100: * @see org.eclipse.team.core.RepositoryProvider#canHandleLinkedResources() zingo 79 3590e08abad7 Mon Jan 01 22:43:34 2007 +0100: */ stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: @Override stefanc 221 41a8f5926910 Sun Mar 30 01:06:38 2008 +0100: public boolean canHandleLinkedResources() zingo 79 3590e08abad7 Mon Jan 01 22:43:34 2007 +0100: { zingo 79 3590e08abad7 Mon Jan 01 22:43:34 2007 +0100: return true; zingo 79 3590e08abad7 Mon Jan 01 22:43:34 2007 +0100: } zingo 0 5ff6dbe5d3f8 Wed Nov 23 21:36:48 2005 +0200: } eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/000077500000000000000000000000001173713500500303615ustar00rootroot00000000000000AbstractCommandTest.java000066400000000000000000000067371173713500500350640ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * stefanc implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import junit.framework.TestCase; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author stefanc * */ public class AbstractCommandTest extends TestCase { @Override public final void setUp() throws Exception { File where = getRepository(); if(where.exists()) { deleteRepository(); if(where.exists()) { throw new IllegalStateException(where.getAbsolutePath() + " must not exist"); } } where.deleteOnExit(); createEmptyRepository(new File("test/empty-test-repo.zip"), where); TestConfiguration cfg = new TestConfiguration(); HgClients.initialize(cfg, cfg, cfg); } private void createEmptyRepository(File zip, File dest) { try { ZipInputStream zipped = new ZipInputStream(new FileInputStream(zip)); ZipEntry entry; while(null != (entry = zipped.getNextEntry())) { File file = new File(dest.getAbsolutePath() + File.separator + entry.getName()); if(entry.isDirectory()) { file.mkdirs(); } } zipped.close(); zipped = new ZipInputStream(new FileInputStream(zip)); while(null != (entry = zipped.getNextEntry())) { File file = new File(dest.getAbsolutePath() + File.separator + entry.getName()); if(!entry.isDirectory()) { file.createNewFile(); FileOutputStream out = new FileOutputStream(file); byte[] buff = new byte[1024]; int read = 0; while(-1 != (read = zipped.read(buff))) { out.write(buff, 0, read); } out.close(); } } } catch(Exception e) { System.err.println("Failed creating repository"); e.printStackTrace(System.err); dest.delete(); } } public final HgRoot getRepository() throws IOException { String testRepoRoot = System.getProperty("java.io.tmpdir") + File.separator + "test/repo"; HgRoot where = new HgRoot(testRepoRoot); return where; } @Override public final void tearDown() throws Exception { try { super.tearDown(); deleteRepository(); } catch(Exception ex) { ex.printStackTrace(System.err); throw ex; } } private void deleteRepository() throws IOException { File repository = getRepository(); delTree(repository); assertFalse("Unable to delete test repository", repository.exists()); } private void delTree(File dir) { File[] sub = dir.listFiles(); for (File file : sub) { if(file.isDirectory()) { delTree(file); } assertTrue(!file.exists() || file.delete()); } assertTrue(!dir.exists() || dir.delete()); } public void testCreateRepo() throws Exception { assertTrue(getRepository().exists()); } protected void addToRepository(File newFile) throws InterruptedException, IOException { Runtime runtime = Runtime.getRuntime(); runtime.exec("hg add " + newFile.getCanonicalPath(), null, getRepository()).waitFor(); } } HgBranchClientTest.java000066400000000000000000000064341173713500500346270ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * zk implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import junit.framework.TestCase; import com.vectrace.MercurialEclipse.model.Branch; /** * @author Zsolt Koppany * */ public class HgBranchClientTest extends TestCase { public void testParseValidBranches() throws Exception { String[] lines = { " default 27860:6be4e6914439", "cb-5.4 27832:33ab0c49de97", "cb-5.5.0 27769:3c679028db6e", "cmr-5.4 25057:13b6d1a4e4ce", " cb-tracker-baselining 24953:3d176bf4dc2d", "cb-5.3 24126:cd008bd788e9", "createreferringissue-feature 27521:3615d5cc7a6f (inactive)", "ehcache-conversion-branch 27378:fdb7771ddc89 (inactive)", "gravatar-feature 27273:347b8185f056 (inactive)", "milestone-feature 26734:b3332c14b4a4 (inactive)", "fop-1.0-experiment 26374:2bb9b137ae89 (inactive)", "cb-5.4.2-AUO 24622:a294bf6d8ce4 (inactive)", "mr-access-feature 23693:a2f11c74e8b8 (inactive) ", "rebase keepbranches 2139:a73da2849655 (inactive)" }; for (String line : lines) { Branch branch = HgBranchClient.parseBranch(line); assertTrue(branch.getName().trim().length() > 0); assertEquals(branch.getName().trim(), branch.getName()); assertTrue(branch.getGlobalId().trim().length() > 0); assertEquals(branch.getGlobalId().trim(), branch.getGlobalId()); } } public void testParseBranch() throws Exception { Branch branch = HgBranchClient.parseBranch(" a test 3:066ee3f79d2a"); assertEquals("a test", branch.getName()); assertEquals(3, branch.getRevision()); assertEquals("066ee3f79d2a", branch.getGlobalId()); assertTrue(branch.isActive()); branch = HgBranchClient.parseBranch("* 2:5a953790aa12 (inactive)"); assertEquals("*", branch.getName()); assertEquals(2, branch.getRevision()); assertEquals("5a953790aa12", branch.getGlobalId()); assertFalse(branch.isActive()); branch = HgBranchClient.parseBranch("default 0:fd83cc49d230 (inactive)"); assertEquals("default", branch.getName()); assertEquals(0, branch.getRevision()); assertEquals("fd83cc49d230", branch.getGlobalId()); assertFalse(branch.isActive()); branch = HgBranchClient.parseBranch("rebase keepbranches 2139:a73da2849655 (inactive) "); assertEquals("rebase keepbranches", branch.getName()); assertEquals(2139, branch.getRevision()); assertEquals("a73da2849655", branch.getGlobalId()); assertFalse(branch.isActive()); branch = HgBranchClient.parseBranch("rebase keepbranches"); assertNull(branch); branch = HgBranchClient.parseBranch("2139:a73da2849655"); assertNull(branch); } } HgCommitClientTest.java000066400000000000000000000045451173713500500346630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * stefanc implementation * Adam Berkes (Intland) - restructure, special character tests *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.util.ArrayList; import java.util.List; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author stefanc * */ public class HgCommitClientTest extends AbstractCommandTest { private static final String UE = "\u00FC"; private static final String OE = "\u00F6"; private static final String AE = "\u00E4"; private static final String SS = "\u00DF"; /* (non-Javadoc) * @see com.vectrace.MercurialEclipse.commands.AbstractCommandTest#testCreateRepo() */ public void testCommitSimpleMessage() throws Exception { doCommit("Simple", "the message"); } /* (non-Javadoc) * @see com.vectrace.MercurialEclipse.commands.AbstractCommandTest#testCreateRepo() */ public void testCommitMessageWithQuote() throws Exception { doCommit("Trasan 'O Banarne", "is this message \" really escaped?"); } public void testCommitMessageWithSpecialChars1() throws Exception { String special1 = "árvíztűrő tükörfúrógép"; String special2 = "Qualit"+AE+"ts Ger"+AE+"te Pl"+AE+"ne Liebesgr"+UE+""+SS+"e Grundgeb"+UE+"hr Kocht"+OE+"pfe"; doCommit("Simple", special1); doCommit("Simple", special2, "dummy2.txt"); } private void doCommit(String user, String message) throws Exception { doCommit(user, message, "dummy.txt"); } private void doCommit(String user, String message, String commitFileName) throws Exception { File root = getRepository(); File newFile = new File(root.getAbsolutePath(), commitFileName); assertTrue("Unable to create file to commit", newFile.createNewFile()); addToRepository(newFile); HgRoot hgroot = new HgRoot(root.getAbsolutePath()); List files = new ArrayList(); files.add(newFile); HgCommitClient.commit(hgroot, files, user, message, false); } } HgDebugInstallTest.java000066400000000000000000000026601173713500500346450ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * bastian implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import com.vectrace.MercurialEclipse.AbstractMercurialTestCase; import com.vectrace.MercurialEclipse.exception.HgException; /** * @author bastian * */ public class HgDebugInstallTest extends AbstractMercurialTestCase { /* * (non-Javadoc) * * @see com.vectrace.MercurialEclipse.AbstractMercurialTestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); } /* * (non-Javadoc) * * @see com.vectrace.MercurialEclipse.AbstractMercurialTestCase#tearDown() */ @Override protected void tearDown() throws Exception { super.tearDown(); } /** * Test method for * {@link com.vectrace.MercurialEclipse.commands.HgDebugInstallClient#debugInstall()}. * @throws HgException */ public void testDebugInstall() throws HgException { String result; result = HgDebugInstallClient.debugInstall(); assertTrue(result != null); } } HgIdentClientTest.java000066400000000000000000000020231173713500500344630ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * stefanc implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.InputStream; import junit.framework.TestCase; /** * @author stefanc * */ public class HgIdentClientTest extends TestCase { public void testGetCurrentChangesetId() throws Exception { String expected = "9b417223cbb2f53e54872bfbd559db35645a6afb"; InputStream dirstate = Thread.currentThread().getContextClassLoader() .getResourceAsStream("dirstate"); String id = HgIdentClient.getCurrentChangesetId(dirstate); assertEquals(expected, id); } } HgStatusClientTest.java000066400000000000000000000017301173713500500347070ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import junit.framework.TestCase; import com.vectrace.MercurialEclipse.model.HgRoot; /** * @author Stefan * */ public class HgStatusClientTest extends TestCase { @Override protected void setUp() throws Exception { TestConfiguration cfg = new TestConfiguration(); HgClients.initialize(cfg, cfg, cfg); } public void testGetStatus() throws Exception { HgStatusClient.getDirtyFiles(new HgRoot(".")); } } HgTagClientTests.java000066400000000000000000000056611173713500500343310ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/******************************************************************************* * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.util.Collection; import java.util.Iterator; import junit.framework.TestCase; import com.vectrace.MercurialEclipse.HgRevision; import com.vectrace.MercurialEclipse.model.Tag; /** * @author Zsolt Koppany * @version $Id$ */ public class HgTagClientTests extends TestCase { public void testGetTags1() throws Exception { String[] lines = { "cb-3-6-RC1 7144:3e28ba45c18e", "end_of_metrics_branch 7117:db9d060ed00f", "cb-3-5-RC 6472:37e681b9c47b", "CB-3-5-RC 6472:37e681b9c47b", "original 5999:fc532a302004", "tip 23323:e374027944fb", "Root_eclipse-2-1 5601:8de90d654b96", }; Collection tags = HgTagClient.getTags(null, lines); Iterator it = tags.iterator(); Tag tag = it.next(); assertEquals(HgRevision.TIP.getChangeset(), tag.getName()); tag = it.next(); assertEquals("CB-3-5-RC", tag.getName()); tag = it.next(); assertEquals("cb-3-5-RC", tag.getName()); tag = it.next(); assertEquals("cb-3-6-RC1", tag.getName()); tag = it.next(); assertEquals("end_of_metrics_branch", tag.getName()); tag = it.next(); assertEquals("original", tag.getName()); tag = it.next(); assertEquals("Root_eclipse-2-1", tag.getName()); assertEquals(lines.length, tags.size()); } public void testGetTags2() throws Exception { String[] lines = { "tip 1377:288718b86ade", "release_1.2 941:c3db62d68609", "RELEASE_1.2 941:c3db62d68609", "RELEASE_1.4 1280:0fedfb9cf182", "RELEASE_1.3 1019:758c1089d4f0", "RELEASE_1.1 867:5dbd10536a7d", "RELEASE_1.0 741:e97205e404e7", "RELEASE_0.2 239:4b5fcdf8128f", "RELEASE_0.1 40:dde832884afc" }; Collection tags = HgTagClient.getTags(null, lines); Iterator it = tags.iterator(); Tag tag = it.next(); assertEquals(HgRevision.TIP.getChangeset(), tag.getName()); tag = it.next(); assertEquals("RELEASE_0.1", tag.getName()); tag = it.next(); assertEquals("RELEASE_0.2", tag.getName()); tag = it.next(); assertEquals("RELEASE_1.0", tag.getName()); tag = it.next(); assertEquals("RELEASE_1.1", tag.getName()); tag = it.next(); assertEquals("RELEASE_1.2", tag.getName()); tag = it.next(); assertEquals("release_1.2", tag.getName()); tag = it.next(); assertEquals("RELEASE_1.3", tag.getName()); } } TestConfiguration.java000066400000000000000000000053141173713500500346170ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/commands/******************************************************************************* * Copyright (c) 2005-2008 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Stefan implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.commands; import java.io.File; import java.io.PrintStream; import java.util.HashMap; import java.util.Map; import junit.framework.TestCase; import com.vectrace.MercurialEclipse.exception.HgCoreException; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.HgRoot; import com.vectrace.MercurialEclipse.preferences.MercurialPreferenceConstants; /** * @author Stefan * */ public class TestConfiguration extends TestCase implements IConsole, IErrorHandler, IConfiguration { private final Map preferences = new HashMap() { { put(MercurialPreferenceConstants.PREF_CONSOLE_DEBUG, "true"); } }; public void test(){ // just a dumy method for JUnit to avoid test failure because of missing test } public PrintStream getOutputStream() { return System.out; } public void logError(Throwable e) { fail(e.getMessage()); } public void logWarning(String message, Throwable e) { fail(e.getMessage()); } public String getDefaultUserName() { return "foo"; } public String getExecutable() { String path = "hg"; // path = "hg"; return path; } public int getTimeOut(String commandId) { return 12000; } public void commandCompleted(int exitCode, long timeInMillis, String message, Throwable error) { System.out.println(exitCode + " - " + message); if (error != null) { error.printStackTrace(System.err); } } public void commandInvoked(String command) { System.out.println(command); } public void printError(String message, Throwable root) { System.err.println(message); root.printStackTrace(System.err); } public void printMessage(String message, Throwable root) { System.out.println(message); if (root != null) { root.printStackTrace(System.out); } } public String getPreference(String preferenceConstant, String defaultIfNotSet) { String pref = preferences.get(preferenceConstant); if (pref != null) { return pref; } return defaultIfNotSet; } public HgRoot getHgRoot(File file) { try { return HgRootClient.getHgRoot(file); } catch (HgException e) { throw new HgCoreException(e); } } } eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/storage/000077500000000000000000000000001173713500500302245ustar00rootroot00000000000000HgRepositoryAuthCrpyterTests.java000066400000000000000000000033041173713500500366640ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2009 Intland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Adam Berkes (Intland) - implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.io.File; import java.security.InvalidKeyException; import javax.crypto.SecretKey; import junit.framework.TestCase; /** * @author adam.berkes */ public class HgRepositoryAuthCrpyterTests extends TestCase { private File keyFile; @Override protected void setUp() throws Exception { super.setUp(); keyFile = File.createTempFile(".key", ""); } @Override protected void tearDown() throws Exception { super.tearDown(); if(keyFile != null && !keyFile.delete()) { keyFile.deleteOnExit(); } } public void testCrypt() throws Exception { SecretKey key = HgRepositoryAuthCrypter.generateKey(); HgRepositoryAuthCrypterFactory.writeBytesToFile(key.getEncoded(), keyFile); HgRepositoryAuthCrypter crypter = HgRepositoryAuthCrypterFactory.create(keyFile); String data = "test"; assertEquals(data, crypter.decrypt(crypter.encrypt(data))); } public void testWrongCrypt() throws Exception { try { HgRepositoryAuthCrypter.generateKey(); HgRepositoryAuthCrypterFactory.create(keyFile); } catch (InvalidKeyException ex) { return; } assertTrue("Crypter cannot created from empty key data", false); } } HgRepositoryLocationParserTests.java000066400000000000000000000143271173713500500373460ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/storage/******************************************************************************* * Copyright (c) 2009 Intland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Adam Berkes (Intland) - implementation * Andrei Loskutov - bug fixes *******************************************************************************/ package com.vectrace.MercurialEclipse.storage; import java.io.File; import junit.framework.TestCase; import com.vectrace.MercurialEclipse.exception.HgException; import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation; /** * Unit test for parsing/creating hg repository representation * @author adam.berkes */ public class HgRepositoryLocationParserTests extends TestCase { public void testParseLine() throws Exception { parseLine(false); } public void testParseLineEncrypted() throws Exception { parseLine(true); } public void testParseLineWithProject() throws Exception { final String uri = "http://javaforge.com/hg/hgeclipse"; final String user = "test"; final String password = "test"; final String alias = "default"; IHgRepositoryLocation location = HgRepositoryLocationParser.parseLine(createTestLine(uri, user, password, alias, true)); assertNotNull(location); assertEquals(uri, location.getLocation()); assertEquals(user, location.getUser()); assertEquals(password, location.getPassword()); assertEquals(alias, location.getLogicalName()); } public void testCreateLine() throws Exception { final String repo = "http://javaforge.com/hg/hgeclipse"; final String user = "test"; final String password = "test"; final String alias = "default"; IHgRepositoryLocation location = new HgRepositoryLocation(alias, repo, user, password); String repoLine = HgRepositoryLocationParser.createLine(location); assertNotNull(repoLine); assertTrue(repoLine.length() > 0); assertEquals(createTestLine(location.getLocation(), location.getUser(), location.getPassword(), location.getLogicalName(), true), repoLine); } public void testCreateLineWithProject() throws Exception { final String repo = "http://javaforge.com/hg/hgeclipse"; final String user = "test"; final String password = "test"; final String alias = "default"; IHgRepositoryLocation location = new HgRepositoryLocation(alias, repo, user, password); String repoLine = HgRepositoryLocationParser.createLine(location); assertNotNull(repoLine); assertTrue(repoLine.length() > 0); assertEquals(createTestLine(location.getLocation(), location.getUser(), location.getPassword(), location.getLogicalName(), true), repoLine); } public void testParseCreateLineLocalWinOld() throws Exception { final String uri = "C:\\Documents and settings\\workspace\\hgeclipse"; final String alias = "default"; final String user = "test"; final String password = "test"; String saveString = null; try { IHgRepositoryLocation location = HgRepositoryLocationParser.parseLine(alias, uri, user, password); assertNotNull(location); assertEquals(uri, location.getLocation()); assertEquals(user, location.getUser()); assertEquals(password, location.getPassword()); assertEquals(alias, location.getLogicalName()); saveString = HgRepositoryLocationParser.createSaveString(location); } catch(HgException ex) { if (File.pathSeparator.equals("\\")) { assertTrue(ex.getMessage(), false); } return; } assertNotNull(saveString); assertTrue(saveString.length() > 0); assertEquals(uri + HgRepositoryLocationParser.SPLIT_TOKEN + user + HgRepositoryLocationParser.PASSWORD_TOKEN + password + HgRepositoryLocationParser.ALIAS_TOKEN + alias, saveString); } public void testParseCreateLineLocalLinOld() throws Exception { final String uri = "/home/adam.berkes/workspace/hgeclipse"; final String alias = "default"; IHgRepositoryLocation location = HgRepositoryLocationParser.parseLine(alias, uri, null, null); assertNotNull(location); assertEquals(uri, location.getLocation()); assertEquals(null, location.getUser()); assertEquals(null, location.getPassword()); assertEquals(alias, location.getLogicalName()); String saveString = HgRepositoryLocationParser.createSaveString(location); assertNotNull(saveString); assertTrue(saveString.length() > 0); assertEquals(uri + HgRepositoryLocationParser.ALIAS_TOKEN + alias, saveString); } private void parseLine(boolean toEncryptAuth) throws Exception { final String uri = "http://javaforge.com/hg/hgeclipse"; final String user = "test"; final String password = "test"; final String alias = "default"; IHgRepositoryLocation location = HgRepositoryLocationParser.parseLine(createTestLine(uri, user, password, alias, toEncryptAuth)); assertNotNull(location); assertEquals(uri, location.getLocation()); assertEquals(user, location.getUser()); assertEquals(password, location.getPassword()); assertEquals(alias, location.getLogicalName()); } private String createTestLine(String uri, String user, String password, String alias, boolean toEncryptAuth) { HgRepositoryAuthCrypter crypter = HgRepositoryAuthCrypterFactory.create(); StringBuilder line = new StringBuilder("d"); line.append(uri.length()); line.append(HgRepositoryLocationParser.PART_SEPARATOR); line.append(uri); line.append(HgRepositoryLocationParser.PART_SEPARATOR); if (toEncryptAuth) { user = HgRepositoryLocationParser.ENCRYPTED_PREFIX + HgRepositoryLocationParser.PART_SEPARATOR + crypter.encrypt(user); } line.append(user.length()); line.append(HgRepositoryLocationParser.PART_SEPARATOR); line.append(user); line.append(HgRepositoryLocationParser.PART_SEPARATOR); if (toEncryptAuth) { password = HgRepositoryLocationParser.ENCRYPTED_PREFIX + HgRepositoryLocationParser.PART_SEPARATOR + crypter.encrypt(password); } line.append(password.length()); line.append(HgRepositoryLocationParser.PART_SEPARATOR); line.append(password); line.append(HgRepositoryLocationParser.PART_SEPARATOR); line.append(alias.length()); line.append(HgRepositoryLocationParser.PART_SEPARATOR); line.append(alias); return line.toString(); } } eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/utils/000077500000000000000000000000001173713500500277205ustar00rootroot00000000000000ChangeSetUtilsTest.java000066400000000000000000000045541173713500500342360ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/utils/******************************************************************************* * Copyright (c) 2005-2010 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Philip Graf implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import junit.framework.TestCase; import com.vectrace.MercurialEclipse.model.ChangeSet; /** * Tests for {@link ChangeSetUtils}. * * @author Philip Graf */ public class ChangeSetUtilsTest extends TestCase { /** * Tests for {@link ChangeSetUtils#getPrintableTagsString(ChangeSet)}. */ public void testGetPrintableTagsString() { assertEquals("no changeset", "", ChangeSetUtils.getPrintableTagsString(null)); ChangeSet changeSet = new ChangeSet.Builder(0, "a", "b", "c", "d", null).build(); assertEquals("changeset without tags", "", ChangeSetUtils.getPrintableTagsString(changeSet)); changeSet = new ChangeSet.Builder(0, "a", "b", "c", "d", null).tags("tag1").build(); assertEquals("changeset with one tag", "tag1", ChangeSetUtils.getPrintableTagsString(changeSet)); changeSet = new ChangeSet.Builder(0, "a", "b", "c", "d", null).tags("tag1_,_tag2").build(); assertEquals("changeset with two tags", "tag1, tag2", ChangeSetUtils.getPrintableTagsString(changeSet)); changeSet = new ChangeSet.Builder(0, "a", "b", "c", "d", null).tags("tag1_,_tag2_,_tag3").build(); assertEquals("changeset with three tags", "tag1, tag2, tag3", ChangeSetUtils.getPrintableTagsString(changeSet)); } /** * Tests for {@link ChangeSetUtils#getPrintableRevisionShort(ChangeSet)}. */ public void testGetPrintableRevisionShort() { assertEquals("no changeset", "", ChangeSetUtils.getPrintableRevisionShort(null)); ChangeSet changeSet = new ChangeSet.Builder(1, "a", "b", "c", "d", null).build(); assertEquals("changeset without short revision", "1", ChangeSetUtils.getPrintableRevisionShort(changeSet)); changeSet = new ChangeSet.Builder(1, "a", "b", "c", "d", null).nodeShort("cafebeef").build(); assertEquals("changeset with short revision", "1:cafebeef", ChangeSetUtils.getPrintableRevisionShort(changeSet)); } } eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/utils/StringUtilsTests.java000066400000000000000000000026411173713500500341000ustar00rootroot00000000000000/******************************************************************************* * Copyright (c) 2005-2009 VecTrace (Zingo Andersen) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * zk implementation *******************************************************************************/ package com.vectrace.MercurialEclipse.utils; import junit.framework.TestCase; /** * @author Zsolt Koppany */ public class StringUtilsTests extends TestCase { public void testRemoveLineBreaks() { assertEquals("", StringUtils.removeLineBreaks("\r\n")); assertEquals("", StringUtils.removeLineBreaks(" \r\n ")); assertEquals("", StringUtils.removeLineBreaks("\r\n ")); assertEquals("", StringUtils.removeLineBreaks(" \r\n")); assertEquals("abc def", StringUtils.removeLineBreaks("abc\r\ndef")); assertEquals("abc def", StringUtils.removeLineBreaks("abc\r\n def")); assertEquals("abc def", StringUtils.removeLineBreaks("abc \r\n def")); assertEquals("abc def", StringUtils.removeLineBreaks("abc\t \r\n def")); assertEquals("hello abcdef", StringUtils.removeLineBreaks("hello\rabcdef")); assertEquals("hello abcdef", StringUtils.removeLineBreaks("hello\nabcdef")); } } eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/wizards/000077500000000000000000000000001173713500500302435ustar00rootroot00000000000000ConfigurationWizardMainPageTests.java000066400000000000000000000035761173713500500374570ustar00rootroot00000000000000eclipse-mercurialeclipse-1.9.4/plugin/test/com/vectrace/MercurialEclipse/wizards/******************************************************************************* * Copyright (c) 2009 Intland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zsolt Koppany - zsolt.koppany@intland.com *******************************************************************************/ package com.vectrace.MercurialEclipse.wizards; import java.io.File; import java.net.URL; import junit.framework.TestCase; /** * @author Zsolt Koppany */ public class ConfigurationWizardMainPageTests extends TestCase { public void testGetLocalDirectory() throws Exception { ConfigurationWizardMainPage cp = new ConfigurationWizardMainPage("", "", null); assertNull(cp.getLocalDirectory(null)); assertNull(cp.getLocalDirectory("http://intland.com")); assertNull(cp.getLocalDirectory("https://codebeamer.com/cb/issue/29229?orgDitchnetTabPaneId=task-details-comments")); assertNull(cp.getLocalDirectory("ftp://ftp.codebeamer.com")); assertNull(cp.getLocalDirectory("ssh://www.intland.com")); assertNull(cp.getLocalDirectory("")); assertNull(cp.getLocalDirectory(" ")); assertNull(cp.getLocalDirectory(null)); File tempDir = File.createTempFile("hgplg", ""); tempDir.delete(); tempDir.mkdir(); try { assertTrue(tempDir.isDirectory()); File dir = cp.getLocalDirectory(tempDir.getAbsolutePath()); assertTrue(dir.isDirectory()); URL url = new URL("file", "", tempDir.getAbsolutePath()); dir = cp.getLocalDirectory(url.toString()); assertTrue(dir.isDirectory()); dir = cp.getLocalDirectory("file://" + tempDir.getAbsolutePath()); assertTrue(dir.isDirectory()); } finally { tempDir.delete(); } } } eclipse-mercurialeclipse-1.9.4/plugin/test/compare-test-plan.txt000066400000000000000000000071721173713500500250610ustar00rootroot00000000000000Test plan for MercurialEclipse's various comparison functionality TODO: add variations for these situations: workspace under symbolic link, linked resources, repository root above workspace root. From the context menu ===================== 1. Compare with parent (without local change) Expected: The local file is compared with the file's previous change. Local resource is editable and savable. Always in sync. Should work on rename. Current: Works 2. Compare with parent (with local saved change) Expected: The local file is compared with its clean copy. Local resource is editable and savable. Always in sync. Should work on rename. Current: Works 3. Compare with to Another Revision (single file) Expected: Compare Editor shown. Renamed file is treated as different file. Not always in sync. Local resource is editable and savable. Current: Works 4. Compare with to Another Revision (single folder/project) Expected: Compare Editor shown. Renamed file is treated as different file. Not always in sync. Local resource is editable and savable. Current: Works 5. Repeat step 1-4 with unsaved local changes Expected: Current: From the History view ===================== 1. In History view of a file, select two revisions and compare with each other Expected: Compare Editor shown. Three-way comparison is used when the two revision have a common parent. Current: Does not work before rename. 2. In History view select a revision and compare with current Expected: Current: 3. In History view of a file with no renames double click on a row in file history Expected: Show uneditable comparison of the two revisions Current: Works 4. In History view of a file double click on a row in file history on a revision of a rename Expected: Show uneditable comparison of the two revisions Current: 5. In History view of a file double click on a row in file history on a revision prior to a rename where the rename source is a path under the project Expected: Show uneditable comparison of the two revisions Current: Does not work 6. In History view of a file double click on a row in file history on a revision prior to a rename where the rename source is a path not under any project in the workspace (eg where src was renamed to plugin/src and the project is at plugin) Expected: Show uneditable comparison of the two revisions Current: Does not work 7. Repeat 2-6 but instead double clicking on the row click on the file in the "affected paths" zone Expected: Current: From the Sync view ================== 1. In Sync view, file in incoming changesets of an added file Expected: File is shown in one pane, other pane is blank, uneditable Current: Works 2. In Sync view, file in incoming changesets of an changed file Expected: File is compared with the changeset's parent revision, uneditable Current: Works 3. In Sync view, file in incoming changesets of an renamed file Expected: File is compared with the changeset's parent revision. Current: 4. In Sync view, file in incoming changesets that is based on an incoming changeset that the file was renamed in (the file doesn't exist in workspace) Expected: File is compared with the changeset's parent revision. Current: 5. In Sync view, file in outgoing changesets Expected: File is compared with the changeset's parent revision. Current: Works 6. In Sync view, file in uncommitted changesets Expected: The local file is compared with its clean copy. Local resource is editable and savable. Always in sync. Should work on rename. Current: Works (except local rename?) eclipse-mercurialeclipse-1.9.4/plugin/test/dirstate000066400000000000000000000770031173713500500225270ustar00rootroot00000000000000Ar#˲>T+Y5dZjn Ir79src/com/vectrace/MercurialEclipse/wizards/ImportPage.javan RIr7Csrc/com/vectrace/MercurialEclipse/commands/mq/HgQRefreshClient.javanIr7Asrc/com/vectrace/MercurialEclipse/menu/SingleResourceHandler.javandIr7@src/com/vectrace/MercurialEclipse/wizards/BackoutWizardPage.javanIr7Csrc/com/vectrace/MercurialEclipse/actions/AddToWorkspaceAction.javan#Ir7).settings/org.eclipse.pde.api.tools.prefsn Ir7=src/com/vectrace/MercurialEclipse/wizards/SyncRepoWizard.javanIr7icons/wizards/share_wizban.pngn Ir7:src/com/vectrace/MercurialEclipse/actions/HgOperation.javanEzIr7Bsrc/com/vectrace/MercurialEclipse/repository/RepositoriesView.javan-Ir7Esrc/com/vectrace/MercurialEclipse/storage/HgCommitMessageManager.javan"IsT?src/com/vectrace/MercurialEclipse/team/cache/AbstractCache.javan I{s9src/com/vectrace/MercurialEclipse/commands/HgClients.javan dIr75src/com/vectrace/MercurialEclipse/model/Ancestor.javanoIr7@src/com/vectrace/MercurialEclipse/menu/RefreshStatusHandler.javan TIr7Bsrc/com/vectrace/MercurialEclipse/commands/HgTransplantClient.javanIr7Hsrc/com/vectrace/MercurialEclipse/preferences/PreferenceInitializer.javan Ir7;src/com/vectrace/MercurialEclipse/team/DecoratorImages.javanPIr7Fsrc/com/vectrace/MercurialEclipse/ui/ResourcesTreeContentProvider.javanIr7?src/com/vectrace/MercurialEclipse/commands/HgResolveClient.javanIr7:src/com/vectrace/MercurialEclipse/team/images/modified.pngnIr7icons/cview16/newstream_wiz.gifnaIr7icons/flatLayout.gifnQIr7@src/com/vectrace/MercurialEclipse/wizards/ImportOptionsPage.javanCIr7=src/com/vectrace/MercurialEclipse/model/FlaggedAdaptable.javanRIr7=src/com/vectrace/MercurialEclipse/team/CompareWithAction.javan Ir79src/com/vectrace/MercurialEclipse/menu/SwitchHandler.javanIr76src/com/vectrace/MercurialEclipse/model/Signature.javanIr73src/com/vectrace/MercurialEclipse/model/HgFile.javanhIr7!icons/wizards/newlocation_wiz.gifnEIr73src/com/vectrace/MercurialEclipse/model/HgRoot.javan?I{<>src/com/vectrace/MercurialEclipse/views/console/HgConsole.javan QIr7>src/com/vectrace/MercurialEclipse/menu/FlagPropertyTester.javanIr75src/com/vectrace/MercurialEclipse/views/Messages.javan*Ir7src/com/vectrace/MercurialEclipse/dialogs/MultiLineDialog.javan Ir7=src/com/vectrace/MercurialEclipse/commands/HgPatchClient.javanNIr7=src/com/vectrace/MercurialEclipse/wizards/messages.propertiesnIr7icons/actions/merge.gifnIr7;src/com/vectrace/MercurialEclipse/preferences/Messages.javan>Ir7Isrc/com/vectrace/MercurialEclipse/team/MercurialProjectSetCapability.javanIr7Tsrc/com/vectrace/MercurialEclipse/wizards/MercurialParticipantSynchronizeWizard.javan7Ir7?src/com/vectrace/MercurialEclipse/exception/messages.propertiesnIr7=src/com/vectrace/MercurialEclipse/menu/DisconnectHandler.javanlIr7Dsrc/com/vectrace/MercurialEclipse/synchronize/MercurialSyncInfo.javanFIs6Rsrc/com/vectrace/MercurialEclipse/synchronize/MercurialSynchronizeParticipant.javanIr7:src/com/vectrace/MercurialEclipse/team/cache/Messages.javanIr7?src/com/vectrace/MercurialEclipse/operations/InitOperation.javan$?Ir7src/com/vectrace/MercurialEclipse/commands/HgStatusClient.javanRIr7icons/cview16/share_project.gifnIr74src/com/vectrace/MercurialEclipse/menu/Messages.javanIr7Asrc/com/vectrace/MercurialEclipse/annotations/AnnotateBlocks.javan >Ir7Asrc/com/vectrace/MercurialEclipse/team/MercurialTeamProvider.javan:Ir7:src/com/vectrace/MercurialEclipse/commands/GpgCommand.javan pIr7"icons/wizards/newstream_wizban.gifn,Ir7src/com/vectrace/MercurialEclipse/commands/HgRemoveClient.javanYIr79src/com/vectrace/MercurialEclipse/menu/UpdateHandler.javanIr7icons/elcl16/expandall.gifn Ir7;src/com/vectrace/MercurialEclipse/menu/BookmarkHandler.javanIr7Ir79src/com/vectrace/MercurialEclipse/ui/SWTWidgetHelper.javan1Ir7@src/com/vectrace/MercurialEclipse/team/SingleResourceAction.javanIr7=src/com/vectrace/MercurialEclipse/storage/messages.propertiesnnI>src/com/vectrace/MercurialEclipse/team/ResourceProperties.javanIr7icons/compare_view.gifn =Ir7Ir7 icons/add.gifn~Ir75src/com/vectrace/MercurialEclipse/ui/BranchTable.javanIr72src/com/vectrace/MercurialEclipse/ui/TagTable.javan!Ir7 icons/cview16/repository_rep.gifnIr79src/com/vectrace/MercurialEclipse/menu/CommitHandler.javan"Ir7?src/com/vectrace/MercurialEclipse/history/MercurialHistory.javan/Ir77src/com/vectrace/MercurialEclipse/SafeWorkspaceJob.javan$)Ir78src/com/vectrace/MercurialEclipse/ui/ChangesetTable.javanIr7 .cprojectn/kIr77src/com/vectrace/MercurialEclipse/wizards/PullPage.javan aIr7Bsrc/com/vectrace/MercurialEclipse/commands/mq/HgQImportClient.javanMMI=src/com/vectrace/MercurialEclipse/wizards/PullRepoWizard.javanCIr7@src/com/vectrace/MercurialEclipse/commands/HgAnnotateClient.javanIr71src/com/vectrace/MercurialEclipse/HgRevision.javan,Ir77src/com/vectrace/MercurialEclipse/menu/SignHandler.javanIr7Lsrc/com/vectrace/MercurialEclipse/preferences/PerformancePreferencePage.javanIr7=src/com/vectrace/MercurialEclipse/team/images/not_tracked.pngnIr7;src/com/vectrace/MercurialEclipse/wizards/OutgoingPage.javanIr7;src/com/vectrace/MercurialEclipse/wizards/ImportWizard.javanhIr7icons/dlcl16/refresh.gifn3Ir7icons/mercury_Hg.pngn)Ir7src/com/vectrace/MercurialEclipse/commands/HgParentClient.javanIr7 .classpathnIIr79src/com/vectrace/MercurialEclipse/utils/CompareUtils.javanIr7:src/com/vectrace/MercurialEclipse/menu/QImportHandler.javanIr7:src/com/vectrace/MercurialEclipse/wizards/ServeWizard.javanrIr7=src/com/vectrace/MercurialEclipse/team/images/modified_ov.gifnIr7Csrc/com/vectrace/MercurialEclipse/operations/UnShelveOperation.javan-Ir7src/com/vectrace/MercurialEclipse/menu/ExportPatchHandler.javanIr7@src/com/vectrace/MercurialEclipse/wizards/mq/QRefreshWizard.javan:Ir7>src/com/vectrace/MercurialEclipse/commands/HgUpdateClient.javan'Ir7 styles/log_style_with_files.tmpln Ir7@src/com/vectrace/MercurialEclipse/wizards/NewLocationWizard.javancIr77src/com/vectrace/MercurialEclipse/model/GChangeSet.javanIr7;src/com/vectrace/MercurialEclipse/model/FlaggedProject.javanIsAsrc/com/vectrace/MercurialEclipse/operations/ShelveOperation.javan gIr7Gsrc/com/vectrace/MercurialEclipse/history/MercurialHistoryProvider.javan |Ir7src/com/vectrace/MercurialEclipse/commands/HgRenameClient.javanIr7;src/com/vectrace/MercurialEclipse/utils/messages.propertiesnIr7Hsrc/com/vectrace/MercurialEclipse/preferences/GeneralPreferencePage.javanIr7icons/actions/synch.gifnIr7>src/com/vectrace/MercurialEclipse/commands/messages.propertiesnIr77src/com/vectrace/MercurialEclipse/menu/PullHandler.javan@Ir7>src/com/vectrace/MercurialEclipse/commands/AbstractClient.javanIr7@src/com/vectrace/MercurialEclipse/team/cache/messages.propertiesn2I|RFsrc/com/vectrace/MercurialEclipse/team/cache/MercurialStatusCache.javanIr7styles/log_style.tmplnIr7Ksrc/com/vectrace/MercurialEclipse/team/cache/RefreshLocalChangesetsJob.javanIr7/src/com/vectrace/MercurialEclipse/Messages.javanIr7@src/com/vectrace/MercurialEclipse/model/FlagManagerListener.javan/Ir7Jsrc/com/vectrace/MercurialEclipse/annotations/ShowAnnotationOperation.javan-Ir7>src/com/vectrace/MercurialEclipse/wizards/AddBranchWizard.javanIr77src/com/vectrace/MercurialEclipse/wizards/Messages.javan bIr7:src/com/vectrace/MercurialEclipse/utils/ChangeSetNode.javanIr7src/com/vectrace/MercurialEclipse/wizards/CloneRepoWizard.javanIr7;src/com/vectrace/MercurialEclipse/annotations/Messages.javan$I~H@src/com/vectrace/MercurialEclipse/commands/HgOutgoingClient.javan Ir7src/com/vectrace/MercurialEclipse/commands/IConfiguration.javan Ir75src/com/vectrace/MercurialEclipse/model/HgFolder.javan Ir7>src/com/vectrace/MercurialEclipse/commands/HgIgnoreClient.javanIr7Osrc/com/vectrace/MercurialEclipse/preferences/MercurialPreferenceConstants.javanIr7Gsrc/com/vectrace/MercurialEclipse/repository/model/AllRootsElement.javan3Ir7@src/com/vectrace/MercurialEclipse/team/ShowAnnotationAction.javan'Ir7@src/com/vectrace/MercurialEclipse/history/MercurialRevision.javan=Ir7Dsrc/com/vectrace/MercurialEclipse/repository/actions/TeamAction.javan%[Ir7Bsrc/com/vectrace/MercurialEclipse/repository/actions/HgAction.javanI{=W;src/com/vectrace/MercurialEclipse/DefaultConfiguration.javan2Ir7".settings/org.eclipse.jdt.ui.prefsnIr78src/com/vectrace/MercurialEclipse/wizards/ClonePage.javan.Ir7Qsrc/com/vectrace/MercurialEclipse/annotations/SourceViewerInformationControl.javanIr7:src/com/vectrace/MercurialEclipse/wizards/mq/Messages.javan4Ir7;src/com/vectrace/MercurialEclipse/wizards/PushPullPage.javan+Ir7>src/com/vectrace/MercurialEclipse/commands/HgBranchClient.javan.Ir7=src/com/vectrace/MercurialEclipse/commands/HgMergeClient.javanIr7icons/elcl16/refresh.gifnIr77src/com/vectrace/MercurialEclipse/menu/PushHandler.javanIr7.hgsigsn I{:src/com/vectrace/MercurialEclipse/team/messages.propertiesnIr7Asrc/com/vectrace/MercurialEclipse/dialogs/CommitResourceUtil.javanIr7>src/com/vectrace/MercurialEclipse/model/HgResourceMapping.javanIr7icons/actions/tag.gifn6gIr79src/com/vectrace/MercurialEclipse/wizards/RebasePage.javanIr79src/com/vectrace/MercurialEclipse/team/images/ignored.pngnIIr79src/com/vectrace/MercurialEclipse/team/images/managed.pngnHIr7src/com/vectrace/MercurialEclipse/commands/HgBisectClient.javanIr7styles/log_stylen]Ir7Isrc/com/vectrace/MercurialEclipse/preferences/ConsolePreferencesPage.javanoIr7=src/com/vectrace/MercurialEclipse/actions/messages.propertiesn\Ir7src/com/vectrace/MercurialEclipse/ui/UntrackedFilesFilter.javanI|};src/com/vectrace/MercurialEclipse/commands/HgLogClient.javan)Ir7Csrc/com/vectrace/MercurialEclipse/wizards/mq/QImportWizardPage.javan6Isf>src/com/vectrace/MercurialEclipse/commands/HgCommitClient.javanzIr7;src/com/vectrace/MercurialEclipse/menu/RollbackHandler.javanIr7>src/com/vectrace/MercurialEclipse/menu/ImportPatchHandler.javanXIr7Fsrc/com/vectrace/MercurialEclipse/repository/model/HgModelElement.javan^Ir7icons/rem_co.gifn2Ir7=src/com/vectrace/MercurialEclipse/wizards/TransplantPage.javanIr7:src/com/vectrace/MercurialEclipse/menu/BackoutHandler.javan"FIr7Hsrc/com/vectrace/MercurialEclipse/team/MercurialConfigurationWizard.javanIr7icons/sample_hg.gifn3Ir7Dsrc/com/vectrace/MercurialEclipse/dialogs/RevisionChooserDialog.javan $Ir7icons/wizards/droplets-50.pngn!Ir7.fbprefsnWIr7icons/comments.gifnEYIsEsrc/com/vectrace/MercurialEclipse/team/cache/LocalChangesetCache.javanIr7;src/com/vectrace/MercurialEclipse/menu/QRefreshHandler.javanIr7build.propertiesn IsBsrc/com/vectrace/MercurialEclipse/annotations/CommitterColors.javanIr76src/com/vectrace/MercurialEclipse/menu/TagHandler.javan#I|gEsrc/com/vectrace/MercurialEclipse/team/IStorageMercurialRevision.javanIr7?src/com/vectrace/MercurialEclipse/commands/mq/HgQPopClient.javan Ir7Jsrc/com/vectrace/MercurialEclipse/repository/actions/RemoveRootAction.javan Ir7Csrc/com/vectrace/MercurialEclipse/compare/HgCompareEditorInput.javanGIr7>src/com/vectrace/MercurialEclipse/commands/HgConfigClient.javanyIr7icons/branches_rep.gifnIr7plugin.propertiesn>Ir76src/com/vectrace/MercurialEclipse/menu/AddHandler.javan{Ir7;src/com/vectrace/MercurialEclipse/utils/HistoryPainter.javan Ir7>src/com/vectrace/MercurialEclipse/commands/HgRebaseClient.javankIr7Jsrc/com/vectrace/MercurialEclipse/team/images/deleted_still_tracked_ov.gifnGIr7icons/clcl16/refresh.gifn_Ir7>src/com/vectrace/MercurialEclipse/commands/HgIMergeClient.javanCIsMsrc/com/vectrace/MercurialEclipse/views/console/HgConsolePageParticipant.javanBIr7?src/com/vectrace/MercurialEclipse/wizards/TransplantWizard.javan!Ir7#icons/wizards/cleanmanifest_wiz.pngnIr79src/com/vectrace/MercurialEclipse/exception/Messages.javanjIr7=src/com/vectrace/MercurialEclipse/ResourceAdapterFactory.javan?Ir7@src/com/vectrace/MercurialEclipse/storage/ProjectDataLoader.javanIr78src/com/vectrace/MercurialEclipse/menu/StripHandler.javan&Ir7Hsrc/com/vectrace/MercurialEclipse/team/cache/IncomingChangesetCache.javanIr7;src/com/vectrace/MercurialEclipse/compare/RevisionNode.javanIIr7>src/com/vectrace/MercurialEclipse/menu/CommitMergeHandler.javanIr7;src/com/vectrace/MercurialEclipse/wizards/RebaseWizard.javan5Ir7icons/export.gifnIr7Bsrc/com/vectrace/MercurialEclipse/repository/RepositorySorter.javanIr7>src/com/vectrace/MercurialEclipse/wizards/ServeWizardPage.javan>Ir7Jsrc/com/vectrace/MercurialEclipse/storage/HgRepositoryLocationManager.javanGIr75src/com/vectrace/MercurialEclipse/AdapterFactory.javanIr7icons/reltopics_co.gifnIr7Ctest/com/vectrace/MercurialEclipse/commands/HgDebugInstallTest.javan`Ir7Gtest/com/vectrace/MercurialEclipse/annotations/AnnotateCommandTest.javan @Ir7?src/com/vectrace/MercurialEclipse/team/MultipleFilesAction.javan Ir7Osrc/com/vectrace/MercurialEclipse/repository/actions/ReplaceableIconAction.javanIr77src/com/vectrace/MercurialEclipse/team/images/added.pngnIr70src/com/vectrace/MercurialEclipse/model/Tag.javanIr7Bsrc/com/vectrace/MercurialEclipse/annotations/AnnotateCommand.javanIIr78src/com/vectrace/MercurialEclipse/menu/MergeHandler.javan#YIr78src/com/vectrace/MercurialEclipse/dialogs/TagDialog.javanIr78src/com/vectrace/MercurialEclipse/ui/messages.propertiesn[Ir7=src/com/vectrace/MercurialEclipse/commands/IErrorHandler.javan_Ir7=src/com/vectrace/MercurialEclipse/commands/HgPathsClient.javan IIr7Rsrc/com/vectrace/MercurialEclipse/synchronize/actions/CommitSynchronizeAction.javan8Ir77src/com/vectrace/MercurialEclipse/model/FileStatus.javanIr7icons/actions/commit.gifn5Ir7Rsrc/com/vectrace/MercurialEclipse/annotations/HgPristineCopyQuickDiffProvider.javan&Ir7;src/com/vectrace/MercurialEclipse/views/messages.propertiesnKIr7;src/com/vectrace/MercurialEclipse/wizards/PushRepoPage.javanXIr7;src/com/vectrace/MercurialEclipse/dialogs/IgnoreDialog.javan iIr7?src/com/vectrace/MercurialEclipse/utils/HistoryPainterEdge.javanI|dHsrc/com/vectrace/MercurialEclipse/team/cache/OutgoingChangesetCache.javan6Ir79src/com/vectrace/MercurialEclipse/menu/RebaseHandler.javan Ir7Zsrc/com/vectrace/MercurialEclipse/synchronize/actions/ShowHistorySynchronizeOperation.javan8PIr7;src/com/vectrace/MercurialEclipse/views/PatchQueueView.javankIr7Atest/com/vectrace/MercurialEclipse/AbstractMercurialTestCase.javanP I{<>src/com/vectrace/MercurialEclipse/team/MercurialUtilities.javan{Ir7Hsrc/com/vectrace/MercurialEclipse/operations/CreateProjectOperation.javanIr7Bsrc/com/vectrace/MercurialEclipse/ui/UntrackedResourcesFilter.javan%Ir7;src/com/vectrace/MercurialEclipse/team/DecoratorStatus.javanFIr7icons/checkout_action.gifnjIzdMETA-INF/MANIFEST.MFnIr7Esrc/com/vectrace/MercurialEclipse/team/MercurialTeamProviderType.javanIr7>src/com/vectrace/MercurialEclipse/wizards/StripWizardPage.javanIr77src/com/vectrace/MercurialEclipse/ui/BookmarkTable.javan"Ir7@src/com/vectrace/MercurialEclipse/wizards/mq/QNewWizardPage.javanIr7Ctest/com/vectrace/MercurialEclipse/commands/HgCommitClientTest.javan*Ir7@src/com/vectrace/MercurialEclipse/commands/mq/HgQInitClient.javanIs]Dtest/com/vectrace/MercurialEclipse/commands/AbstractCommandTest.javan5Ir7?src/com/vectrace/MercurialEclipse/ui/ResourceLabelProvider.javan`Ir77src/com/vectrace/MercurialEclipse/wizards/HgWizard.javan8Ir78src/com/vectrace/MercurialEclipse/menu/QInitHandler.javanIr7=src/com/vectrace/MercurialEclipse/views/console/Messages.javanIr79src/com/vectrace/MercurialEclipse/team/images/removed.pngnkIr78src/com/vectrace/MercurialEclipse/menu/ServeHandler.javan Ir79src/com/vectrace/MercurialEclipse/storage/DataLoader.javan IIr7;src/com/vectrace/MercurialEclipse/wizards/HgWizardPage.javanIr7Gsrc/com/vectrace/MercurialEclipse/team/images/deleted_still_tracked.pngn4Ir7icons/history.gifn Ir7?src/com/vectrace/MercurialEclipse/wizards/mq/QImportWizard.javanIr7