Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce2009-09-29 21:18:28 -0400
committerShawn O. Pearce2009-09-29 21:18:28 -0400
commitdfbdc456d8645fc0c310b5e15cf8d25d8ff7f84b (patch)
tree73461cd1d4e0481e18d25b0c75bd2a4b6d130e45
downloadegit-dfbdc456d8645fc0c310b5e15cf8d25d8ff7f84b.tar.gz
egit-dfbdc456d8645fc0c310b5e15cf8d25d8ff7f84b.tar.xz
egit-dfbdc456d8645fc0c310b5e15cf8d25d8ff7f84b.zip
Initial EGit contribution to eclipse.org
Per CQ 3393 this is the initial contribution of the EGit project (an Eclipse team provider for Git) to eclipse.org. This initial version is derived from the historial EGit repository at commit a9578ba7361b66ab403c6605a1b87fb7b2f94c6e. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
-rw-r--r--.gitattributes1
-rw-r--r--EGIT_INSTALL47
-rw-r--r--LICENSE88
-rw-r--r--README165
-rw-r--r--SUBMITTING_PATCHES103
-rw-r--r--TODO55
-rw-r--r--org.eclipse.egit-feature/.project17
-rw-r--r--org.eclipse.egit-feature/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit-feature/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit-feature/build.properties3
-rw-r--r--org.eclipse.egit-feature/feature.properties123
-rw-r--r--org.eclipse.egit-feature/feature.xml79
-rw-r--r--org.eclipse.egit-feature/license.html79
-rw-r--r--org.eclipse.egit-updatesite/.project23
-rw-r--r--org.eclipse.egit-updatesite/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit-updatesite/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit-updatesite/index.html60
-rw-r--r--org.eclipse.egit-updatesite/site.xml14
-rw-r--r--org.eclipse.egit-updatesite/web/site.css12
-rw-r--r--org.eclipse.egit-updatesite/web/site.xsl214
-rw-r--r--org.eclipse.egit.core.test/.classpath7
-rw-r--r--org.eclipse.egit.core.test/.gitignore1
-rw-r--r--org.eclipse.egit.core.test/.project28
-rw-r--r--org.eclipse.egit.core.test/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit.core.test/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit.core.test/.settings/org.eclipse.jdt.core.prefs320
-rw-r--r--org.eclipse.egit.core.test/.settings/org.eclipse.jdt.ui.prefs9
-rw-r--r--org.eclipse.egit.core.test/META-INF/MANIFEST.MF20
-rw-r--r--org.eclipse.egit.core.test/build.properties4
-rw-r--r--org.eclipse.egit.core.test/org.eclipse.egit.core--All-Tests.launch41
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/T0003_AdaptableFileTreeIteratorTest.java77
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/mapping/T0002_history.java189
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/op/T0001_ConnectProviderOperationTest.java124
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/Activator.java59
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitTestCase.java54
-rw-r--r--org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestProject.java178
-rw-r--r--org.eclipse.egit.core/.classpath7
-rw-r--r--org.eclipse.egit.core/.gitignore1
-rw-r--r--org.eclipse.egit.core/.options1
-rw-r--r--org.eclipse.egit.core/.project28
-rw-r--r--org.eclipse.egit.core/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit.core/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit.core/.settings/org.eclipse.jdt.core.prefs320
-rw-r--r--org.eclipse.egit.core/.settings/org.eclipse.jdt.ui.prefs9
-rw-r--r--org.eclipse.egit.core/META-INF/MANIFEST.MF21
-rw-r--r--org.eclipse.egit.core/build.properties7
-rw-r--r--org.eclipse.egit.core/plugin.properties10
-rw-r--r--org.eclipse.egit.core/plugin.xml20
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/Activator.java102
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/AdaptableFileTreeIterator.java88
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java239
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java106
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/EclipseGitProgressTransformer.java110
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/GitCorePreferenceInitializer.java27
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/GitCorePreferences.java21
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/GitMoveDeleteHook.java205
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/GitProvider.java90
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/GitTag.java34
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/ResourceList.java43
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties51
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/UpdateJob.java164
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/BlobStorage.java81
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/CommitFileRevision.java131
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistory.java187
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistoryProvider.java38
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileRevision.java91
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/IndexFileRevision.java88
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommit.java42
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommitList.java21
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidWalk.java26
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/WorkspaceFileRevision.java56
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ExceptionCollector.java128
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/AssumeUnchangedOperation.java125
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/BranchOperation.java168
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/CloneOperation.java221
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/ConnectProviderOperation.java101
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/DisconnectProviderOperation.java91
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/ListRemoteOperation.java105
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperation.java154
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperationResult.java274
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperationSpecification.java83
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/ResetOperation.java244
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/TrackOperation.java149
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/UntrackOperation.java127
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/op/UpdateOperation.java46
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/project/GitProjectData.java491
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryChangeListener.java28
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryFinder.java143
-rw-r--r--org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java248
-rw-r--r--org.eclipse.egit.ui/.classpath7
-rw-r--r--org.eclipse.egit.ui/.gitignore1
-rw-r--r--org.eclipse.egit.ui/.options1
-rw-r--r--org.eclipse.egit.ui/.project30
-rw-r--r--org.eclipse.egit.ui/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit.ui/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit.ui/.settings/org.eclipse.jdt.core.prefs328
-rw-r--r--org.eclipse.egit.ui/.settings/org.eclipse.jdt.ui.prefs9
-rw-r--r--org.eclipse.egit.ui/META-INF/MANIFEST.MF27
-rw-r--r--org.eclipse.egit.ui/build.properties7
-rw-r--r--org.eclipse.egit.ui/icons/checkboxes/disabled_checked.gifbin0 -> 106 bytes
-rw-r--r--org.eclipse.egit.ui/icons/checkboxes/disabled_unchecked.gifbin0 -> 96 bytes
-rw-r--r--org.eclipse.egit.ui/icons/checkboxes/enabled_checked.gifbin0 -> 874 bytes
-rw-r--r--org.eclipse.egit.ui/icons/checkboxes/enabled_unchecked.gifbin0 -> 856 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/add.gifbin0 -> 318 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/author.gifbin0 -> 594 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/clear.gifbin0 -> 595 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/comment.gifbin0 -> 341 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/commit.gifbin0 -> 178 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/committer.gifbin0 -> 589 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/delete.gifbin0 -> 351 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/filterfolder.gifbin0 -> 153 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/filterproject.gifbin0 -> 154 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/filterrepo.gifbin0 -> 322 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/find.gifbin0 -> 546 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/next.gifbin0 -> 353 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/previous.gifbin0 -> 352 bytes
-rw-r--r--org.eclipse.egit.ui/icons/elcl16/trash.gifbin0 -> 590 bytes
-rw-r--r--org.eclipse.egit.ui/icons/etool16/newconnect_wiz.gifbin0 -> 368 bytes
-rw-r--r--org.eclipse.egit.ui/icons/obj16/import_obj.gifbin0 -> 357 bytes
-rw-r--r--org.eclipse.egit.ui/icons/ovr/assume_valid.gifbin0 -> 85 bytes
-rw-r--r--org.eclipse.egit.ui/icons/ovr/conflict.gifbin0 -> 194 bytes
-rw-r--r--org.eclipse.egit.ui/icons/ovr/staged.gifbin0 -> 114 bytes
-rw-r--r--org.eclipse.egit.ui/icons/ovr/staged_added.gifbin0 -> 169 bytes
-rw-r--r--org.eclipse.egit.ui/icons/ovr/staged_removed.gifbin0 -> 176 bytes
-rw-r--r--org.eclipse.egit.ui/icons/ovr/untracked.gifbin0 -> 79 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/checkoutd.pngbin0 -> 412 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/checkoute.pngbin0 -> 419 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/commitd.pngbin0 -> 431 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/commite.pngbin0 -> 435 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/fetchd.pngbin0 -> 359 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/fetche.pngbin0 -> 393 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/pushd.pngbin0 -> 372 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/pushe.pngbin0 -> 404 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/resetd.pngbin0 -> 382 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/resete.pngbin0 -> 408 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/trackd.pngbin0 -> 387 bytes
-rw-r--r--org.eclipse.egit.ui/icons/toolbar/tracke.pngbin0 -> 411 bytes
-rw-r--r--org.eclipse.egit.ui/icons/wizban/import_wiz.pngbin0 -> 6461 bytes
-rw-r--r--org.eclipse.egit.ui/icons/wizban/newconnect_wizban.pngbin0 -> 4918 bytes
-rw-r--r--org.eclipse.egit.ui/plugin.properties79
-rw-r--r--org.eclipse.egit.ui/plugin.xml391
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java397
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseAuthenticator.java58
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseProxySelector.java73
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java62
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/GitHistoryPageSource.java40
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java65
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIIcons.java140
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java141
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java1088
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java129
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java405
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitResourceNode.java123
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/SWTUtils.java595
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractOperationAction.java118
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractRevObjectAction.java27
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractRevObjectOperation.java22
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AssumeUnchanged.java29
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/BranchAction.java82
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitAction.java413
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexAction.java92
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithRevisionAction.java59
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Disconnect.java33
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/FetchAction.java52
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/HardResetToRevisionAction.java29
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/MixedResetToRevisionAction.java29
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PushAction.java53
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/QuickdiffBaselineOperation.java45
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryAction.java141
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetAction.java79
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetQuickdiffBaselineAction.java26
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetQuickdiffBaselineHeadParentAction.java25
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SetQuickdiffBaselineAction.java27
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowResourceInHistoryAction.java52
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SoftResetToRevisionAction.java29
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Track.java59
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Untrack.java29
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Update.java28
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/CloneDestinationPage.java346
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCloneWizard.java176
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitProjectsImportPage.java794
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/SourceBranchPage.java294
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/BaseWizardPage.java59
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/CenteredImageLabelProvider.java53
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/CheckboxLabelProvider.java156
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ClickableCellEditor.java69
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/ComboLabelingSupport.java78
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RefContentProposal.java140
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RefSpecPage.java299
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RefSpecPanel.java1832
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RepositorySelection.java134
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/RepositorySelectionPage.java675
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/components/SelectionChangeListener.java20
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/DecoratableResourceAdapter.java409
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitDocument.java195
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitLightweightDecorator.java655
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/GitQuickDiffProvider.java105
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/decorators/IDecoratableResource.java101
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/BranchSelectionDialog.java434
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CommitDialog.java792
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/factories/GitAdapterFactory.java37
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchResultDialog.java77
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchResultTable.java213
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchWizard.java190
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/TrackingRefUpdateContentProvider.java42
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitFileDiffViewer.java154
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitGraphTable.java239
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitMessageViewer.java262
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/CommitNavigationListener.java21
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiff.java118
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffContentProvider.java48
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FileDiffLabelProvider.java31
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindResults.java202
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindToolbar.java534
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/FindToolbarThread.java225
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GenerateHistoryJob.java77
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GitHistoryPage.java956
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GraphContentProvider.java29
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/GraphLabelProvider.java62
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/RevObjectSelectionProvider.java68
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTCommit.java28
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTCommitList.java59
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTPlotRenderer.java168
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/SWTWalk.java25
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitDecoratorPreferencePage.java937
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitPreferenceRoot.java34
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/GitProjectPropertyPage.java136
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/HistoryPreferencePage.java52
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/StorageSizeFieldEditor.java128
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/preferences/WindowCachePreferencePage.java69
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/ConfirmationPage.java224
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/PushResultDialog.java66
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/PushResultTable.java333
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/PushWizard.java252
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/RefUpdateContentProvider.java67
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/push/RefUpdateElement.java68
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/sharing/ExistingOrNewPage.java228
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/sharing/SharingWizard.java99
-rw-r--r--org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties397
-rw-r--r--org.eclipse.egit/.classpath6
-rw-r--r--org.eclipse.egit/.project28
-rw-r--r--org.eclipse.egit/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.egit/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.egit/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--org.eclipse.egit/META-INF/MANIFEST.MF7
-rw-r--r--org.eclipse.egit/about.ini28
-rw-r--r--org.eclipse.egit/build.properties3
-rw-r--r--org.eclipse.egit/egit.pngbin0 -> 1366 bytes
-rw-r--r--org.eclipse.egit/egit.svg134
-rwxr-xr-xtag_egit.sh47
250 files changed, 28426 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..f57840b7e
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.java diff=java
diff --git a/EGIT_INSTALL b/EGIT_INSTALL
new file mode 100644
index 000000000..81d0adab0
--- /dev/null
+++ b/EGIT_INSTALL
@@ -0,0 +1,47 @@
+
+ EGit Installation
+
+PREREQUISITES
+
+In order to install the Git Eclipse plugin you need to have the following
+things.
+
+- Eclipse version 3.3.1, or 3.4.0
+
+- Java 6. Java 1.5.0_11 and later seems to work. The reason is that
+ the garbage collection does not do a good enough job when using memory
+ mapped files. The sources can be hacked to used non-mmaped files but
+ that is very slow. JDK 1.4.x is *not* supported at all and JDK 1.5 is only
+ supported as long as it works :).
+
+- A reasonably recent version of Git itself installed on your platform to
+ take care of what the plugin does not yet do or do things that native
+ git does better. Some tests have been performed using both Cygwin and MSYS git.
+ Both have issues that we need both feedback and patches for.
+
+INSTALLATION INSTRUCTIONS
+
+- Delete any old versions of the plugin in the <eclipse-path>/plugins/org.eclipse.egit.*
+- Start eclipse
+- Make sure a recent JDK 1.5.0_11 or JDK 1.6.x is among your installed JRE's. Which
+ one is the default should not matter but Java 6 is recommended.
+- Import the egit projects. Make sure there are no compilation errors
+- Now you can either export the plugin to a set of jar files to use in an Eclipse
+ installation or run it from within Eclipse. The latter is for development and
+ tracking down bugs.
+- Export the plugin by selecting the org.eclipse.egit.* packages in package
+ explorer and choosing File/Export. Then select Deployable plug-ins and
+ fragments and choose the Next button. Set Directory to the top of your
+ installation directory (NOT the plugins directory). Select Finish. After
+ that restart Eclipse. You can associate a project withe Eclipse using the
+ Team>Share menu in the context menu when a project is selected.
+
+DEBUGGING INSTRUCTIONS
+- Select the org.eclipse.egit.ui project, and using the context menu select
+ Run As(or Debug As) / Eclipse Application. Make sure the application runs
+ using JDK 1.6 (or JDK1.5.0_11 or newer) if you have any problems.
+
+There may be errors in the <workspace>/.metadata/.log or even on stdout that can help
+you track down and problem. When reporting errors include stack traces and the commit
+id or the version your plugin is built from, or the version of the plugin if it does
+not contain a date.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..f61d34dfe
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,88 @@
+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.
+
+
diff --git a/README b/README
new file mode 100644
index 000000000..d54bf40fc
--- /dev/null
+++ b/README
@@ -0,0 +1,165 @@
+ == Eclipse GIT plugin ==
+
+This package is licensed under the EPL. Please refer to the COPYING
+and LICENSE files for the complete licenses within each package.
+
+This package is actually composed of three major components plus
+three for packaging.
+
+ org.eclipse.egit.core/
+
+ An Eclipse plugin providing an interface to org.eclipse.jgit
+ and support routines to allow processing against the Eclipse
+ workspace and resource APIs, rather than the standard Java
+ file APIs. It also supplies the team provider implementation.
+ Everything here is EPL.
+
+ org.eclipse.egit.ui/
+
+ An Eclipse plugin providing the user interface on top of
+ org.eclipse.egit.core.
+
+ Everything here is EPL.
+
+ org.eclipse.egit.core.test/
+
+ Unit tests for org.eclipse.egit.core.
+
+ Everything here is EPL.
+
+ org.eclipse.egit/
+
+ A plugin for packaging
+
+ Everything here is EPL.
+
+ org.eclipse.egit-feature
+
+ Also packaging. This project is for building an Eclipse "feature"
+ out of the plugins above.
+
+ Everything here is EPL.
+
+ org.eclipse.egit-updatesite/
+
+ This package is for producing and update site, i.e. a web site
+ you can point your eclipse at and just upgrade.
+
+ Everything here is EPL.
+
+ == WARNINGS / CAVEATS ==
+
+- Symbolic links are not supported because java does not support it.
+ Such links could be damaged.
+
+- Only the timestamp of the index is used by jgit check if the index
+ is dirty.
+
+- Don't try the plugin with a JDK other than 1.6 (Java 6) unless you
+ are prepared to investigate problems yourself. JDK 1.5.0_11 and later
+ Java 5 versions *may* work. Earlier versions do not. JDK 1.4 is *not*
+ supported. Apple's Java 1.5.0_07 is reported to work acceptably. We
+ have no information about other vendors. Please report your findings
+ if you try.
+
+- CRLF conversion is never performed. On Windows you should thereforc
+ make sure your projects and workspaces are configured to save files
+ with Unix (LF) line endings.
+
+ == COMPATIBILITY ==
+
+- Eclipse 3.4 is the minimum Eclipse version.
+
+- Newer version of EGit may implement new functionality, remove
+ existing functions and change others without other notice than what
+ is written in the commit log and source files themselves.
+
+
+ == Package Features ==
+
+ org.eclipse.egit.core/
+
+ * Supplies an Eclipse team provider.
+
+ * Connect/disconnect the provider to a project.
+
+ * Search for the repositories associated with a project by
+ autodetecting the GIT repository directories.
+
+ * Store which repositories are tied to which containers in the
+ Eclipse workspace.
+
+ * Tracks moves/renames/deletes and reflects them in the cache
+ tree.
+
+ * Resolves through linked containers.
+
+ org.eclipse.egit.ui/
+
+ * Connect team provider wizard panels.
+
+ * Connect to GIT team provider by making a new repository.
+
+ * Connect to GIT team provider by searching local filesystem
+ for existing repository directories.
+
+ * Team actions: track (add), untrack (remove), disconnect, show
+ history, compare version.
+
+ * Resource decorator shows file/directory state in the package
+ explorer and other views.
+
+ * Creating new commits or amending commits.
+
+ * Graphical history viewer with the ability to compare versions
+ using eclipse built-in compare editor.
+
+ * Clone, push, fetch
+
+ == Missing Features ==
+
+There are a lot of missing features. You need the real Git for this.
+For some operations it may just be the preferred solution also. There
+are not just a command line, there is e.g. git-gui that makes committing
+partial files simple.
+
+- Merging.
+
+- Repacking from within the plugin.
+
+- Generate a GIT format patch.
+
+- Apply a GIT format patch.
+
+- Documentation. :-)
+
+- gitattributes support
+ In particular CRLF conversion is not implemented. Files are treated
+ as byte sequences.
+
+- submodule support
+ Submodules are not supported or even recognized.
+
+- The Eclipse plugin cannot handle files outside any Eclipse project. You
+ need commit changes to such files outside of Eclipse.
+
+ == Support ==
+
+ Post question, comments or patches to the git@vger.kernel.org mailing list.
+
+
+ == Contributing ==
+
+ See SUBMITTING_PATCHES in this directory. However, feedback and bug reports
+ are also contributions.
+
+
+ == About GIT ==
+
+More information about GIT, its repository format, and the canonical
+C based implementation can be obtained from the GIT websites:
+
+ http://git.or.cz/
+ http://www.kernel.org/pub/software/scm/git/
+ http://www.kernel.org/pub/software/scm/git/docs/
+
diff --git a/SUBMITTING_PATCHES b/SUBMITTING_PATCHES
new file mode 100644
index 000000000..5d08c182f
--- /dev/null
+++ b/SUBMITTING_PATCHES
@@ -0,0 +1,103 @@
+Short Version:
+
+ - Make small logical changes.
+ - Provide a meaningful commit message.
+
+ - Review and follow the Eclipse Due Diligence Process
+
+ http://www.eclipse.org/legal/EclipseLegalProcessPoster.pdf
+
+ - Submit patch as an attachment to eclipse.org via bugzilla:
+
+ https://bugs.eclipse.org/bugs/enter_bug.cgi?product=EGit
+
+
+Long Version:
+
+I wanted a file describing how to submit patches for EGit,
+so I started with the one found in the core Git distribution
+(Documentation/SubmittingPatches), which itself was based on the
+patch submission guidelines for the Linux kernel.
+
+However there are quite a few differences, so please review and
+familiarize yourself with the following relevant bits:
+
+
+(1) Make separate commits for logically separate changes.
+
+Unless your patch is really trivial, you should not be sending
+out a patch that was generated between your working tree and your
+commit head. Instead, always make a commit with complete commit
+message and generate a series of patches from your repository.
+It is a good discipline.
+
+Describe the technical detail of the change(s).
+
+If your description starts to get too long, that's a sign that you
+probably need to split up your commit to finer grained pieces.
+
+I am very picky about formatting. Make sure your final version
+of every file was formatted using the Eclipse code formatter
+using the project specific settings (Properties->Java Code
+Style->Formatter->"Java Conventions [built-in]").
+
+
+(2) Generate your patch using git tools out of your commits.
+
+git based diff tools (git, and StGIT included) generate unidiff,
+which is the only acceptable format.
+
+You do not have to be afraid to use -M option to "git diff" or "git
+format-patch", if your patch involves file renames. The receiving
+end can handle them just fine.
+
+Please make sure your patch does not include any extra files which
+do not belong in a patch submission. Make sure to review your
+patch after generating it, to ensure accuracy. Before sending out,
+please make sure it cleanly applies to the "master" branch head.
+
+
+(3) Check the license.
+
+EGit is licensed under the Eclipse Public License (EPL).
+
+Under this licensing model *every* file within the project
+*must* list which license covers it in the header of the file.
+Any new contributions to an existing file *must* be submitted under
+the current license of that file. Any new files *must* clearly
+indicate which license they are provided under in the file header.
+
+Please verify that you are legally allowed and willing to submit your
+changes under the license covering each file *prior* to submitting
+your patch. It is virtually impossible to remove a patch once it
+has been applied and pushed out.
+
+
+(4) Review the Eclipse Due Diligence Process.
+
+ http://www.eclipse.org/legal/EclipseLegalProcessPoster.pdf
+
+
+(5) Sending your patches.
+
+"git format-patch" command follows the best current practice to
+format a commit as a reviewable text message.
+
+At the beginning of the patch should come your commit message,
+a line that consists of three dashes, followed by the diffstat
+information and the patch itself. If you are forwarding a patch
+from somebody else, optionally, at the beginning of the e-mail
+message just before the commit message starts, you can put a "From:
+" line to name that person.
+
+You often want to add additional explanation about the patch,
+other than the commit message itself. Place such "cover letter"
+material between the three dash lines and the diffstat, or please
+place it in the bug description itself.
+
+Open a new bug on the Eclipse bug tracker on the EGit project:
+
+ https://bugs.eclipse.org/bugs/enter_bug.cgi?product=EGit
+
+Attach the mailbox file(s) created by "git format-patch" to the bug.
+
diff --git a/TODO b/TODO
new file mode 100644
index 000000000..5f35b2517
--- /dev/null
+++ b/TODO
@@ -0,0 +1,55 @@
+= Eclipse Plugin Wishlist =
+
+Now that we have some basic features in the Eclipse plugin, we need
+to focus on making it usable by average users doing daily tasks.
+
+== Create Branch ==
+
+Create a new branch from any revision specification.
+
+== Delete Branch ==
+
+Delete a branch.
+
+== Switch Branch ==
+
+Switch to an existing branch, updating the working directory to match.
+
+Note that updating the working directory may require a 3 way merge
+if the working directory is dirty (git checkout -m).
+
+My usual git working style is to not switch branches with a dirty
+working directory; I always commit to the current branch before
+switching to a new one. I mention that because I assume it'll be
+easier to implement that workflow first; once you have commit
+capability, you can do that style of branch switching (either
+preventing the switch or doing an implicit commit when the working
+directory is dirty) without having to worry about merging. ''--
+Steven Grimm''
+
+== Merge ==
+
+Merging changes from one local branch to another.
+
+Again, like fetch I'd like to keep egit/jgit 100% pure Java and
+implement merge-recursive in Java. We may need to invoke RCS
+merge if Eclipse doesn't have its own 3 way file merge algorithm
+available, or do what core Git just did and implement a 3 way in
+memory merge algorithm. git-merge-recursive is only 1336 lines of C
+so it should not be too difficult to port the algorithm to pure Java.
+
+== SVN Integration ==
+
+It would be swell -- but put it at the bottom of your priority list
+-- to have git-svn interoperability; sadly most of my git usage at
+the moment is in cloned svn repositories and it would be great if
+egit could do the right thing when the current git repo is cloned
+from svn. What "the right thing" is, exactly, is debatable, but I
+suppose some kind of integration with the Subclipse plugin is one
+possibility (and if nothing else, that plugin probably has code
+that can be reused.) I'd like to be able to update from and commit
+to the parent svn repository. ''-- Steven Grimm''
+
+I'm considering this to be out of scope for the time being, but if
+someone takes it on and submits reasonable patches we'll include
+them. ''-- Shawn Pearce''
diff --git a/org.eclipse.egit-feature/.project b/org.eclipse.egit-feature/.project
new file mode 100644
index 000000000..1064bb024
--- /dev/null
+++ b/org.eclipse.egit-feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit-feature</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.FeatureBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.FeatureNature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.egit-feature/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit-feature/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..8d266d994
--- /dev/null
+++ b/org.eclipse.egit-feature/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:46:45 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit-feature/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit-feature/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..f468d739b
--- /dev/null
+++ b/org.eclipse.egit-feature/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:55:38 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit-feature/build.properties b/org.eclipse.egit-feature/build.properties
new file mode 100644
index 000000000..dd544b319
--- /dev/null
+++ b/org.eclipse.egit-feature/build.properties
@@ -0,0 +1,3 @@
+bin.includes = feature.xml,\
+ feature.properties,\
+ license.html
diff --git a/org.eclipse.egit-feature/feature.properties b/org.eclipse.egit-feature/feature.properties
new file mode 100644
index 000000000..7d59ded94
--- /dev/null
+++ b/org.eclipse.egit-feature/feature.properties
@@ -0,0 +1,123 @@
+###############################################################################
+# 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
+#
+###############################################################################
+
+# "copyright" property - text of the "Feature Update Copyright"
+copyright=\
+Copyright (c) 2005, 2009 Shawn Pearce, Robin Rosenberg, et.al.\n\
+All rights reserved. This program and the accompanying materials\n\
+are made available under the terms of the Eclipse Public License v1.0\n\
+which accompanies this distribution, and is available at\n\
+http://www.eclipse.org/legal/epl-v10.html\n
+################ end of copyright property ####################################
+
+# "licenseURL" property - URL of the "Feature License"
+# do not translate value - just change to point to a locale-specific HTML page
+licenseURL=license.html
+
+# "license" property - text of the "Feature Update License"
+# should be plain text version of license agreement pointed to be "licenseURL"
+license=\
+ECLIPSE FOUNDATION SOFTWARE USER AGREEMENT\n\
+March 17, 2005\n\
+\n\
+Usage Of Content\n\
+\n\
+THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR\n\
+OTHER MATERIALS FOR OPEN SOURCE PROJECTS (COLLECTIVELY "CONTENT").\n\
+USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS\n\
+AGREEMENT AND/OR THE TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR\n\
+NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU\n\
+AGREE THAT YOUR USE OF THE CONTENT IS GOVERNED BY THIS AGREEMENT\n\
+AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS\n\
+OR NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE\n\
+TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND CONDITIONS\n\
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED\n\
+BELOW, THEN YOU MAY NOT USE THE CONTENT.\n\
+\n\
+Applicable Licenses\n\
+\n\
+Unless otherwise indicated, all Content made available by the Eclipse Foundation\n\
+is provided to you under the terms and conditions of the Eclipse Public\n\
+License Version 1.0 ("EPL"). A copy of the EPL is provided with this\n\
+Content and is also available at http://www.eclipse.org/legal/epl-v10.html.\n\
+For purposes of the EPL, "Program" will mean the Content.\n\
+\n\
+Content includes, but is not limited to, source code, object code,\n\
+documentation and other files maintained in the Eclipse.org CVS\n\
+repository ("Repository") in CVS modules ("Modules") and made available\n\
+as downloadable archives ("Downloads").\n\
+\n\
+ - Content may be structured and packaged into modules to facilitate delivering,\n\
+ extending, and upgrading the Content. Typical modules may include plug-ins ("Plug-ins"),\n\
+ plug-in fragments ("Fragments"), and features ("Features").\n\
+ - Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java? ARchive)\n\
+ in a directory named "plugins".\n\
+ - A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material.\n\
+ Each Feature may be packaged as a sub-directory in a directory named "features".\n\
+ Within a Feature, files named "feature.xml" may contain a list of the names and version\n\
+ numbers of the Plug-ins and/or Fragments associated with that Feature.\n\
+ - Features may also include other Features ("Included Features"). Within a Feature, files\n\
+ named "feature.xml" may contain a list of the names and version numbers of Included Features.\n\
+\n\
+Features may also include other Features ("Included Features"). Files named\n\
+"feature.xml" may contain a list of the names and version numbers of\n\
+Included Features.\n\
+\n\
+The terms and conditions governing Plug-ins and Fragments should be\n\
+contained in files named "about.html" ("Abouts"). The terms and\n\
+conditions governing Features and Included Features should be contained\n\
+in files named "license.html" ("Feature Licenses"). Abouts and Feature\n\
+Licenses may be located in any directory of a Download or Module\n\
+including, but not limited to the following locations:\n\
+\n\
+ - The top-level (root) directory\n\
+ - Plug-in and Fragment directories\n\
+ - Inside Plug-ins and Fragments packaged as JARs\n\
+ - Sub-directories of the directory named "src" of certain Plug-ins\n\
+ - Feature directories\n\
+\n\
+Note: if a Feature made available by the Eclipse Foundation is installed using the\n\
+Eclipse Update Manager, you must agree to a license ("Feature Update\n\
+License") during the installation process. If the Feature contains\n\
+Included Features, the Feature Update License should either provide you\n\
+with the terms and conditions governing the Included Features or inform\n\
+you where you can locate them. Feature Update Licenses may be found in\n\
+the "license" property of files named "feature.properties". Such Abouts,\n\
+Feature Licenses and Feature Update Licenses contain the terms and\n\
+conditions (or references to such terms and conditions) that govern your\n\
+use of the associated Content in that directory.\n\
+\n\
+THE ABOUTS, FEATURE LICENSES AND FEATURE UPDATE LICENSES MAY REFER\n\
+TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS.\n\
+SOME OF THESE OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):\n\
+\n\
+ - Common Public License Version 1.0 (available at http://www.eclipse.org/legal/cpl-v10.html)\n\
+ - Apache Software License 1.1 (available at http://www.apache.org/licenses/LICENSE)\n\
+ - Apache Software License 2.0 (available at http://www.apache.org/licenses/LICENSE-2.0)\n\
+ - IBM Public License 1.0 (available at http://oss.software.ibm.com/developerworks/opensource/license10.html)\n\
+ - Metro Link Public License 1.00 (available at http://www.opengroup.org/openmotif/supporters/metrolink/license.html)\n\
+ - Mozilla Public License Version 1.1 (available at http://www.mozilla.org/MPL/MPL-1.1.html)\n\
+\n\
+IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR\n\
+TO USE OF THE CONTENT. If no About, Feature License or Feature Update License\n\
+is provided, please contact the Eclipse Foundation to determine what terms and conditions\n\
+govern that particular Content.\n\
+\n\
+Cryptography\n\
+\n\
+Content may contain encryption software. The country in which you are\n\
+currently may have restrictions on the import, possession, and use,\n\
+and/or re-export to another country, of encryption software. BEFORE\n\
+using any encryption software, please check the country's laws,\n\
+regulations and policies concerning the import, possession, or use,\n\
+and re-export of encryption software, to see if this is permitted.\n\
+\n\
+Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.\n
+########### end of license property ##########################################
+
diff --git a/org.eclipse.egit-feature/feature.xml b/org.eclipse.egit-feature/feature.xml
new file mode 100644
index 000000000..c3d0e2b03
--- /dev/null
+++ b/org.eclipse.egit-feature/feature.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+ id="org.eclipse.egit"
+ label="Eclipse Git Feature (Incubation)"
+ version="0.5.0.qualifier"
+ provider-name="eclipse.org"
+ plugin="org.eclipse.egit">
+
+ <description url="http://www.jgit.org">
+An Eclipse Git Plugin in pure Java.
+
+ !!!Uninstall any pre-0.5 plugins!!!
+
+@buildId@
+
+Changes on @branch@ since @refversion@:
+
+<![CDATA[@shortlog@]]>
+
+ </description>
+
+ <copyright>
+ %copyright
+ </copyright>
+
+ <license url="%licenseURL">
+ %license
+ </license>
+
+ <url>
+ <update label="Eclipse Update Site (experimental)" url="http://www.jgit.org/updates"/>
+ </url>
+
+ <requires>
+ <import plugin="org.eclipse.core.runtime" version="3.4" match="greaterOrEqual"/>
+ <import plugin="org.eclipse.core.resources"/>
+ <import plugin="org.eclipse.core.filesystem"/>
+ <import plugin="org.eclipse.ui"/>
+ <import plugin="org.eclipse.team.ui"/>
+ <import plugin="org.eclipse.jface.text"/>
+ <import plugin="org.eclipse.ui.ide"/>
+ <import plugin="org.eclipse.ui.workbench.texteditor"/>
+ <import plugin="org.eclipse.compare"/>
+ <import plugin="org.eclipse.core.net"/>
+ <import plugin="org.eclipse.team.core" version="3.4.0" match="greaterOrEqual"/>
+ <import plugin="org.eclipse.jsch.ui" version="1.1.100" match="greaterOrEqual"/>
+ <import plugin="org.eclipse.jsch.core"/>
+ <import plugin="com.jcraft.jsch"/>
+ </requires>
+
+ <plugin
+ id="org.eclipse.egit.core"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.egit.ui"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.egit"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.jgit"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+</feature>
diff --git a/org.eclipse.egit-feature/license.html b/org.eclipse.egit-feature/license.html
new file mode 100644
index 000000000..c6af966b6
--- /dev/null
+++ b/org.eclipse.egit-feature/license.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=iso-8859-1">
+<title>Eclipse.org Software User Agreement</title>
+</head>
+
+<body lang="EN-US" link=blue vlink=purple>
+<h2>Eclipse Foundation Software User Agreement</h2>
+<p>March 17, 2005</p>
+
+<h3>Usage Of Content</h3>
+
+<p>THE ECLIPSE FOUNDATION MAKES AVAILABLE SOFTWARE, DOCUMENTATION, INFORMATION AND/OR OTHER MATERIALS FOR OPEN SOURCE PROJECTS
+ (COLLECTIVELY &quot;CONTENT&quot;). USE OF THE CONTENT IS GOVERNED BY THE TERMS AND CONDITIONS OF THIS AGREEMENT AND/OR THE TERMS AND
+ CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE
+ OF THE CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR
+ NOTICES INDICATED OR REFERENCED BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT AND THE TERMS AND
+ CONDITIONS OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT USE THE CONTENT.</p>
+
+<h3>Applicable Licenses</h3>
+
+<p>Unless otherwise indicated, all Content made available by the Eclipse Foundation is provided to you under the terms and conditions of the Eclipse Public License Version 1.0
+ (&quot;EPL&quot;). A copy of the EPL is provided with this Content and is also available at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+ For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>Content includes, but is not limited to, source code, object code, documentation and other files maintained in the Eclipse.org CVS repository (&quot;Repository&quot;) in CVS
+ modules (&quot;Modules&quot;) and made available as downloadable archives (&quot;Downloads&quot;).</p>
+
+<ul>
+ <li>Content may be structured and packaged into modules to facilitate delivering, extending, and upgrading the Content. Typical modules may include plug-ins (&quot;Plug-ins&quot;), plug-in fragments (&quot;Fragments&quot;), and features (&quot;Features&quot;).</li>
+ <li>Each Plug-in or Fragment may be packaged as a sub-directory or JAR (Java&trade; ARchive) in a directory named &quot;plugins&quot;.</li>
+ <li>A Feature is a bundle of one or more Plug-ins and/or Fragments and associated material. Each Feature may be packaged as a sub-directory in a directory named &quot;features&quot;. Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of the Plug-ins
+ and/or Fragments associated with that Feature.</li>
+ <li>Features may also include other Features (&quot;Included Features&quot;). Within a Feature, files named &quot;feature.xml&quot; may contain a list of the names and version numbers of Included Features.</li>
+</ul>
+
+<p>The terms and conditions governing Plug-ins and Fragments should be contained in files named &quot;about.html&quot; (&quot;Abouts&quot;). The terms and conditions governing Features and
+Included Features should be contained in files named &quot;license.html&quot; (&quot;Feature Licenses&quot;). Abouts and Feature Licenses may be located in any directory of a Download or Module
+including, but not limited to the following locations:</p>
+
+<ul>
+ <li>The top-level (root) directory</li>
+ <li>Plug-in and Fragment directories</li>
+ <li>Inside Plug-ins and Fragments packaged as JARs</li>
+ <li>Sub-directories of the directory named &quot;src&quot; of certain Plug-ins</li>
+ <li>Feature directories</li>
+</ul>
+
+<p>Note: if a Feature made available by the Eclipse Foundation is installed using the Eclipse Update Manager, you must agree to a license (&quot;Feature Update License&quot;) during the
+installation process. If the Feature contains Included Features, the Feature Update License should either provide you with the terms and conditions governing the Included Features or
+inform you where you can locate them. Feature Update Licenses may be found in the &quot;license&quot; property of files named &quot;feature.properties&quot; found within a Feature.
+Such Abouts, Feature Licenses, and Feature Update Licenses contain the terms and conditions (or references to such terms and conditions) that govern your use of the associated Content in
+that directory.</p>
+
+<p>THE ABOUTS, FEATURE LICENSES, AND FEATURE UPDATE LICENSES MAY REFER TO THE EPL OR OTHER LICENSE AGREEMENTS, NOTICES OR TERMS AND CONDITIONS. SOME OF THESE
+OTHER LICENSE AGREEMENTS MAY INCLUDE (BUT ARE NOT LIMITED TO):</p>
+
+<ul>
+ <li>Common Public License Version 1.0 (available at <a href="http://www.eclipse.org/legal/cpl-v10.html">http://www.eclipse.org/legal/cpl-v10.html</a>)</li>
+ <li>Apache Software License 1.1 (available at <a href="http://www.apache.org/licenses/LICENSE">http://www.apache.org/licenses/LICENSE</a>)</li>
+ <li>Apache Software License 2.0 (available at <a href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>)</li>
+ <li>IBM Public License 1.0 (available at <a href="http://oss.software.ibm.com/developerworks/opensource/license10.html">http://oss.software.ibm.com/developerworks/opensource/license10.html</a>)</li>
+ <li>Metro Link Public License 1.00 (available at <a href="http://www.opengroup.org/openmotif/supporters/metrolink/license.html">http://www.opengroup.org/openmotif/supporters/metrolink/license.html</a>)</li>
+ <li>Mozilla Public License Version 1.1 (available at <a href="http://www.mozilla.org/MPL/MPL-1.1.html">http://www.mozilla.org/MPL/MPL-1.1.html</a>)</li>
+</ul>
+
+<p>IT IS YOUR OBLIGATION TO READ AND ACCEPT ALL SUCH TERMS AND CONDITIONS PRIOR TO USE OF THE CONTENT. If no About, Feature License, or Feature Update License is provided, please
+contact the Eclipse Foundation to determine what terms and conditions govern that particular Content.</p>
+
+<h3>Cryptography</h3>
+
+<p>Content may contain encryption software. The country in which you are currently may have restrictions on the import, possession, and use, and/or re-export to
+ another country, of encryption software. BEFORE using any encryption software, please check the country's laws, regulations and policies concerning the import,
+ possession, or use, and re-export of encryption software, to see if this is permitted.</p>
+
+<small>Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.</small>
+</body>
+</html>
diff --git a/org.eclipse.egit-updatesite/.project b/org.eclipse.egit-updatesite/.project
new file mode 100644
index 000000000..964220e70
--- /dev/null
+++ b/org.eclipse.egit-updatesite/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit-updatesite</name>
+ <comment></comment>
+ <projects>
+ <project>org.eclipse.egit</project>
+ <project>org.eclipse.egit.core</project>
+ <project>org.eclipse.egit.core.test</project>
+ <project>org.eclipse.egit.ui</project>
+ <project>org.eclipse.egit-feature</project>
+ <project>org.eclipse.jgit</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.UpdateSiteBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.UpdateSiteNature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.egit-updatesite/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit-updatesite/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..4ec836b53
--- /dev/null
+++ b/org.eclipse.egit-updatesite/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:46:54 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit-updatesite/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit-updatesite/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..fc5b578c1
--- /dev/null
+++ b/org.eclipse.egit-updatesite/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:55:44 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit-updatesite/index.html b/org.eclipse.egit-updatesite/index.html
new file mode 100644
index 000000000..3153645c6
--- /dev/null
+++ b/org.eclipse.egit-updatesite/index.html
@@ -0,0 +1,60 @@
+<html>
+<head>
+<title>org.eclipse.egit-updatesite</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<style>@import url("web/site.css");</style>
+<script type="text/javascript">
+ var returnval = 0;
+ var stylesheet, xmlFile, cache, doc;
+ function init(){
+ // NSCP 7.1+ / Mozilla 1.4.1+ / Safari
+ // Use the standard DOM Level 2 technique, if it is supported
+ if (document.implementation && document.implementation.createDocument) {
+ xmlFile = document.implementation.createDocument("", "", null);
+ stylesheet = document.implementation.createDocument("", "", null);
+ if (xmlFile.load){
+ xmlFile.load("site.xml");
+ stylesheet.load("web/site.xsl");
+ } else {
+ alert("Document could not be loaded by browser.");
+ }
+ xmlFile.addEventListener("load", transform, false);
+ stylesheet.addEventListener("load", transform, false);
+ }
+ //IE 6.0+ solution
+ else if (window.ActiveXObject) {
+ xmlFile = new ActiveXObject("msxml2.DOMDocument.3.0");
+ xmlFile.async = false;
+ xmlFile.load("site.xml");
+ stylesheet = new ActiveXObject("msxml2.FreeThreadedDOMDocument.3.0");
+ stylesheet.async = false;
+ stylesheet.load("web/site.xsl");
+ cache = new ActiveXObject("msxml2.XSLTemplate.3.0");
+ cache.stylesheet = stylesheet;
+ transformData();
+ }
+ }
+ // separate transformation function for IE 6.0+
+ function transformData(){
+ var processor = cache.createProcessor();
+ processor.input = xmlFile;
+ processor.transform();
+ data.innerHTML = processor.output;
+ }
+ // separate transformation function for NSCP 7.1+ and Mozilla 1.4.1+
+ function transform(){
+ returnval+=1;
+ if (returnval==2){
+ var processor = new XSLTProcessor();
+ processor.importStylesheet(stylesheet);
+ doc = processor.transformToDocument(xmlFile);
+ document.getElementById("data").innerHTML = doc.documentElement.innerHTML;
+ }
+ }
+</script>
+</head>
+<body onload="init();">
+<!--[insert static HTML here]-->
+<div id="data"><!-- this is where the transformed data goes --></div>
+</body>
+</html>
diff --git a/org.eclipse.egit-updatesite/site.xml b/org.eclipse.egit-updatesite/site.xml
new file mode 100644
index 000000000..4483f213a
--- /dev/null
+++ b/org.eclipse.egit-updatesite/site.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<site>
+ <description url="Eclipse Git Plugin">
+ This is a pure Java implementation of the Git version control system. The native Git version is also required in this version,
+ </description>
+ <feature url="features/org.eclipse.egit_0.5.0.qualifier.jar" id="org.eclipse.egit" version="0.5.0.qualifier" patch="true">
+ <category name="Eclipse Git Plugin (Incubation)"/>
+ </feature>
+ <category-def name="Eclipse Git Plugin (Incubation)" label="Eclipse Git Plugin (Incubation)">
+ <description>
+ Eclipse Git Plugin (Incubation)
+ </description>
+ </category-def>
+</site>
diff --git a/org.eclipse.egit-updatesite/web/site.css b/org.eclipse.egit-updatesite/web/site.css
new file mode 100644
index 000000000..62c6f9ffa
--- /dev/null
+++ b/org.eclipse.egit-updatesite/web/site.css
@@ -0,0 +1,12 @@
+<STYLE type="text/css">
+td.spacer {padding-bottom: 10px; padding-top: 10px;}
+.title { font-family: sans-serif; color: #99AACC;}
+.bodyText { font-family: sans-serif; font-size: 9pt; color:#000000; }
+.sub-header { font-family: sans-serif; font-style: normal; font-weight: bold; font-size: 9pt; color: white;}
+.log-text {font-family: sans-serif; font-style: normal; font-weight: lighter; font-size: 8pt; color:black;}
+.big-header { font-family: sans-serif; font-style: normal; font-weight: bold; font-size: 9pt; color: white; border-top:10px solid white;}
+.light-row {background:#FFFFFF}
+.dark-row {background:#EEEEFF}
+.header {background:#99AADD}
+#indent {word-wrap : break-word;width :300px;text-indent:10px;}
+</STYLE>
diff --git a/org.eclipse.egit-updatesite/web/site.xsl b/org.eclipse.egit-updatesite/web/site.xsl
new file mode 100644
index 000000000..0620b5c7b
--- /dev/null
+++ b/org.eclipse.egit-updatesite/web/site.xsl
@@ -0,0 +1,214 @@
+<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:msxsl="urn:schemas-microsoft-com:xslt">
+<xsl:output method="html" encoding="UTF-8"/>
+<xsl:key name="cat" match="category" use="@name"/>
+<xsl:template match="/">
+<xsl:for-each select="site">
+ <html>
+ <head>
+ <title>org.eclipse.egit-updatesite</title>
+ <style>@import url("web/site.css");</style>
+ </head>
+ <body>
+ <h1 class="title">org.eclipse.egit-updatesite</h1>
+ <p class="bodyText"><xsl:value-of select="description"/></p>
+ <table width="100%" border="0" cellspacing="1" cellpadding="2">
+ <xsl:for-each select="category-def">
+ <xsl:sort select="@label" order="ascending" case-order="upper-first"/>
+ <xsl:sort select="@name" order="ascending" case-order="upper-first"/>
+ <xsl:if test="count(key('cat',@name)) != 0">
+ <tr class="header">
+ <td class="sub-header" width="30%">
+ <xsl:value-of select="@name"/>
+ </td>
+ <td class="sub-header" width="70%">
+ <xsl:value-of select="@label"/>
+ </td>
+ </tr>
+ <xsl:for-each select="key('cat',@name)">
+ <xsl:sort select="ancestor::feature//@version" order="ascending"/>
+ <xsl:sort select="ancestor::feature//@id" order="ascending" case-order="upper-first"/>
+ <tr>
+ <xsl:choose>
+ <xsl:when test="(position() mod 2 = 1)">
+ <xsl:attribute name="class">dark-row</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="class">light-row</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <td class="log-text" id="indent">
+ <xsl:choose>
+ <xsl:when test="ancestor::feature//@label">
+ <a href="{ancestor::feature//@url}"><xsl:value-of select="ancestor::feature//@label"/></a>
+ <br/>
+ <div id="indent">
+ (<xsl:value-of select="ancestor::feature//@id"/> - <xsl:value-of select="ancestor::feature//@version"/>)
+ </div>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="{ancestor::feature//@url}"><xsl:value-of select="ancestor::feature//@id"/> - <xsl:value-of select="ancestor::feature//@version"/></a>
+ </xsl:otherwise>
+ </xsl:choose>
+ <br />
+ </td>
+ <td>
+ <table>
+ <xsl:if test="ancestor::feature//@os">
+ <tr><td class="log-text" id="indent">Operating Systems:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="ancestor::feature//@os"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="ancestor::feature//@ws">
+ <tr><td class="log-text" id="indent">Windows Systems:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="ancestor::feature//@ws"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="ancestor::feature//@nl">
+ <tr><td class="log-text" id="indent">Languages:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="ancestor::feature//@nl"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="ancestor::feature//@arch">
+ <tr><td class="log-text" id="indent">Architecture:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="ancestor::feature//@arch"/></td>
+ </tr>
+ </xsl:if>
+ </table>
+ </td>
+ </tr>
+ </xsl:for-each>
+ <tr><td class="spacer"><br/></td><td class="spacer"><br/></td></tr>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="count(feature) &gt; count(feature/category)">
+ <tr class="header">
+ <td class="sub-header" colspan="2">
+ Uncategorized
+ </td>
+ </tr>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="function-available('msxsl:node-set')">
+ <xsl:variable name="rtf-nodes">
+ <xsl:for-each select="feature[not(category)]">
+ <xsl:sort select="@id" order="ascending" case-order="upper-first"/>
+ <xsl:sort select="@version" order="ascending" />
+ <xsl:value-of select="."/>
+ <xsl:copy-of select="." />
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="myNodeSet" select="msxsl:node-set($rtf-nodes)/*"/>
+ <xsl:for-each select="$myNodeSet">
+ <tr>
+ <xsl:choose>
+ <xsl:when test="position() mod 2 = 1">
+ <xsl:attribute name="class">dark-row</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="class">light-row</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <td class="log-text" id="indent">
+ <xsl:choose>
+ <xsl:when test="@label">
+ <a href="{@url}"><xsl:value-of select="@label"/></a>
+ <br />
+ <div id="indent">
+ (<xsl:value-of select="@id"/> - <xsl:value-of select="@version"/>)
+ </div>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="{@url}"><xsl:value-of select="@id"/> - <xsl:value-of select="@version"/></a>
+ </xsl:otherwise>
+ </xsl:choose>
+ <br /><br />
+ </td>
+ <td>
+ <table>
+ <xsl:if test="@os">
+ <tr><td class="log-text" id="indent">Operating Systems:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="@os"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="@ws">
+ <tr><td class="log-text" id="indent">Windows Systems:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="@ws"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="@nl">
+ <tr><td class="log-text" id="indent">Languages:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="@nl"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="@arch">
+ <tr><td class="log-text" id="indent">Architecture:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="@arch"/></td>
+ </tr>
+ </xsl:if>
+ </table>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="feature[not(category)]">
+ <xsl:sort select="@id" order="ascending" case-order="upper-first"/>
+ <xsl:sort select="@version" order="ascending" />
+ <tr>
+ <xsl:choose>
+ <xsl:when test="count(preceding-sibling::feature[not(category)]) mod 2 = 1">
+ <xsl:attribute name="class">dark-row</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="class">light-row</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <td class="log-text" id="indent">
+ <xsl:choose>
+ <xsl:when test="@label">
+ <a href="{@url}"><xsl:value-of select="@label"/></a>
+ <br />
+ <div id="indent">
+ (<xsl:value-of select="@id"/> - <xsl:value-of select="@version"/>)
+ </div>
+ </xsl:when>
+ <xsl:otherwise>
+ <a href="{@url}"><xsl:value-of select="@id"/> - <xsl:value-of select="@version"/></a>
+ </xsl:otherwise>
+ </xsl:choose>
+ <br /><br />
+ </td>
+ <td>
+ <table>
+ <xsl:if test="@os">
+ <tr><td class="log-text" id="indent">Operating Systems:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="@os"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="@ws">
+ <tr><td class="log-text" id="indent">Windows Systems:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="@ws"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="@nl">
+ <tr><td class="log-text" id="indent">Languages:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="@nl"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="@arch">
+ <tr><td class="log-text" id="indent">Architecture:</td>
+ <td class="log-text" id="indent"><xsl:value-of select="@arch"/></td>
+ </tr>
+ </xsl:if>
+ </table>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </table>
+ </body>
+ </html>
+</xsl:for-each>
+</xsl:template>
+</xsl:stylesheet>
diff --git a/org.eclipse.egit.core.test/.classpath b/org.eclipse.egit.core.test/.classpath
new file mode 100644
index 000000000..304e86186
--- /dev/null
+++ b/org.eclipse.egit.core.test/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.egit.core.test/.gitignore b/org.eclipse.egit.core.test/.gitignore
new file mode 100644
index 000000000..5e56e040e
--- /dev/null
+++ b/org.eclipse.egit.core.test/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/org.eclipse.egit.core.test/.project b/org.eclipse.egit.core.test/.project
new file mode 100644
index 000000000..36089b8b0
--- /dev/null
+++ b/org.eclipse.egit.core.test/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit.core.test</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.egit.core.test/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit.core.test/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..84e44d8d3
--- /dev/null
+++ b/org.eclipse.egit.core.test/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:47:12 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit.core.test/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit.core.test/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..29b7c796c
--- /dev/null
+++ b/org.eclipse.egit.core.test/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:54:45 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit.core.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.egit.core.test/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..fb77da2f8
--- /dev/null
+++ b/org.eclipse.egit.core.test/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,320 @@
+#Sun Feb 03 03:52:00 CET 2008
+eclipse.preferences.version=1
+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.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=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=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+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.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=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=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
+org.eclipse.jdt.core.compiler.source=1.5
+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=1
+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_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=false
+org.eclipse.jdt.core.formatter.comment.format_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_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=80
+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=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_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.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=80
+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
diff --git a/org.eclipse.egit.core.test/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.egit.core.test/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..709a44074
--- /dev/null
+++ b/org.eclipse.egit.core.test/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,9 @@
+#Wed May 09 00:20:24 CEST 2007
+eclipse.preferences.version=1
+formatter_profile=_JGit
+formatter_settings_version=10
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
diff --git a/org.eclipse.egit.core.test/META-INF/MANIFEST.MF b/org.eclipse.egit.core.test/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..5548c87c7
--- /dev/null
+++ b/org.eclipse.egit.core.test/META-INF/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Test Plug-in (Incubation)
+Bundle-SymbolicName: org.eclipse.egit.core.test
+Bundle-Version: 0.5.0.qualifier
+Bundle-Activator: org.eclipse.egit.core.test.Activator
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.team.core,
+ org.junit,
+ org.eclipse.egit.core,
+ org.eclipse.egit.ui,
+ org.eclipse.jgit,
+ org.eclipse.core.filesystem
+Bundle-ActivationPolicy: lazy
+Import-Package: org.eclipse.core.resources,
+ org.eclipse.jdt.core,
+ org.eclipse.jdt.junit,
+ org.eclipse.jdt.launching
+Export-Package: org.eclipse.egit.core.internal.mapping
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/org.eclipse.egit.core.test/build.properties b/org.eclipse.egit.core.test/build.properties
new file mode 100644
index 000000000..34d2e4d2d
--- /dev/null
+++ b/org.eclipse.egit.core.test/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/org.eclipse.egit.core.test/org.eclipse.egit.core--All-Tests.launch b/org.eclipse.egit.core.test/org.eclipse.egit.core--All-Tests.launch
new file mode 100644
index 000000000..10b0eb760
--- /dev/null
+++ b/org.eclipse.egit.core.test/org.eclipse.egit.core--All-Tests.launch
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
+<booleanAttribute key="askclear" value="false"/>
+<booleanAttribute key="automaticAdd" value="true"/>
+<booleanAttribute key="automaticValidate" value="false"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="true"/>
+<booleanAttribute key="clearws" value="true"/>
+<booleanAttribute key="clearwslog" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
+<booleanAttribute key="default" value="true"/>
+<booleanAttribute key="includeOptional" value="true"/>
+<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.egit.core.test"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.egit.core.test"/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.egit.core.test"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useDefaultConfig" value="true"/>
+<booleanAttribute key="useDefaultConfigArea" value="false"/>
+<booleanAttribute key="useProduct" value="true"/>
+</launchConfiguration>
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/T0003_AdaptableFileTreeIteratorTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/T0003_AdaptableFileTreeIteratorTest.java
new file mode 100644
index 000000000..f7a501a1e
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/T0003_AdaptableFileTreeIteratorTest.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (C) 2009, Tor Arne Vestbø <torarnv@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.egit.core.AdaptableFileTreeIterator;
+import org.eclipse.egit.core.ContainerTreeIterator;
+import org.eclipse.egit.core.op.ConnectProviderOperation;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.egit.core.test.GitTestCase;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.WorkingTreeIterator;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+
+public class T0003_AdaptableFileTreeIteratorTest extends GitTestCase {
+
+ private Repository repository;
+
+ private File repositoryRoot;
+
+ private File file;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ repository = new Repository(gitDir);
+ repositoryRoot = repository.getWorkDir();
+ repository.create();
+
+ file = new File(project.getProject().getLocation().toFile(), "a.txt");
+ final FileWriter fileWriter = new FileWriter(file);
+ fileWriter.write("aaaaaaaaaaa");
+ fileWriter.close();
+
+ final ConnectProviderOperation operation = new ConnectProviderOperation(
+ project.getProject());
+ operation.run(null);
+ }
+
+ public void testFileTreeToContainerAdaptation() throws IOException {
+ final IWorkspaceRoot root = project.getProject().getWorkspace()
+ .getRoot();
+
+ final TreeWalk treeWalk = new TreeWalk(repository);
+ treeWalk.addTree(new AdaptableFileTreeIterator(repositoryRoot, root));
+ treeWalk.setRecursive(true);
+
+ final IFile eclipseFile = project.getProject().getFile(file.getName());
+ final RepositoryMapping mapping = RepositoryMapping
+ .getMapping(eclipseFile);
+ final Set<String> repositoryPaths = Collections.singleton(mapping
+ .getRepoRelativePath(eclipseFile));
+
+ assertTrue(repositoryPaths.size() == 1);
+ treeWalk.setFilter(PathFilterGroup.createFromStrings(repositoryPaths));
+
+ assertTrue(treeWalk.next());
+
+ final WorkingTreeIterator iterator = treeWalk.getTree(1,
+ WorkingTreeIterator.class);
+ assertTrue(iterator instanceof ContainerTreeIterator);
+ }
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/mapping/T0002_history.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/mapping/T0002_history.java
new file mode 100644
index 000000000..d2a6c937f
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/internal/mapping/T0002_history.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.mapping;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.egit.core.GitProvider;
+import org.eclipse.egit.core.op.ConnectProviderOperation;
+import org.eclipse.egit.core.test.GitTestCase;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.team.core.history.IFileHistory;
+import org.eclipse.team.core.history.IFileHistoryProvider;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.FileTreeEntry;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Tree;
+
+public class T0002_history extends GitTestCase {
+
+ protected static final PersonIdent jauthor;
+
+ protected static final PersonIdent jcommitter;
+
+ static {
+ jauthor = new PersonIdent("J. Author", "jauthor@example.com");
+ jcommitter = new PersonIdent("J. Committer", "jcommitter@example.com");
+ }
+
+ private File workDir;
+ private File gitDir;
+ private Repository thisGit;
+ private Tree tree;
+ private ObjectWriter objectWriter;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ project.createSourceFolder();
+ gitDir = new File(project.getProject().getWorkspace().getRoot()
+ .getRawLocation().toFile(), ".git");
+ thisGit = new Repository(gitDir);
+ workDir = thisGit.getWorkDir();
+ thisGit.create();
+ objectWriter = new ObjectWriter(thisGit);
+
+ tree = new Tree(thisGit);
+ Tree projectTree = tree.addTree("Project-1");
+ File project1_a_txt = createFile("Project-1/A.txt","A.txt - first version\n");
+ addFile(projectTree,project1_a_txt);
+ projectTree.setId(objectWriter.writeTree(projectTree));
+ File project1_b_txt = createFile("Project-1/B.txt","B.txt - first version\n");
+ addFile(projectTree,project1_b_txt);
+ projectTree.setId(objectWriter.writeTree(projectTree));
+ tree.setId(objectWriter.writeTree(tree));
+ Commit commit = new Commit(thisGit);
+ commit.setAuthor(new PersonIdent(jauthor, new Date(0L), TimeZone
+ .getTimeZone("GMT+1")));
+ commit.setCommitter(new PersonIdent(jcommitter, new Date(0L), TimeZone
+ .getTimeZone("GMT+1")));
+ commit.setMessage("Foo\n\nMessage");
+ commit.setTree(tree);
+ ObjectId commitId = objectWriter.writeCommit(commit);
+
+ tree = new Tree(thisGit);
+ projectTree = tree.addTree("Project-1");
+ addFile(projectTree,project1_a_txt);
+
+ File project1_b_v2_txt = createFile("Project-1/B.txt","B.txt - second version\n");
+ addFile(projectTree,project1_b_v2_txt);
+ projectTree.setId(objectWriter.writeTree(projectTree));
+ tree.setId(objectWriter.writeTree(tree));
+ commit = new Commit(thisGit);
+ commit.setAuthor(new PersonIdent(jauthor, new Date(0L), TimeZone
+ .getTimeZone("GMT+1")));
+ commit.setCommitter(new PersonIdent(jcommitter, new Date(0L), TimeZone
+ .getTimeZone("GMT+1")));
+ commit.setMessage("Modified");
+ commit.setParentIds(new ObjectId[] { commitId });
+ commit.setTree(tree);
+ commitId = objectWriter.writeCommit(commit);
+
+ RefUpdate lck = thisGit.updateRef("refs/heads/master");
+ assertNotNull("obtained lock", lck);
+ lck.setNewObjectId(commitId);
+ assertEquals(RefUpdate.Result.NEW, lck.forceUpdate());
+
+ ConnectProviderOperation operation = new ConnectProviderOperation(
+ project.getProject());
+ operation.run(null);
+ }
+
+ private void addFile(Tree t,File f) throws IOException {
+ ObjectId id = objectWriter.writeBlob(f);
+ t.addEntry(new FileTreeEntry(t,id,f.getName().getBytes("UTF-8"),false));
+ }
+
+ private File createFile(String name, String content) throws IOException {
+ File f = new File(workDir, name);
+ FileWriter fileWriter = new FileWriter(f);
+ fileWriter.write(content);
+ fileWriter.close();
+ return f;
+ }
+
+ public void testSingleRevision_1() {
+ GitProvider provider = (GitProvider)RepositoryProvider.getProvider(project.project);
+ assertNotNull(provider);
+ IFileHistoryProvider fileHistoryProvider = provider.getFileHistoryProvider();
+ IFileHistory fileHistory = fileHistoryProvider.getFileHistoryFor(project.getProject().getWorkspace().getRoot().findMember("Project-1/A.txt"), IFileHistoryProvider.SINGLE_LINE_OF_DESCENT, new NullProgressMonitor());
+ IFileRevision fileRevision = fileHistory.getFileRevision("60f0d7917fe2aed5c92b5bc35dfb55b9b8ada359");
+ assertEquals("60f0d7917fe2aed5c92b5bc35dfb55b9b8ada359", fileRevision.getContentIdentifier());
+ assertEquals("J. Author",fileRevision.getAuthor());
+
+ }
+
+ public void testSingleRevision_2() {
+ GitProvider provider = (GitProvider)RepositoryProvider.getProvider(project.project);
+ assertNotNull(provider);
+ IFileHistoryProvider fileHistoryProvider = provider.getFileHistoryProvider();
+ IFileHistory fileHistory = fileHistoryProvider.getFileHistoryFor(project.getProject().getWorkspace().getRoot().findMember("Project-1/A.txt"), IFileHistoryProvider.SINGLE_LINE_OF_DESCENT, new NullProgressMonitor());
+ IFileRevision fileRevision = fileHistory.getFileRevision("fd5a571c8a3a4a152e4c413d09d3ecb7d41e1e5f");
+ assertNull(fileRevision); // not matched by getFileHistoryFor
+ }
+
+ public void testSingleRevision_3() {
+ GitProvider provider = (GitProvider)RepositoryProvider.getProvider(project.project);
+ assertNotNull(provider);
+ IFileHistoryProvider fileHistoryProvider = provider.getFileHistoryProvider();
+ IFileHistory fileHistory = fileHistoryProvider.getFileHistoryFor(project.getProject().getWorkspace().getRoot().findMember("Project-1/B.txt"), IFileHistoryProvider.SINGLE_LINE_OF_DESCENT, new NullProgressMonitor());
+ IFileRevision fileRevision = fileHistory.getFileRevision("fd5a571c8a3a4a152e4c413d09d3ecb7d41e1e5f");
+ assertEquals("fd5a571c8a3a4a152e4c413d09d3ecb7d41e1e5f", fileRevision.getContentIdentifier());
+ assertEquals("J. Author",fileRevision.getAuthor());
+
+ }
+
+ public void testShallowHistory() {
+ GitProvider provider = (GitProvider)RepositoryProvider.getProvider(project.project);
+ assertNotNull(provider);
+ IFileHistoryProvider fileHistoryProvider = provider.getFileHistoryProvider();
+ IFileHistory fileHistory = fileHistoryProvider.getFileHistoryFor(project.getProject().getWorkspace().getRoot().findMember("Project-1/A.txt"), IFileHistoryProvider.SINGLE_LINE_OF_DESCENT, new NullProgressMonitor());
+ IFileRevision[] fileRevisions = fileHistory.getFileRevisions();
+ assertEquals(1, fileRevisions.length);
+ assertEquals("60f0d7917fe2aed5c92b5bc35dfb55b9b8ada359", fileRevisions[0].getContentIdentifier());
+ assertEquals("J. Author",fileRevisions[0].getAuthor());
+
+ }
+
+ public void testDeepHistory_A() {
+ GitProvider provider = (GitProvider)RepositoryProvider.getProvider(project.project);
+ assertNotNull(provider);
+ IFileHistoryProvider fileHistoryProvider = provider.getFileHistoryProvider();
+ IFileHistory fileHistory = fileHistoryProvider.getFileHistoryFor(project.getProject().getWorkspace().getRoot().findMember("Project-1/A.txt"), IFileHistoryProvider.NONE, new NullProgressMonitor());
+ IFileRevision[] fileRevisions = fileHistory.getFileRevisions();
+ assertEquals(1, fileRevisions.length);
+ assertEquals("60f0d7917fe2aed5c92b5bc35dfb55b9b8ada359", fileRevisions[0].getContentIdentifier());
+ assertEquals("J. Author",fileRevisions[0].getAuthor());
+
+ }
+
+ public void testDeepHistory_B() {
+ GitProvider provider = (GitProvider)RepositoryProvider.getProvider(project.project);
+ assertNotNull(provider);
+ IFileHistoryProvider fileHistoryProvider = provider.getFileHistoryProvider();
+ IFileHistory fileHistory = fileHistoryProvider.getFileHistoryFor(project.getProject().getWorkspace().getRoot().findMember("Project-1/B.txt"), IFileHistoryProvider.NONE, new NullProgressMonitor());
+ IFileRevision[] fileRevisions = fileHistory.getFileRevisions();
+ assertEquals(2, fileRevisions.length);
+ assertEquals("fd5a571c8a3a4a152e4c413d09d3ecb7d41e1e5f", fileRevisions[0].getContentIdentifier());
+ assertEquals("J. Author",fileRevisions[0].getAuthor());
+ assertEquals("60f0d7917fe2aed5c92b5bc35dfb55b9b8ada359", fileRevisions[1].getContentIdentifier());
+ assertEquals("J. Author",fileRevisions[0].getAuthor());
+
+ }
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/op/T0001_ConnectProviderOperationTest.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/op/T0001_ConnectProviderOperationTest.java
new file mode 100644
index 000000000..dc3969f43
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/op/T0001_ConnectProviderOperationTest.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.egit.core.op.ConnectProviderOperation;
+import org.eclipse.egit.core.test.GitTestCase;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.FileTreeEntry;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Tree;
+
+public class T0001_ConnectProviderOperationTest extends GitTestCase {
+
+ public void testNoRepository() throws CoreException {
+
+ ConnectProviderOperation operation = new ConnectProviderOperation(
+ project.getProject());
+ operation.run(null);
+
+ // We are shared because we declared as shared
+ assertTrue(RepositoryProvider.isShared(project.getProject()));
+ assertTrue(!gitDir.exists());
+ }
+
+ public void testNewRepository() throws CoreException, IOException {
+
+ File gitDir = new File(project.getProject().getWorkspace().getRoot()
+ .getRawLocation().toFile(), ".git");
+ Repository repository = new Repository(gitDir);
+ repository.create();
+ repository.close();
+ ConnectProviderOperation operation = new ConnectProviderOperation(
+ project.getProject());
+ operation.run(null);
+
+ assertTrue(RepositoryProvider.isShared(project.getProject()));
+
+ assertTrue(gitDir.exists());
+ }
+
+ public void testNewUnsharedFile() throws CoreException, IOException,
+ InterruptedException {
+
+ project.createSourceFolder();
+ IFile fileA = project.getProject().getFolder("src").getFile("A.java");
+ String srcA = "class A {\n" + "}\n";
+ fileA.create(new ByteArrayInputStream(srcA.getBytes()), false, null);
+
+ File gitDir = new File(project.getProject().getWorkspace().getRoot()
+ .getRawLocation().toFile(), ".git");
+ Repository thisGit = new Repository(gitDir);
+ thisGit.create();
+ Tree rootTree = new Tree(thisGit);
+ Tree prjTree = rootTree.addTree(project.getProject().getName());
+ Tree srcTree = prjTree.addTree("src");
+ FileTreeEntry entryA = srcTree.addFile("A.java");
+ ObjectWriter writer = new ObjectWriter(thisGit);
+ entryA.setId(writer.writeBlob(fileA.getRawLocation().toFile()));
+ srcTree.setId(writer.writeTree(srcTree));
+ prjTree.setId(writer.writeTree(prjTree));
+ rootTree.setId(writer.writeTree(rootTree));
+ Commit commit = new Commit(thisGit);
+ commit.setTree(rootTree);
+ commit.setAuthor(new PersonIdent("J. Git", "j.git@egit.org", new Date(
+ 60876075600000L), TimeZone.getTimeZone("GMT+1")));
+ commit.setCommitter(commit.getAuthor());
+ commit.setMessage("testNewUnsharedFile\n\nJunit tests\n");
+ ObjectId id = writer.writeCommit(commit);
+ RefUpdate lck = thisGit.updateRef("refs/heads/master");
+ assertNotNull("obtained lock", lck);
+ lck.setNewObjectId(id);
+ assertEquals(RefUpdate.Result.NEW, lck.forceUpdate());
+
+ ConnectProviderOperation operation = new ConnectProviderOperation(
+ project.getProject());
+ operation.run(null);
+
+ final boolean f[] = new boolean[1];
+ new Job("wait") {
+ protected IStatus run(IProgressMonitor monitor) {
+
+ System.out.println("MyJob");
+ f[0] = true;
+ return null;
+ }
+
+ {
+ setRule(project.getProject());
+ schedule();
+ }
+ };
+ while (!f[0]) {
+ System.out.println("Waiting");
+ Thread.sleep(1000);
+ }
+ System.out.println("DONE");
+
+ assertNotNull(RepositoryProvider.getProvider(project.getProject()));
+
+ }
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/Activator.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/Activator.java
new file mode 100644
index 000000000..e49d527bd
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/Activator.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.test;
+
+import org.eclipse.core.runtime.Plugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends Plugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.egit.core.test";
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ // Empty
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugins#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.core.runtime.Plugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitTestCase.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitTestCase.java
new file mode 100644
index 000000000..cbe89c3c4
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/GitTestCase.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.test;
+
+import java.io.File;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+public abstract class GitTestCase extends TestCase {
+
+ protected TestProject project;
+
+ protected File gitDir;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ project = new TestProject();
+ gitDir = new File(project.getProject().getWorkspace().getRoot()
+ .getRawLocation().toFile(), ".git");
+ rmrf(gitDir);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ project.dispose();
+ rmrf(gitDir);
+ }
+
+ private void rmrf(File d) throws IOException {
+ if (!d.exists())
+ return;
+
+ File[] files = d.listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; ++i) {
+ if (files[i].isDirectory())
+ rmrf(files[i]);
+ else if (!files[i].delete())
+ throw new IOException(files[i] + " in use or undeletable");
+ }
+ }
+ if (!d.delete())
+ throw new IOException(d + " in use or undeletable");
+ assert !d.exists();
+ }
+
+}
diff --git a/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestProject.java b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestProject.java
new file mode 100644
index 000000000..b9ea08708
--- /dev/null
+++ b/org.eclipse.egit.core.test/src/org/eclipse/egit/core/test/TestProject.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.test;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IPluginDescriptor;
+import org.eclipse.core.runtime.IPluginRegistry;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.launching.JavaRuntime;
+
+public class TestProject {
+ public IProject project;
+
+ public IJavaProject javaProject;
+
+ private IPackageFragmentRoot sourceFolder;
+
+ public TestProject() throws CoreException {
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ project = root.getProject("Project-1");
+ project.create(null);
+ project.open(null);
+ javaProject = JavaCore.create(project);
+ IFolder binFolder = createBinFolder();
+ setJavaNature();
+ javaProject.setRawClasspath(new IClasspathEntry[0], null);
+ createOutputFolder(binFolder);
+ addSystemLibraries();
+ }
+
+ public IProject getProject() {
+ return project;
+ }
+
+ public IJavaProject getJavaProject() {
+ return javaProject;
+ }
+
+ public void addJar(String plugin, String jar) throws MalformedURLException,
+ IOException, JavaModelException {
+ Path result = findFileInPlugin(plugin, jar);
+ IClasspathEntry[] oldEntries = javaProject.getRawClasspath();
+ IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1];
+ System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length);
+ newEntries[oldEntries.length] = JavaCore.newLibraryEntry(result, null,
+ null);
+ javaProject.setRawClasspath(newEntries, null);
+ }
+
+ public IPackageFragment createPackage(String name) throws CoreException {
+ if (sourceFolder == null)
+ sourceFolder = createSourceFolder();
+ return sourceFolder.createPackageFragment(name, false, null);
+ }
+
+ public IType createType(IPackageFragment pack, String cuName, String source)
+ throws JavaModelException {
+ StringBuffer buf = new StringBuffer();
+ buf.append("package " + pack.getElementName() + ";\n");
+ buf.append("\n");
+ buf.append(source);
+ ICompilationUnit cu = pack.createCompilationUnit(cuName,
+ buf.toString(), false, null);
+ return cu.getTypes()[0];
+ }
+
+ public void dispose() throws CoreException {
+ waitForIndexer();
+ project.delete(true, true, null);
+ }
+
+ private IFolder createBinFolder() throws CoreException {
+ IFolder binFolder = project.getFolder("bin");
+ binFolder.create(false, true, null);
+ return binFolder;
+ }
+
+ private void setJavaNature() throws CoreException {
+ IProjectDescription description = project.getDescription();
+ description.setNatureIds(new String[] { JavaCore.NATURE_ID });
+ project.setDescription(description, null);
+ }
+
+ private void createOutputFolder(IFolder binFolder)
+ throws JavaModelException {
+ IPath outputLocation = binFolder.getFullPath();
+ javaProject.setOutputLocation(outputLocation, null);
+ }
+
+ public IPackageFragmentRoot createSourceFolder() throws CoreException {
+ IFolder folder = project.getFolder("src");
+ folder.create(false, true, null);
+ IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(folder);
+ IClasspathEntry[] oldEntries = javaProject.getRawClasspath();
+ IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1];
+ System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length);
+ newEntries[oldEntries.length] = JavaCore.newSourceEntry(root.getPath());
+ javaProject.setRawClasspath(newEntries, null);
+ return root;
+ }
+
+ private void addSystemLibraries() throws JavaModelException {
+ IClasspathEntry[] oldEntries = javaProject.getRawClasspath();
+ IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1];
+ System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length);
+ newEntries[oldEntries.length] = JavaRuntime
+ .getDefaultJREContainerEntry();
+ javaProject.setRawClasspath(newEntries, null);
+ }
+
+ private Path findFileInPlugin(String plugin, String file)
+ throws MalformedURLException, IOException {
+ IPluginRegistry registry = Platform.getPluginRegistry();
+ IPluginDescriptor descriptor = registry.getPluginDescriptor(plugin);
+ URL pluginURL = descriptor.getInstallURL();
+ URL jarURL = new URL(pluginURL, file);
+ URL localJarURL = Platform.asLocalURL(jarURL);
+ return new Path(localJarURL.getPath());
+ }
+
+ public void waitForIndexer() {
+ // new SearchEngine().searchAllTypeNames(ResourcesPlugin.getWorkspace(),
+ // null, null, IJavaSearchConstants.EXACT_MATCH,
+ // IJavaSearchConstants.CASE_SENSITIVE,
+ // IJavaSearchConstants.CLASS, SearchEngine
+ // .createJavaSearchScope(new IJavaElement[0]),
+ // new ITypeNameRequestor() {
+ // public void acceptClass(char[] packageName,
+ // char[] simpleTypeName, char[][] enclosingTypeNames,
+ // String path) {
+ // }
+ // public void acceptInterface(char[] packageName,
+ // char[] simpleTypeName, char[][] enclosingTypeNames,
+ // String path) {
+ // }
+ // }, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null);
+ }
+
+ /**
+ * @return Returns the sourceFolder.
+ */
+ public IPackageFragmentRoot getSourceFolder() {
+ return sourceFolder;
+ }
+
+ /**
+ * @param sourceFolder The sourceFolder to set.
+ */
+ public void setSourceFolder(IPackageFragmentRoot sourceFolder) {
+ this.sourceFolder = sourceFolder;
+ }
+}
diff --git a/org.eclipse.egit.core/.classpath b/org.eclipse.egit.core/.classpath
new file mode 100644
index 000000000..304e86186
--- /dev/null
+++ b/org.eclipse.egit.core/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.egit.core/.gitignore b/org.eclipse.egit.core/.gitignore
new file mode 100644
index 000000000..ba077a403
--- /dev/null
+++ b/org.eclipse.egit.core/.gitignore
@@ -0,0 +1 @@
+bin
diff --git a/org.eclipse.egit.core/.options b/org.eclipse.egit.core/.options
new file mode 100644
index 000000000..ef2dc6104
--- /dev/null
+++ b/org.eclipse.egit.core/.options
@@ -0,0 +1 @@
+org.eclipse.egit.core/trace/verbose = false
diff --git a/org.eclipse.egit.core/.project b/org.eclipse.egit.core/.project
new file mode 100644
index 000000000..e937b1cf4
--- /dev/null
+++ b/org.eclipse.egit.core/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit.core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.egit.core/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit.core/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..d4ff695e8
--- /dev/null
+++ b/org.eclipse.egit.core/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:47:03 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit.core/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit.core/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..b6db226b2
--- /dev/null
+++ b/org.eclipse.egit.core/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:54:53 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit.core/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.egit.core/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..f94f9a80d
--- /dev/null
+++ b/org.eclipse.egit.core/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,320 @@
+#Sun Feb 03 18:48:30 CET 2008
+eclipse.preferences.version=1
+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.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=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=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+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.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=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=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error
+org.eclipse.jdt.core.compiler.source=1.5
+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=1
+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_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=false
+org.eclipse.jdt.core.formatter.comment.format_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_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=80
+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=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_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.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=80
+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
diff --git a/org.eclipse.egit.core/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.egit.core/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..709a44074
--- /dev/null
+++ b/org.eclipse.egit.core/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,9 @@
+#Wed May 09 00:20:24 CEST 2007
+eclipse.preferences.version=1
+formatter_profile=_JGit
+formatter_settings_version=10
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
diff --git a/org.eclipse.egit.core/META-INF/MANIFEST.MF b/org.eclipse.egit.core/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..b290075f6
--- /dev/null
+++ b/org.eclipse.egit.core/META-INF/MANIFEST.MF
@@ -0,0 +1,21 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %plugin_name
+Bundle-SymbolicName: org.eclipse.egit.core;singleton:=true
+Bundle-Version: 0.5.0.qualifier
+Bundle-Activator: org.eclipse.egit.core.Activator
+Bundle-Vendor: %provider_name
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.team.core,
+ org.eclipse.core.resources,
+ org.eclipse.jgit,
+ org.eclipse.core.filesystem,
+ org.eclipse.ui
+Export-Package: org.eclipse.egit.core,
+ org.eclipse.egit.core.internal.storage;x-friends:="org.eclipse.egit.ui",
+ org.eclipse.egit.core.internal.util;x-friends:="org.eclipse.egit.ui",
+ org.eclipse.egit.core.op,
+ org.eclipse.egit.core.project
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/org.eclipse.egit.core/build.properties b/org.eclipse.egit.core/build.properties
new file mode 100644
index 000000000..59c50b7cd
--- /dev/null
+++ b/org.eclipse.egit.core/build.properties
@@ -0,0 +1,7 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ .options,\
+ plugin.properties
diff --git a/org.eclipse.egit.core/plugin.properties b/org.eclipse.egit.core/plugin.properties
new file mode 100644
index 000000000..9b61e82fe
--- /dev/null
+++ b/org.eclipse.egit.core/plugin.properties
@@ -0,0 +1,10 @@
+###############################################################################
+# Copyright (c) 2005, 2009 Shawn Pearce and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+###############################################################################
+plugin_name=Git Team Provider (Core) (Incubation)
+provider_name=eclipse.org
diff --git a/org.eclipse.egit.core/plugin.xml b/org.eclipse.egit.core/plugin.xml
new file mode 100644
index 000000000..9b9b1f71a
--- /dev/null
+++ b/org.eclipse.egit.core/plugin.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension point="org.eclipse.core.runtime.preferences">
+ <initializer class="org.eclipse.egit.core.GitCorePreferenceInitializer"/>
+ </extension>
+
+ <extension point="org.eclipse.team.core.repository">
+ <repository
+ class="org.eclipse.egit.core.GitProvider"
+ id="org.eclipse.egit.core.GitProvider">
+ </repository>
+ </extension>
+ <extension
+ point="org.eclipse.team.core.ignore">
+ <ignore
+ enabled="true"
+ pattern=".git"/>
+ </extension>
+</plugin>
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/Activator.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/Activator.java
new file mode 100644
index 000000000..86f38978f
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/Activator.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.egit.core.project.GitProjectData;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The plugin class for the org.eclipse.egit.core plugin. This
+ * is a singleton class.
+ */
+public class Activator extends AbstractUIPlugin {
+ private static Activator plugin;
+
+ /**
+ * @return the singleton {@link Activator}
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * @return the name of this plugin
+ */
+ public static String getPluginId() {
+ return getDefault().getBundle().getSymbolicName();
+ }
+
+ /**
+ * Utility method to help throwing errors in the Egit plugin. This method
+ * does not actually throw the exception, but just creates an instance.
+ *
+ * @param message User comprehensible message
+ * @param thr cause
+ * @return an Initialized {@link CoreException}
+ */
+ public static CoreException error(final String message, final Throwable thr) {
+ return new CoreException(new Status(IStatus.ERROR, getPluginId(), 0,
+ message, thr));
+ }
+
+ /**
+ * Utility method to log errors in the Egit plugin.
+ * @param message User comprehensible message
+ * @param thr The exception through which we noticed the error
+ */
+ public static void logError(final String message, final Throwable thr) {
+ getDefault().getLog().log(
+ new Status(IStatus.ERROR, getPluginId(), 0, message, thr));
+ }
+
+ private static boolean isOptionSet(final String optionId) {
+ final String option = getPluginId() + optionId;
+ final String value = Platform.getDebugOption(option);
+ return value != null && value.equals("true");
+ }
+
+ /**
+ * Utility method for debug logging.
+ *
+ * @param what
+ */
+ public static void trace(final String what) {
+ if (getDefault().traceVerbose) {
+ System.out.println("[" + getPluginId() + "] " + what);
+ }
+ }
+
+ private boolean traceVerbose;
+
+ /**
+ * Construct the {@link Activator} singleton instance
+ */
+ public Activator() {
+ plugin = this;
+ }
+
+ public void start(final BundleContext context) throws Exception {
+ super.start(context);
+ traceVerbose = isOptionSet("/trace/verbose");
+ GitProjectData.reconfigureWindowCache();
+ GitProjectData.attachToWorkspace(true);
+ }
+
+ public void stop(final BundleContext context) throws Exception {
+ GitProjectData.detachFromWorkspace();
+ super.stop(context);
+ plugin = null;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/AdaptableFileTreeIterator.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/AdaptableFileTreeIterator.java
new file mode 100644
index 000000000..3fbab868a
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/AdaptableFileTreeIterator.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (C) 2009, Tor Arne Vestbø <torarnv@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.treewalk.AbstractTreeIterator;
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+
+/**
+ * Java IO file tree iterator that can adapt to a {@link ContainerTreeIterator}
+ * <p>
+ * The iterator automatically adapts to a {@link ContainerTreeIterator} when
+ * recursing into directories that are accessible from the given workspace root.
+ *
+ * @see org.eclipse.jgit.treewalk.FileTreeIterator
+ * @see org.eclipse.egit.core.ContainerTreeIterator
+ */
+public class AdaptableFileTreeIterator extends FileTreeIterator {
+
+ IWorkspaceRoot root;
+
+ /**
+ * Create a new iterator to traverse the given directory and its children
+ * <p>
+ * The iterator will automatically adapt to a {@link ContainerTreeIterator}
+ * when encountering directories what can be mapped into the given workspace
+ * root.
+ *
+ * @param path
+ * the starting directory. This directory should correspond to
+ * the repository root.
+ * @param workspaceRoot
+ * the workspace root to check resource mapping against.
+ *
+ */
+ public AdaptableFileTreeIterator(final File path,
+ final IWorkspaceRoot workspaceRoot) {
+ super(path);
+ root = workspaceRoot;
+ }
+
+ /**
+ * Create a new iterator to traverse a subdirectory.
+ * <p>
+ * The iterator will automatically adapt to a {@link ContainerTreeIterator}
+ * when encountering directories what can be mapped into the given workspace
+ * root.
+ *
+ * @param path
+ * the subdirectory. This should be a directory contained within
+ * the parent directory.
+ * @param parent
+ * the parent iterator we were created from.
+ * @param workspaceRoot
+ * the workspace root to check resource mapping against.
+ */
+ protected AdaptableFileTreeIterator(final AdaptableFileTreeIterator parent,
+ File path, final IWorkspaceRoot workspaceRoot) {
+ super(parent, path);
+ root = workspaceRoot;
+ }
+
+ @Override
+ public AbstractTreeIterator createSubtreeIterator(Repository repo)
+ throws IncorrectObjectTypeException, IOException {
+ final File currentFile = ((FileEntry) current()).getFile();
+ final IContainer[] containers = root.findContainersForLocation(new Path(
+ currentFile.getAbsolutePath()));
+ if (containers.length > 0)
+ return new ContainerTreeIterator(this, containers[0]);
+ else
+ return new AdaptableFileTreeIterator(this, currentFile, root);
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java
new file mode 100644
index 000000000..4bec94fbf
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/ContainerTreeIterator.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.treewalk.AbstractTreeIterator;
+import org.eclipse.jgit.treewalk.WorkingTreeIterator;
+import org.eclipse.jgit.util.FS;
+
+/**
+ * Adapts an Eclipse {@link IContainer} for use in a <code>TreeWalk</code>.
+ * <p>
+ * This iterator converts an Eclipse IContainer object into something that a
+ * TreeWalk instance can iterate over in parallel with any other Git tree data
+ * structure, such as another working directory tree from outside of the
+ * workspace or a stored tree from a Repository object database.
+ * <p>
+ * Modification times provided by this iterator are obtained from the cache
+ * Eclipse uses to track external resource modification. This can be faster, but
+ * requires the user refresh their workspace when external modifications take
+ * place. This is not really a concern as it is common practice to need to do a
+ * workspace refresh after externally modifying a file.
+ *
+ * @see org.eclipse.jgit.treewalk.TreeWalk
+ */
+public class ContainerTreeIterator extends WorkingTreeIterator {
+ private static String computePrefix(final IContainer base) {
+ final RepositoryMapping rm = RepositoryMapping.getMapping(base);
+ if (rm == null)
+ throw new IllegalArgumentException("Not in a Git project: " + base);
+ return rm.getRepoRelativePath(base);
+ }
+
+ private final IContainer node;
+
+ /**
+ * Construct a new iterator from a container in the workspace.
+ * <p>
+ * The iterator will support traversal over the named container, but only if
+ * it is contained within a project which has the Git repository provider
+ * connected and this resource is mapped into a Git repository. During the
+ * iteration the paths will be automatically generated to match the proper
+ * repository paths for this container's children.
+ *
+ * @param base
+ * the part of the workspace the iterator will walk over.
+ */
+ public ContainerTreeIterator(final IContainer base) {
+ super(computePrefix(base));
+ node = base;
+ init(entries());
+ }
+
+ /**
+ * Construct a new iterator from the workspace root.
+ * <p>
+ * The iterator will support traversal over workspace projects that have
+ * a Git repository provider connected and is mapped into a Git repository.
+ * During the iteration the paths will be automatically generated to match
+ * the proper repository paths for this container's children.
+ *
+ * @param root
+ * the workspace root to walk over.
+ */
+ public ContainerTreeIterator(final IWorkspaceRoot root) {
+ super("");
+ node = root;
+ init(entries());
+ }
+
+ /**
+ * Construct a new iterator from a container in the workspace, with a given
+ * parent iterator.
+ * <p>
+ * The iterator will support traversal over the named container, but only if
+ * it is contained within a project which has the Git repository provider
+ * connected and this resource is mapped into a Git repository. During the
+ * iteration the paths will be automatically generated to match the proper
+ * repository paths for this container's children.
+ *
+ * @param p
+ * the parent iterator we were created from.
+ * @param base
+ * the part of the workspace the iterator will walk over.
+ */
+ public ContainerTreeIterator(final WorkingTreeIterator p,
+ final IContainer base) {
+ super(p);
+ node = base;
+ init(entries());
+ }
+
+ @Override
+ public AbstractTreeIterator createSubtreeIterator(final Repository db)
+ throws IncorrectObjectTypeException, IOException {
+ if (FileMode.TREE.equals(mode))
+ return new ContainerTreeIterator(this,
+ (IContainer) ((ResourceEntry) current()).rsrc);
+ else
+ throw new IncorrectObjectTypeException(ObjectId.zeroId(),
+ Constants.TYPE_TREE);
+ }
+
+ /**
+ * Get the ResourceEntry for the current entry.
+ *
+ * @return the current entry
+ */
+ public ResourceEntry getResourceEntry() {
+ return (ResourceEntry) current();
+ }
+
+ private Entry[] entries() {
+ final IResource[] all;
+ try {
+ all = node.members(IContainer.INCLUDE_HIDDEN);
+ } catch (CoreException err) {
+ return EOF;
+ }
+
+ final Entry[] r = new Entry[all.length];
+ for (int i = 0; i < r.length; i++)
+ r[i] = new ResourceEntry(all[i]);
+ return r;
+ }
+
+ /**
+ * Wrapper for a resource in the Eclipse workspace
+ */
+ static public class ResourceEntry extends Entry {
+ final IResource rsrc;
+
+ private final FileMode mode;
+
+ private long length = -1;
+
+ ResourceEntry(final IResource f) {
+ rsrc = f;
+
+ switch (f.getType()) {
+ case IResource.FILE:
+ if (FS.INSTANCE.canExecute(asFile()))
+ mode = FileMode.EXECUTABLE_FILE;
+ else
+ mode = FileMode.REGULAR_FILE;
+ break;
+ case IResource.PROJECT:
+ case IResource.FOLDER: {
+ final IContainer c = (IContainer) f;
+ if (c.findMember(".git") != null)
+ mode = FileMode.GITLINK;
+ else
+ mode = FileMode.TREE;
+ break;
+ }
+ default:
+ mode = FileMode.MISSING;
+ break;
+ }
+ }
+
+ @Override
+ public FileMode getMode() {
+ return mode;
+ }
+
+ @Override
+ public String getName() {
+ if (rsrc.getType() == IResource.PROJECT)
+ return rsrc.getLocation().lastSegment();
+ else
+ return rsrc.getName();
+ }
+
+ @Override
+ public long getLength() {
+ if (length < 0) {
+ if (rsrc instanceof IFile)
+ length = asFile().length();
+ else
+ length = 0;
+ }
+ return length;
+ }
+
+ @Override
+ public long getLastModified() {
+ return rsrc.getLocalTimeStamp();
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ if (rsrc instanceof IFile) {
+ try {
+ return ((IFile) rsrc).getContents(true);
+ } catch (CoreException err) {
+ final IOException ioe = new IOException(err.getMessage());
+ ioe.initCause(err);
+ throw ioe;
+ }
+ }
+ throw new IOException("Not a regular file: " + rsrc);
+ }
+
+ /**
+ * Get the underlying resource of this entry.
+ *
+ * @return the underlying resource
+ */
+ public IResource getResource() {
+ return rsrc;
+ }
+
+ private File asFile() {
+ return ((IFile) rsrc).getLocation().toFile();
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java
new file mode 100644
index 000000000..6e82b9b57
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/CoreText.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Possibly Translated strings for the Egit plugin.
+ */
+public class CoreText extends NLS {
+
+ /** */
+ public static String AssumeUnchangedOperation_adding;
+
+ /** */
+ public static String UpdateOperation_updating;
+
+ /** */
+ public static String UpdateOperation_failed;
+
+ /** */
+ public static String ConnectProviderOperation_connecting;
+
+ /** */
+ public static String ConnectProviderOperation_ConnectingProject;
+
+ /** */
+ public static String DisconnectProviderOperation_disconnecting;
+
+ /** */
+ public static String AddOperation_adding;
+
+ /** */
+ public static String AddOperation_failed;
+
+ /** */
+ public static String UntrackOperation_adding;
+
+ /** */
+ public static String UntrackOperation_failed;
+
+ /** */
+ public static String GitProjectData_lazyResolveFailed;
+
+ /** */
+ public static String GitProjectData_mappedResourceGone;
+
+ /** */
+ public static String GitProjectData_cannotReadHEAD;
+
+ /** */
+ public static String GitProjectData_missing;
+
+ /** */
+ public static String GitProjectData_saveFailed;
+
+ /** */
+ public static String GitProjectData_notifyChangedFailed;
+
+ /** */
+ public static String RepositoryFinder_finding;
+
+ /** */
+ public static String MoveDeleteHook_cannotModifyFolder;
+
+ /** */
+ public static String MoveDeleteHook_operationError;
+
+ /** */
+ public static String Error_CanonicalFile;
+
+ /** */
+ public static String CloneOperation_title;
+
+ /** */
+ public static String ListRemoteOperation_title;
+
+ /** */
+ public static String PushOperation_resultCancelled;
+
+ /** */
+ public static String PushOperation_resultNotSupported;
+
+ /** */
+ public static String PushOperation_resultTransportError;
+
+ /** */
+ public static String PushOperation_resultNoServiceError;
+
+ /** */
+ public static String PushOperation_taskNameDryRun;
+
+ /** */
+ public static String PushOperation_taskNameNormalRun;
+
+ static {
+ initializeMessages("org.eclipse.egit.core.coretext", CoreText.class);
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/EclipseGitProgressTransformer.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/EclipseGitProgressTransformer.java
new file mode 100644
index 000000000..94f3edcca
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/EclipseGitProgressTransformer.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jgit.lib.ProgressMonitor;
+
+/** Create a new Git to Eclipse progress monitor. */
+public class EclipseGitProgressTransformer implements ProgressMonitor {
+ private final IProgressMonitor root;
+
+ private IProgressMonitor task;
+
+ private String msg;
+
+ private int lastWorked;
+
+ private int totalWork;
+
+ /**
+ * Create a new progress monitor.
+ *
+ * @param eclipseMonitor
+ * the Eclipse monitor we update.
+ */
+ public EclipseGitProgressTransformer(final IProgressMonitor eclipseMonitor) {
+ root = eclipseMonitor;
+ }
+
+ public void start(final int totalTasks) {
+ root.beginTask("", totalTasks * 1000);
+ }
+
+ public void beginTask(final String name, final int total) {
+ endTask();
+ msg = name;
+ lastWorked = 0;
+ totalWork = total;
+ task = new SubProgressMonitor(root, 1000);
+ if (totalWork == UNKNOWN)
+ task.beginTask("", IProgressMonitor.UNKNOWN);
+ else
+ task.beginTask("", totalWork);
+ task.subTask(msg);
+ }
+
+ public void update(final int work) {
+ if (task == null)
+ return;
+
+ final int cmp = lastWorked + work;
+ if (lastWorked == UNKNOWN && cmp > 0) {
+ task.subTask(msg + ", " + cmp);
+ } else if (totalWork <= 0) {
+ // Do nothing to update the task.
+ } else if (cmp * 100 / totalWork != lastWorked * 100 / totalWork) {
+ final StringBuilder m = new StringBuilder();
+ m.append(msg);
+ m.append(": ");
+ while (m.length() < 25)
+ m.append(' ');
+
+ if (totalWork == UNKNOWN) {
+ m.append(cmp);
+ } else {
+ final String twstr = String.valueOf(totalWork);
+ String cmpstr = String.valueOf(cmp);
+ while (cmpstr.length() < twstr.length())
+ cmpstr = " " + cmpstr;
+ final int pcnt = (cmp * 100 / totalWork);
+ if (pcnt < 100)
+ m.append(' ');
+ if (pcnt < 10)
+ m.append(' ');
+ m.append(pcnt);
+ m.append("% (");
+ m.append(cmpstr);
+ m.append("/");
+ m.append(twstr);
+ m.append(")");
+ }
+ task.subTask(m.toString());
+ }
+ lastWorked = cmp;
+ task.worked(work);
+ }
+
+ public void endTask() {
+ if (task != null) {
+ try {
+ task.done();
+ } finally {
+ task = null;
+ }
+ }
+ }
+
+ public boolean isCancelled() {
+ if (task != null)
+ return task.isCanceled();
+ return root.isCanceled();
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/GitCorePreferenceInitializer.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitCorePreferenceInitializer.java
new file mode 100644
index 000000000..6435a953e
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitCorePreferenceInitializer.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+
+/** Initializes plugin preferences with default values. */
+public class GitCorePreferenceInitializer extends AbstractPreferenceInitializer {
+ private static final int MB = 1024 * 1024;
+
+ public void initializeDefaultPreferences() {
+ final Preferences p = Activator.getDefault().getPluginPreferences();
+
+ p.setDefault(GitCorePreferences.core_packedGitWindowSize, 8 * 1024);
+ p.setDefault(GitCorePreferences.core_packedGitLimit, 10 * MB);
+ p.setDefault(GitCorePreferences.core_packedGitMMAP, false);
+ p.setDefault(GitCorePreferences.core_deltaBaseCacheLimit, 10 * MB);
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/GitCorePreferences.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitCorePreferences.java
new file mode 100644
index 000000000..20238862e
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitCorePreferences.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+/** Preferences used by the core plugin. */
+public class GitCorePreferences {
+ /** */
+ public static final String core_packedGitWindowSize = "core_packedGitWindowSize";
+ /** */
+ public static final String core_packedGitLimit = "core_packedGitLimit";
+ /** */
+ public static final String core_packedGitMMAP = "core_packedGitMMAP";
+ /** */
+ public static final String core_deltaBaseCacheLimit = "core_deltaBaseCacheLimit";
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/GitMoveDeleteHook.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitMoveDeleteHook.java
new file mode 100644
index 000000000..7fd82c961
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitMoveDeleteHook.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+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.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.team.IMoveDeleteHook;
+import org.eclipse.core.resources.team.IResourceTree;
+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.egit.core.project.GitProjectData;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheBuilder;
+import org.eclipse.jgit.dircache.DirCacheEditor;
+import org.eclipse.jgit.dircache.DirCacheEntry;
+
+class GitMoveDeleteHook implements IMoveDeleteHook {
+ private static final boolean I_AM_DONE = true;
+
+ private static final boolean FINISH_FOR_ME = false;
+
+ private final GitProjectData data;
+
+ GitMoveDeleteHook(final GitProjectData d) {
+ Assert.isNotNull(d);
+ data = d;
+ }
+
+ public boolean deleteFile(final IResourceTree tree, final IFile file,
+ final int updateFlags, final IProgressMonitor monitor) {
+ final boolean force = (updateFlags & IResource.FORCE) == IResource.FORCE;
+ if (!force && !tree.isSynchronized(file, IResource.DEPTH_ZERO))
+ return false;
+
+ final RepositoryMapping map = RepositoryMapping.getMapping(file);
+ if (map == null)
+ return false;
+
+ try {
+ final DirCache dirc = DirCache.lock(map.getRepository());
+ final int first = dirc.findEntry(map.getRepoRelativePath(file));
+ if (first < 0) {
+ dirc.unlock();
+ return false;
+ }
+
+ final DirCacheBuilder edit = dirc.builder();
+ if (first > 0)
+ edit.keep(0, first);
+ final int next = dirc.nextEntry(first);
+ if (next < dirc.getEntryCount())
+ edit.keep(next, dirc.getEntryCount() - next);
+ if (!edit.commit())
+ tree.failed(new Status(IStatus.ERROR, Activator.getPluginId(),
+ 0, CoreText.MoveDeleteHook_operationError, null));
+ tree.standardDeleteFile(file, updateFlags, monitor);
+ } catch (IOException e) {
+ tree.failed(new Status(IStatus.ERROR, Activator.getPluginId(), 0,
+ CoreText.MoveDeleteHook_operationError, e));
+ }
+ return true;
+ }
+
+ public boolean deleteFolder(final IResourceTree tree, final IFolder folder,
+ final int updateFlags, final IProgressMonitor monitor) {
+ // Deleting a GIT repository which is in use is a pretty bad idea. To
+ // delete disconnect the team provider first.
+ //
+ if (data.isProtected(folder)) {
+ return cannotModifyRepository(tree);
+ } else {
+ return FINISH_FOR_ME;
+ }
+ }
+
+ public boolean deleteProject(final IResourceTree tree,
+ final IProject project, final int updateFlags,
+ final IProgressMonitor monitor) {
+ // TODO: Note that eclipse thinks folders are real, while
+ // Git does not care.
+ return FINISH_FOR_ME;
+ }
+
+ public boolean moveFile(final IResourceTree tree, final IFile srcf,
+ final IFile dstf, final int updateFlags,
+ final IProgressMonitor monitor) {
+ final boolean force = (updateFlags & IResource.FORCE) == IResource.FORCE;
+ if (!force && !tree.isSynchronized(srcf, IResource.DEPTH_ZERO))
+ return false;
+
+ final RepositoryMapping srcm = RepositoryMapping.getMapping(srcf);
+ if (srcm == null)
+ return false;
+ final RepositoryMapping dstm = RepositoryMapping.getMapping(dstf);
+
+ try {
+ final DirCache sCache = DirCache.lock(srcm.getRepository());
+ final String sPath = srcm.getRepoRelativePath(srcf);
+ final DirCacheEntry sEnt = sCache.getEntry(sPath);
+ if (sEnt == null) {
+ sCache.unlock();
+ return false;
+ }
+
+ final DirCacheEditor sEdit = sCache.editor();
+ sEdit.add(new DirCacheEditor.DeletePath(sEnt));
+ if (dstm != null && dstm.getRepository() == srcm.getRepository()) {
+ final String dPath = srcm.getRepoRelativePath(dstf);
+ sEdit.add(new DirCacheEditor.PathEdit(dPath) {
+ @Override
+ public void apply(final DirCacheEntry dEnt) {
+ dEnt.copyMetaData(sEnt);
+ }
+ });
+ }
+ if (!sEdit.commit())
+ tree.failed(new Status(IStatus.ERROR, Activator.getPluginId(),
+ 0, CoreText.MoveDeleteHook_operationError, null));
+
+ tree.standardMoveFile(srcf, dstf, updateFlags, monitor);
+ } catch (IOException e) {
+ tree.failed(new Status(IStatus.ERROR, Activator.getPluginId(), 0,
+ CoreText.MoveDeleteHook_operationError, e));
+ }
+ return true;
+ }
+
+ public boolean moveFolder(final IResourceTree tree, final IFolder srcf,
+ final IFolder dstf, final int updateFlags,
+ final IProgressMonitor monitor) {
+ final boolean force = (updateFlags & IResource.FORCE) == IResource.FORCE;
+ if (!force && !tree.isSynchronized(srcf, IResource.DEPTH_ZERO))
+ return false;
+
+ final RepositoryMapping srcm = RepositoryMapping.getMapping(srcf);
+ if (srcm == null)
+ return false;
+ final RepositoryMapping dstm = RepositoryMapping.getMapping(dstf);
+
+ try {
+ final DirCache sCache = DirCache.lock(srcm.getRepository());
+ final String sPath = srcm.getRepoRelativePath(srcf);
+ final DirCacheEntry[] sEnt = sCache.getEntriesWithin(sPath);
+ if (sEnt.length == 0) {
+ sCache.unlock();
+ return false;
+ }
+
+ final DirCacheEditor sEdit = sCache.editor();
+ sEdit.add(new DirCacheEditor.DeleteTree(sPath));
+ if (dstm != null && dstm.getRepository() == srcm.getRepository()) {
+ final String dPath = srcm.getRepoRelativePath(dstf) + "/";
+ final int sPathLen = sPath.length() + 1;
+ for (final DirCacheEntry se : sEnt) {
+ final String p = se.getPathString().substring(sPathLen);
+ sEdit.add(new DirCacheEditor.PathEdit(dPath + p) {
+ @Override
+ public void apply(final DirCacheEntry dEnt) {
+ dEnt.copyMetaData(se);
+ }
+ });
+ }
+ }
+ if (!sEdit.commit())
+ tree.failed(new Status(IStatus.ERROR, Activator.getPluginId(),
+ 0, CoreText.MoveDeleteHook_operationError, null));
+
+ tree.standardMoveFolder(srcf, dstf, updateFlags, monitor);
+ } catch (IOException e) {
+ tree.failed(new Status(IStatus.ERROR, Activator.getPluginId(), 0,
+ CoreText.MoveDeleteHook_operationError, e));
+ }
+ return true;
+ }
+
+ public boolean moveProject(final IResourceTree tree, final IProject source,
+ final IProjectDescription description, final int updateFlags,
+ final IProgressMonitor monitor) {
+ // TODO: We should be able to do this without too much effort when the
+ // projects belong to the same Git repository.
+ return FINISH_FOR_ME;
+ }
+
+ private boolean cannotModifyRepository(final IResourceTree tree) {
+ tree.failed(new Status(IStatus.ERROR, Activator.getPluginId(), 0,
+ CoreText.MoveDeleteHook_cannotModifyFolder, null));
+ return I_AM_DONE;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/GitProvider.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitProvider.java
new file mode 100644
index 000000000..d646c15f4
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitProvider.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import org.eclipse.core.resources.IResourceRuleFactory;
+import org.eclipse.core.resources.team.IMoveDeleteHook;
+import org.eclipse.core.resources.team.ResourceRuleFactory;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.egit.core.internal.storage.GitFileHistoryProvider;
+import org.eclipse.egit.core.project.GitProjectData;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.team.core.history.IFileHistoryProvider;
+
+/**
+ * The Team provider class for a Git repository.
+ */
+public class GitProvider extends RepositoryProvider {
+ private GitProjectData data;
+
+ private GitMoveDeleteHook hook;
+
+ private GitFileHistoryProvider historyProvider;
+
+ private final IResourceRuleFactory resourceRuleFactory = new GitResourceRuleFactory();
+
+ public String getID() {
+ return getClass().getName();
+ }
+
+ public void configureProject() throws CoreException {
+ getData().markTeamPrivateResources();
+ }
+
+ public void deconfigure() throws CoreException {
+ GitProjectData.delete(getProject());
+ }
+
+ public boolean canHandleLinkedResources() {
+ return true;
+ }
+
+ @Override
+ public boolean canHandleLinkedResourceURI() {
+ return true;
+ }
+
+ public synchronized IMoveDeleteHook getMoveDeleteHook() {
+ if (hook == null) {
+ GitProjectData _data = getData();
+ if (_data != null)
+ hook = new GitMoveDeleteHook(_data);
+ }
+ return hook;
+ }
+
+ /**
+ * @return information about the mapping of an Eclipse project
+ * to a Git repository.
+ */
+ public synchronized GitProjectData getData() {
+ if (data == null) {
+ data = GitProjectData.get(getProject());
+ }
+ return data;
+ }
+
+ public synchronized IFileHistoryProvider getFileHistoryProvider() {
+ if (historyProvider == null) {
+ historyProvider = new GitFileHistoryProvider();
+ }
+ return historyProvider;
+ }
+
+ @Override
+ public IResourceRuleFactory getRuleFactory() {
+ return resourceRuleFactory;
+ }
+
+ private static class GitResourceRuleFactory extends ResourceRuleFactory {
+ // Use the default rule factory instead of the
+ // pessimistic one by default.
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/GitTag.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitTag.java
new file mode 100644
index 000000000..42581a35a
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/GitTag.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import org.eclipse.team.core.history.ITag;
+
+/**
+ * A representation of a Git tag in Eclipse.
+ */
+public class GitTag implements ITag {
+
+ private String name;
+
+ /**
+ * Construct a GitTag object with a given name.
+ *
+ * @param name the Git tag name
+ */
+ public GitTag(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/ResourceList.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/ResourceList.java
new file mode 100644
index 000000000..c475a0c1d
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/ResourceList.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+
+/** A list of IResource, adaptable to the first item. */
+public class ResourceList implements IAdaptable {
+ private final IResource[] list;
+
+ /**
+ * Create a new list of resources.
+ *
+ * @param items
+ * the items to contain in this list.
+ */
+ public ResourceList(final IResource[] items) {
+ list = items;
+ }
+
+ /**
+ * Get the items stored in this list.
+ *
+ * @return the list provided to our constructor.
+ */
+ public IResource[] getItems() {
+ return list;
+ }
+
+ public Object getAdapter(final Class adapter) {
+ if (adapter == IResource.class && list != null && list.length > 0)
+ return list[0];
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties
new file mode 100644
index 000000000..9b7ed82ba
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/coretext.properties
@@ -0,0 +1,51 @@
+###############################################################################
+# Copyright (c) 2006, 2009 Shawn Pearce and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+###############################################################################
+
+ConnectProviderOperation_connecting=Connecting Git team provider.
+ConnectProviderOperation_ConnectingProject=Connecting project {0}
+
+DisconnectProviderOperation_disconnecting=Disconnecting Git team provider.
+
+UpdateOperation_updating=Updating index
+UpdateOperation_failed=Failed to update index
+
+AddOperation_adding=Adding resources.
+AddOperation_failed=Failed to add resource.
+
+AssumeUnchangedOperation_adding=Marking resources unchanged
+UntrackOperation_adding=Untracking (removing) resources.
+UntrackOperation_failed=Failed to untrack resource.
+
+GitProjectData_mappedResourceGone=A mapped resource no longer exists in Eclipse.
+GitProjectData_cannotReadHEAD=Current tree for `HEAD` cannot be obtained.
+GitProjectData_missing=Git team provider configuration has gone missing.
+GitProjectData_saveFailed=Saving Git team provider data to {0} failed.
+GitProjectData_notifyChangedFailed=Resource change notification failed.
+GitProjectData_lazyResolveFailed=Unable to load a referenced tree.
+
+RepositoryFinder_finding=Searching for associated repositories.
+
+MoveDeleteHook_cannotModifyFolder=Folder contains an active Git repository.\n\
+The folder cannot be moved, renamed or deleted until the team provider is disconnected.
+
+MoveDeleteHook_operationError=Error updating cache during move/delete.\n\
+The resource cannot be moved, renamed or deleted due to an internal error.
+
+Error_CanonicalFile=Unable to determine a canonical file path.
+
+CloneOperation_title=Cloning from {0}
+
+ListRemoteOperation_title=Getting remote branches information
+
+PushOperation_resultCancelled=Operation was cancelled.
+PushOperation_resultNotSupported=Can't push to {0}
+PushOperation_resultTransportError=Transport error occured during push operation: {0}
+PushOperation_resultNoServiceError=Push service is not available: {0}
+PushOperation_taskNameDryRun=Trying pushing to remote repositories
+PushOperation_taskNameNormalRun=Pushing to remote repositories
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/UpdateJob.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/UpdateJob.java
new file mode 100644
index 000000000..de07e118b
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/UpdateJob.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceProxy;
+import org.eclipse.core.resources.IResourceProxyVisitor;
+import org.eclipse.core.resources.IResourceVisitor;
+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.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jgit.errors.NotSupportedException;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.GitIndex.Entry;
+
+/**
+ * This job updates the index with the content of all specified
+ * and tracked resources. If a project is selected all tracked
+ * resources withing that container are updated.
+ */
+public class UpdateJob extends Job {
+
+ private final Collection rsrcList;
+
+ /**
+ * Construct an UpdateJob for the specified resources.
+ *
+ * @param rsrcList
+ */
+ public UpdateJob(Collection rsrcList) {
+ super("Update index");
+ this.rsrcList = rsrcList;
+ setPriority(Job.LONG);
+ }
+
+ protected IStatus run(IProgressMonitor m) {
+ if (m == null) {
+ m = new NullProgressMonitor();
+ }
+
+ trace("running");
+ try {
+ final IdentityHashMap<RepositoryMapping, Boolean> tomerge = new IdentityHashMap<RepositoryMapping, Boolean>();
+ try {
+ final int[] count=new int[1];
+ long t0=System.currentTimeMillis();
+ for (Object obj : rsrcList) {
+ obj = ((IAdaptable)obj).getAdapter(IResource.class);
+ if (obj instanceof IContainer) {
+ ((IContainer)obj).accept(new IResourceProxyVisitor() {
+ public boolean visit(IResourceProxy rp) throws CoreException {
+ if (rp.getType() == IResource.FILE) {
+ count[0]++;
+ }
+ return true;
+ }
+ }, IContainer.EXCLUDE_DERIVED);
+ } else if (obj instanceof IResource) {
+ count[0]++;
+ }
+ }
+ long t1=System.currentTimeMillis();
+ System.out.println("Counted "+count[0]+" items to update in "+(t1-t0)/1000.0+"s");
+ m.beginTask(CoreText.UpdateOperation_updating, count[0]);
+ final IProgressMonitor fm = m;
+ for (Object obj : rsrcList) {
+ if (obj instanceof IResource) {
+ final IResource r = (IResource)obj;
+ final RepositoryMapping rm = RepositoryMapping.getMapping(r);
+ final GitIndex index = rm.getRepository().getIndex();
+ tomerge.put(rm, Boolean.TRUE);
+ if (r instanceof IContainer) {
+ ((IContainer)r).accept(new IResourceVisitor() {
+ public boolean visit(IResource resource) throws CoreException {
+ try {
+ if (resource.getType() == IResource.FILE) {
+ String path = rm.getRepoRelativePath(resource);
+ Entry entry = index.getEntry(path);
+ if (entry != null) {
+ entry.update(new File(rm.getWorkDir(),path));
+ }
+ fm.worked(1);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw Activator.error(CoreText.UpdateOperation_failed, e);
+ }
+ return true;
+ }
+ },IResource.DEPTH_INFINITE, IContainer.EXCLUDE_DERIVED);
+ } else {
+ String path = rm.getRepoRelativePath(r);
+ Entry entry = index.getEntry(path);
+ if (entry != null) {
+ entry.update(new File(rm.getWorkDir(),path));
+ }
+ m.worked(1);
+ }
+ }
+ }
+ for (RepositoryMapping rm : tomerge.keySet()) {
+ m.setTaskName("Writing index for "+rm.getRepository().getDirectory());
+ rm.getRepository().getIndex().write();
+ }
+ } catch (NotSupportedException e) {
+ return Activator.error(e.getMessage(),e).getStatus();
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ return Activator.error(CoreText.UpdateOperation_failed, e).getStatus();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return Activator.error(CoreText.UpdateOperation_failed, e).getStatus();
+ } catch (CoreException e) {
+ e.printStackTrace();
+ return Activator.error(CoreText.UpdateOperation_failed, e).getStatus();
+ } finally {
+ try {
+ final Iterator i = tomerge.keySet().iterator();
+ while (i.hasNext()) {
+ final RepositoryMapping r = (RepositoryMapping) i.next();
+ r.getRepository().getIndex().read();
+ r.fireRepositoryChanged();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ m.done();
+ }
+ }
+ } finally {
+ trace("done");
+ m.done();
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ private void trace(final String m) {
+ Activator.trace("(UpdateJob)"+m);
+ }
+
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/BlobStorage.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/BlobStorage.java
new file mode 100644
index 000000000..05aa0edf6
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/BlobStorage.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.core.internal.resources.ResourceException;
+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 org.eclipse.core.runtime.Path;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.Repository;
+
+/** Accesses a blob from Git. */
+class BlobStorage implements IStorage {
+ private final Repository db;
+
+ private final String path;
+
+ private final ObjectId blobId;
+
+ BlobStorage(final Repository repository, final String fileName,
+ final ObjectId blob) {
+ db = repository;
+ path = fileName;
+ blobId = blob;
+ }
+
+ public InputStream getContents() throws CoreException {
+ try {
+ return open();
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL,
+ getFullPath(), "IO error reading Git blob " + blobId + ".",
+ e);
+ }
+ }
+
+ private InputStream open() throws IOException, ResourceException,
+ IncorrectObjectTypeException {
+ final ObjectLoader reader = db.openBlob(blobId);
+ if (reader == null)
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL,
+ getFullPath(), "Git blob " + blobId + " not found.", null);
+ final byte[] data = reader.getBytes();
+ if (reader.getType() != Constants.OBJ_BLOB)
+ throw new IncorrectObjectTypeException(blobId, Constants.TYPE_BLOB);
+ return new ByteArrayInputStream(data);
+ }
+
+ public IPath getFullPath() {
+ return Path.fromPortableString(path);
+ }
+
+ public String getName() {
+ final int last = path.lastIndexOf('/');
+ return last >= 0 ? path.substring(last + 1) : path;
+ }
+
+ public boolean isReadOnly() {
+ return true;
+ }
+
+ public Object getAdapter(final Class adapter) {
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/CommitFileRevision.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/CommitFileRevision.java
new file mode 100644
index 000000000..2771e889b
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/CommitFileRevision.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import org.eclipse.core.internal.resources.ResourceException;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.egit.core.GitTag;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.core.history.ITag;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.treewalk.TreeWalk;
+
+/**
+ * An {@link IFileRevision} for a version of a specified resource in the
+ * specified commit (revision).
+ */
+class CommitFileRevision extends GitFileRevision {
+ private final Repository db;
+
+ private final RevCommit commit;
+
+ private final PersonIdent author;
+
+ private final String path;
+
+ private ObjectId blobId;
+
+ CommitFileRevision(final Repository repo, final RevCommit rc,
+ final String fileName) {
+ this(repo, rc, fileName, null);
+ }
+
+ CommitFileRevision(final Repository repo, final RevCommit rc,
+ final String fileName, final ObjectId blob) {
+ super(fileName);
+ db = repo;
+ commit = rc;
+ author = rc.getAuthorIdent();
+ path = fileName;
+ blobId = blob;
+ }
+
+ String getGitPath() {
+ return path;
+ }
+
+ public IStorage getStorage(final IProgressMonitor monitor)
+ throws CoreException {
+ if (blobId == null)
+ blobId = locateBlobObjectId();
+ return new BlobStorage(db, path, blobId);
+ }
+
+ public long getTimestamp() {
+ return author != null ? author.getWhen().getTime() : 0;
+ }
+
+ public String getContentIdentifier() {
+ return commit.getId().name();
+ }
+
+ public String getAuthor() {
+ return author != null ? author.getName() : null;
+ }
+
+ public String getComment() {
+ return commit.getShortMessage();
+ }
+
+ public String toString() {
+ return commit.getId() + ":" + path;
+ }
+
+ public ITag[] getTags() {
+ final Collection<GitTag> ret = new ArrayList<GitTag>();
+ for (final Map.Entry<String, Ref> tag : db.getTags().entrySet()) {
+ final ObjectId ref = tag.getValue().getPeeledObjectId();
+ if (ref == null)
+ continue;
+ if (!AnyObjectId.equals(ref, commit))
+ continue;
+ ret.add(new GitTag(tag.getKey()));
+ }
+ return ret.toArray(new ITag[ret.size()]);
+ }
+
+ /**
+ * Get the commit that introduced this file revision.
+ *
+ * @return the commit we most recently noticed this file in.
+ */
+ public RevCommit getRevCommit() {
+ return commit;
+ }
+
+ private ObjectId locateBlobObjectId() throws CoreException {
+ try {
+ final TreeWalk w = TreeWalk.forPath(db, path, commit.getTree());
+ if (w == null)
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL,
+ Path.fromPortableString(path), "Path not in "
+ + commit.getId() + ".", null);
+ return w.getObjectId(0);
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, Path
+ .fromPortableString(path), "IO error looking up path in "
+ + commit.getId() + ".", e);
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistory.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistory.java
new file mode 100644
index 000000000..377b6abcd
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistory.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.team.core.history.IFileHistoryProvider;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.core.history.provider.FileHistory;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+/**
+ * A list of revisions for a specific resource according to some filtering
+ * criterion. Though git really does not do file tracking, this corresponds to
+ * listing all files with the same path.
+ */
+class GitFileHistory extends FileHistory implements IAdaptable {
+ private static final int SINGLE_REVISION = IFileHistoryProvider.SINGLE_REVISION;
+
+ private static final IFileRevision[] NO_REVISIONS = {};
+
+ private static final int BATCH_SIZE = 256;
+
+ private final IResource resource;
+
+ private String gitPath;
+
+ private final KidWalk walk;
+
+ private final IFileRevision[] revisions;
+
+ GitFileHistory(final IResource rsrc, final int flags,
+ final IProgressMonitor monitor) {
+ resource = rsrc;
+ walk = buildWalk();
+ revisions = buildRevisions(monitor, flags);
+ }
+
+ private KidWalk buildWalk() {
+ final RepositoryMapping rm = RepositoryMapping.getMapping(resource);
+ if (rm == null) {
+ Activator.logError("Git not attached to project "
+ + resource.getProject().getName() + ".", null);
+ return null;
+ }
+
+ final KidWalk w = new KidWalk(rm.getRepository());
+ gitPath = rm.getRepoRelativePath(resource);
+ w.setTreeFilter(AndTreeFilter.create(PathFilterGroup
+ .createFromStrings(Collections.singleton(gitPath)),
+ TreeFilter.ANY_DIFF));
+ return w;
+ }
+
+ private IFileRevision[] buildRevisions(final IProgressMonitor monitor,
+ final int flags) {
+ if (walk == null)
+ return NO_REVISIONS;
+
+ final Repository db = walk.getRepository();
+ final RevCommit root;
+ try {
+ final AnyObjectId headId = db.resolve(Constants.HEAD);
+ if (headId == null) {
+ Activator.logError("No HEAD revision available from Git"
+ + " for project " + resource.getProject().getName()
+ + ".", null);
+ return NO_REVISIONS;
+ }
+
+ root = walk.parseCommit(headId);
+ if ((flags & SINGLE_REVISION) == SINGLE_REVISION) {
+ // If all Eclipse wants is one revision it probably is
+ // for the editor "quick diff" feature. We can pass off
+ // just the repository HEAD, even though it may not be
+ // the revision that most recently modified the path.
+ //
+ final CommitFileRevision single;
+ single = new CommitFileRevision(db, root, gitPath);
+ return new IFileRevision[] { single };
+ }
+
+ walk.markStart(root);
+ } catch (IOException e) {
+ Activator.logError("Invalid HEAD revision for project "
+ + resource.getProject().getName() + ".", e);
+ return NO_REVISIONS;
+ }
+
+ final KidCommitList list = new KidCommitList();
+ list.source(walk);
+ try {
+ for (;;) {
+ final int oldsz = list.size();
+ list.fillTo(oldsz + BATCH_SIZE - 1);
+ if (oldsz == list.size())
+ break;
+ if (monitor != null && monitor.isCanceled())
+ break;
+ }
+ } catch (IOException e) {
+ Activator.logError("Error parsing history for "
+ + resource.getFullPath() + ".", e);
+ return NO_REVISIONS;
+ }
+
+ final IFileRevision[] r = new IFileRevision[list.size()];
+ for (int i = 0; i < r.length; i++)
+ r[i] = new CommitFileRevision(db, list.get(i), gitPath);
+ return r;
+ }
+
+ public IFileRevision[] getContributors(final IFileRevision ifr) {
+ if (!(ifr instanceof CommitFileRevision))
+ return NO_REVISIONS;
+
+ final CommitFileRevision rev = (CommitFileRevision) ifr;
+ final Repository db = walk.getRepository();
+ final String p = rev.getGitPath();
+ final RevCommit c = rev.getRevCommit();
+ final IFileRevision[] r = new IFileRevision[c.getParentCount()];
+ for (int i = 0; i < r.length; i++)
+ r[i] = new CommitFileRevision(db, c.getParent(i), p);
+ return r;
+ }
+
+ public IFileRevision[] getTargets(final IFileRevision ifr) {
+ if (!(ifr instanceof CommitFileRevision))
+ return NO_REVISIONS;
+
+ final CommitFileRevision rev = (CommitFileRevision) ifr;
+ final Repository db = walk.getRepository();
+ final String p = rev.getGitPath();
+ final RevCommit rc = rev.getRevCommit();
+ if (!(rc instanceof KidCommit))
+ return NO_REVISIONS;
+
+ final KidCommit c = (KidCommit) rc;
+ final IFileRevision[] r = new IFileRevision[c.children.length];
+ for (int i = 0; i < r.length; i++)
+ r[i] = new CommitFileRevision(db, c.children[i], p);
+ return r;
+ }
+
+ public IFileRevision getFileRevision(final String id) {
+ if (id == null || id.equals("") || GitFileRevision.WORKSPACE.equals(id))
+ return new WorkspaceFileRevision(resource);
+ if (GitFileRevision.INDEX.equals(id))
+ return new IndexFileRevision(walk.getRepository(), gitPath);
+
+ // Only return a revision if it was matched by this filtered history
+ for (IFileRevision r : revisions) {
+ if (r.getContentIdentifier().equals(id))
+ return r;
+ }
+ return null;
+ }
+
+ public IFileRevision[] getFileRevisions() {
+ final IFileRevision[] r = new IFileRevision[revisions.length];
+ System.arraycopy(revisions, 0, r, 0, r.length);
+ return r;
+ }
+
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistoryProvider.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistoryProvider.java
new file mode 100644
index 000000000..b85800d95
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileHistoryProvider.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.history.IFileHistory;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.core.history.provider.FileHistoryProvider;
+
+/**
+ * A {@link FileHistoryProvider} for Git. This class has methods for retrieving
+ * specific versions of a tracked resource.
+ */
+public class GitFileHistoryProvider extends FileHistoryProvider {
+ public IFileHistory getFileHistoryFor(IResource resource, int flags,
+ IProgressMonitor monitor) {
+ return new GitFileHistory(resource, flags, monitor);
+ }
+
+ public IFileRevision getWorkspaceFileRevision(IResource resource) {
+ return new WorkspaceFileRevision(resource);
+ }
+
+ public IFileHistory getFileHistoryFor(IFileStore store, int flags,
+ IProgressMonitor monitor) {
+ // TODO: implement getFileHistoryFor(IFileStore ...)
+ return null;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileRevision.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileRevision.java
new file mode 100644
index 000000000..d9066573d
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/GitFileRevision.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.core.history.provider.FileRevision;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+/**
+ * A Git related {@link IFileRevision}. It references a version and a resource,
+ * i.e. the version we think corresponds to the resource in specific version.
+ */
+public abstract class GitFileRevision extends FileRevision {
+ /** Content identifier for the working copy. */
+ public static final String WORKSPACE = "Workspace";
+
+ /** Content identifier for the content staged in the index. */
+ public static final String INDEX = "Index";
+
+ /**
+ * Obtain a file revision for a specific blob of an existing commit.
+ *
+ * @param db
+ * the repository this commit was loaded out of, and that this
+ * file's blob should also be reachable through.
+ * @param commit
+ * the commit the blob was identified to be within.
+ * @param path
+ * path within the commit's tree of the file.
+ * @param blobId
+ * unique name of the content.
+ * @return revision implementation for this file in the given commit.
+ */
+ public static GitFileRevision inCommit(final Repository db,
+ final RevCommit commit, final String path, final ObjectId blobId) {
+ return new CommitFileRevision(db, commit, path, blobId);
+ }
+
+ /**
+ * @param db
+ * the repository which contains the index to use.
+ * @param path
+ * path of the resource in the index
+ * @return revision implementation for the given path in the index
+ */
+ public static GitFileRevision inIndex(final Repository db, final String path) {
+ return new IndexFileRevision(db, path);
+ }
+
+ private final String path;
+
+ GitFileRevision(final String fileName) {
+ path = fileName;
+ }
+
+ public String getName() {
+ final int last = path.lastIndexOf('/');
+ return last >= 0 ? path.substring(last + 1) : path;
+ }
+
+ public boolean isPropertyMissing() {
+ return false;
+ }
+
+ public IFileRevision withAllProperties(final IProgressMonitor monitor)
+ throws CoreException {
+ return this;
+ }
+
+ public URI getURI() {
+ try {
+ return new URI(null, null, path, null);
+ } catch (URISyntaxException e) {
+ return null;
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/IndexFileRevision.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/IndexFileRevision.java
new file mode 100644
index 000000000..8cf81c9ec
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/IndexFileRevision.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import java.io.IOException;
+
+import org.eclipse.core.internal.resources.ResourceException;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.IStorage;
+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.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.GitIndex.Entry;
+
+/** An {@link IFileRevision} for the version in the Git index. */
+class IndexFileRevision extends GitFileRevision implements IFileRevision {
+ private final Repository db;
+
+ private final String path;
+
+ private ObjectId blobId;
+
+ IndexFileRevision(final Repository repo, final String fileName) {
+ super(fileName);
+ db = repo;
+ path = fileName;
+ }
+
+ public IStorage getStorage(IProgressMonitor monitor) throws CoreException {
+ if (blobId == null)
+ blobId = locateBlobObjectId();
+ return new BlobStorage(db, path, blobId);
+ }
+
+ public boolean isPropertyMissing() {
+ return false;
+ }
+
+ public IFileRevision withAllProperties(IProgressMonitor monitor)
+ throws CoreException {
+ return null;
+ }
+
+ public String getAuthor() {
+ return "";
+ }
+
+ public long getTimestamp() {
+ return -1;
+ }
+
+ public String getComment() {
+ return null;
+ }
+
+ public String getContentIdentifier() {
+ return INDEX;
+ }
+
+ private ObjectId locateBlobObjectId() throws CoreException {
+ try {
+ final GitIndex idx = db.getIndex();
+ final Entry e = idx.getEntry(path);
+ if (e == null)
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL,
+ Path.fromPortableString(path),
+ "Git index entry not found", null);
+ return e.getObjectId();
+
+ } catch (IOException e) {
+ throw new ResourceException(IResourceStatus.FAILED_READ_LOCAL, Path
+ .fromPortableString(path),
+ "IO error looking up path in index.", e);
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommit.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommit.java
new file mode 100644
index 000000000..b94faeac1
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommit.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+class KidCommit extends RevCommit {
+ static final KidCommit[] NO_CHILDREN = {};
+
+ KidCommit[] children = NO_CHILDREN;
+
+ KidCommit(final AnyObjectId id) {
+ super(id);
+ }
+
+ void addChild(final KidCommit c) {
+ final int cnt = children.length;
+ if (cnt == 0)
+ children = new KidCommit[] { c };
+ else if (cnt == 1)
+ children = new KidCommit[] { children[0], c };
+ else {
+ final KidCommit[] n = new KidCommit[cnt + 1];
+ System.arraycopy(children, 0, n, 0, cnt);
+ n[cnt] = c;
+ children = n;
+ }
+ }
+
+ @Override
+ public void reset() {
+ children = NO_CHILDREN;
+ super.reset();
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommitList.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommitList.java
new file mode 100644
index 000000000..4bc9fe16c
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidCommitList.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import org.eclipse.jgit.revwalk.RevCommitList;
+
+class KidCommitList extends RevCommitList<KidCommit> {
+ @Override
+ protected void enter(final int index, final KidCommit e) {
+ final int nParents = e.getParentCount();
+ for (int i = 0; i < nParents; i++)
+ ((KidCommit) e.getParent(i)).addChild(e);
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidWalk.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidWalk.java
new file mode 100644
index 000000000..9865e377a
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/KidWalk.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+class KidWalk extends RevWalk {
+ KidWalk(final Repository repo) {
+ super(repo);
+ }
+
+ @Override
+ protected RevCommit createCommit(final AnyObjectId id) {
+ return new KidCommit(id);
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/WorkspaceFileRevision.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/WorkspaceFileRevision.java
new file mode 100644
index 000000000..e3f450010
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/storage/WorkspaceFileRevision.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
+ * Copyright (C) 2006, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.internal.storage;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.history.IFileRevision;
+
+/** An {@link IFileRevision} for the current version in the workspace. */
+class WorkspaceFileRevision extends GitFileRevision implements IFileRevision {
+ private final IResource rsrc;
+
+ WorkspaceFileRevision(final IResource resource) {
+ super(resource.getName());
+ rsrc = resource;
+ }
+
+ public IStorage getStorage(IProgressMonitor monitor) throws CoreException {
+ return rsrc instanceof IStorage ? (IStorage) rsrc : null;
+ }
+
+ public boolean isPropertyMissing() {
+ return false;
+ }
+
+ public IFileRevision withAllProperties(IProgressMonitor monitor)
+ throws CoreException {
+ return null;
+ }
+
+ public String getAuthor() {
+ return "";
+ }
+
+ public long getTimestamp() {
+ return -1;
+ }
+
+ public String getComment() {
+ return "";
+ }
+
+ public String getContentIdentifier() {
+ return WORKSPACE;
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ExceptionCollector.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ExceptionCollector.java
new file mode 100644
index 000000000..a2cb287f4
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/internal/util/ExceptionCollector.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * 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 org.eclipse.egit.core.internal.util;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.ILog;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * Collects exceptions and can be configured to ignore duplicates exceptions.
+ * Exceptions can be logged and a MultiStatus containing all collected
+ * exceptions can be returned.
+ *
+ * @see org.eclipse.core.runtime.MultiStatus
+ * @see org.eclipse.core.runtime.IStatus
+ *
+ * @since 3.0
+ */
+public class ExceptionCollector {
+
+ private final List<IStatus> statuses = new ArrayList<IStatus>();
+
+ private final String message;
+
+ private final String pluginId;
+
+ private final int severity;
+
+ private final ILog log;
+
+ /**
+ * Creates a collector and initializes the parameters for the top-level
+ * exception that would be returned from <code>getStatus</code> is
+ * exceptions are collected.
+ *
+ * @param message
+ * a human-readable message, localized to the current locale
+ * @param pluginId
+ * the unique identifier of the relevant plug-in
+ * @param severity
+ * the severity; one of <code>OK</code>, <code>ERROR</code>,
+ * <code>INFO</code>, or <code>WARNING</code>
+ * @param log
+ * the log to output the exceptions to, or <code>null</code> if
+ * exceptions should not be logged.
+ */
+ public ExceptionCollector(String message, String pluginId, int severity,
+ ILog log) {
+ this.message = message;
+ this.pluginId = pluginId;
+ this.severity = severity;
+ this.log = log;
+ }
+
+ /**
+ * Clears the exceptions collected.
+ */
+ public void clear() {
+ statuses.clear();
+ }
+
+ /**
+ * Returns a status that represents the exceptions collected. If the
+ * collector is empty <code>IStatus.OK</code> is returned. Otherwise a
+ * MultiStatus containing all collected exceptions is returned.
+ *
+ * @return a multistatus containing the exceptions collected or IStatus.OK
+ * if the collector is empty.
+ */
+ public IStatus getStatus() {
+ if (statuses.isEmpty()) {
+ return Status.OK_STATUS;
+ } else {
+ final MultiStatus multiStatus = new MultiStatus(pluginId, severity,
+ message, null);
+ final Iterator it = statuses.iterator();
+ while (it.hasNext()) {
+ final IStatus status = (IStatus) it.next();
+ multiStatus.merge(status);
+ }
+ return multiStatus;
+ }
+ }
+
+ /**
+ * Add this exception to the collector. If a log was specified in the
+ * constructor then the exception will be output to the log. You can
+ * retreive exceptions using <code>getStatus</code>.
+ *
+ * @param exception
+ * the exception to collect
+ */
+ public void handleException(CoreException exception) {
+ if (log != null) {
+ log.log(new Status(severity, pluginId, 0, message, exception));
+ }
+
+ // Record each status individually to flatten the resulting multi-status
+ final IStatus exceptionStatus = exception.getStatus();
+
+ // Wrap the exception so the stack trace is not lost.
+ final IStatus status = new Status(exceptionStatus.getSeverity(),
+ exceptionStatus.getPlugin(), exceptionStatus.getCode(),
+ exceptionStatus.getMessage(), exception);
+
+ recordStatus(status);
+ for (IStatus childStatus : status.getChildren())
+ recordStatus(childStatus);
+ }
+
+ private void recordStatus(IStatus status) {
+ statuses.add(status);
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/AssumeUnchangedOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/AssumeUnchangedOperation.java
new file mode 100644
index 000000000..21d6d9dc3
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/AssumeUnchangedOperation.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.project.GitProjectData;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheEntry;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Tell JGit to ignore changes in selected files
+ */
+public class AssumeUnchangedOperation implements IWorkspaceRunnable {
+ private final Collection rsrcList;
+
+ private final IdentityHashMap<Repository, DirCache> caches;
+
+ private final IdentityHashMap<RepositoryMapping, Object> mappings;
+
+ /**
+ * Create a new operation to ignore changes in tracked files
+ *
+ * @param rsrcs
+ * collection of {@link IResource}s which should be ignored when
+ * looking for changes or committing.
+ */
+ public AssumeUnchangedOperation(final Collection rsrcs) {
+ rsrcList = rsrcs;
+ caches = new IdentityHashMap<Repository, DirCache>();
+ mappings = new IdentityHashMap<RepositoryMapping, Object>();
+ }
+
+ public void run(IProgressMonitor m) throws CoreException {
+ if (m == null)
+ m = new NullProgressMonitor();
+
+ caches.clear();
+ mappings.clear();
+
+ m.beginTask(CoreText.AssumeUnchangedOperation_adding,
+ rsrcList.size() * 200);
+ try {
+ for (Object obj : rsrcList) {
+ obj = ((IAdaptable) obj).getAdapter(IResource.class);
+ if (obj instanceof IResource)
+ assumeValid((IResource) obj);
+ m.worked(200);
+ }
+
+ for (Map.Entry<Repository, DirCache> e : caches.entrySet()) {
+ final Repository db = e.getKey();
+ final DirCache editor = e.getValue();
+ m.setTaskName("Writing index for " + db.getDirectory());
+ editor.write();
+ editor.commit();
+ }
+ } catch (RuntimeException e) {
+ throw Activator.error(CoreText.UntrackOperation_failed, e);
+ } catch (IOException e) {
+ throw Activator.error(CoreText.UntrackOperation_failed, e);
+ } finally {
+ for (final RepositoryMapping rm : mappings.keySet())
+ rm.fireRepositoryChanged();
+ caches.clear();
+ mappings.clear();
+ m.done();
+ }
+ }
+
+ private void assumeValid(final IResource resource) throws CoreException {
+ final IProject proj = resource.getProject();
+ final GitProjectData pd = GitProjectData.get(proj);
+ if (pd == null)
+ return;
+ final RepositoryMapping rm = pd.getRepositoryMapping(resource);
+ if (rm == null)
+ return;
+ final Repository db = rm.getRepository();
+
+ DirCache cache = caches.get(db);
+ if (cache == null) {
+ try {
+ cache = DirCache.lock(db);
+ } catch (IOException err) {
+ throw Activator.error(CoreText.UntrackOperation_failed, err);
+ }
+ caches.put(db, cache);
+ mappings.put(rm, rm);
+ }
+
+ final String path = rm.getRepoRelativePath(resource);
+ if (resource instanceof IContainer) {
+ for (final DirCacheEntry ent : cache.getEntriesWithin(path))
+ ent.setAssumeValid(true);
+ } else {
+ final DirCacheEntry ent = cache.getEntry(path);
+ if (ent != null)
+ ent.setAssumeValid(true);
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/BranchOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/BranchOperation.java
new file mode 100644
index 000000000..7c50dff31
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/BranchOperation.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.jgit.errors.CheckoutConflictException;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.RefLogWriter;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.lib.WorkDirCheckout;
+
+/**
+ * This class implements checkouts of a specific revision. A check
+ * is made that this can be done without data loss.
+ */
+public class BranchOperation implements IWorkspaceRunnable {
+
+ private final Repository repository;
+
+ private final String refName;
+
+ /**
+ * Construct a {@link BranchOperation} object.
+ * @param repository
+ * @param refName Name of git ref to checkout
+ */
+ public BranchOperation(Repository repository, String refName) {
+ this.repository = repository;
+ this.refName = refName;
+ }
+
+ private Tree oldTree;
+
+ private GitIndex index;
+
+ private Tree newTree;
+
+ private Commit oldCommit;
+
+ private Commit newCommit;
+
+
+
+ public void run(IProgressMonitor monitor) throws CoreException {
+ lookupRefs();
+ monitor.worked(1);
+
+ mapObjects();
+ monitor.worked(1);
+
+ checkoutTree();
+ monitor.worked(1);
+
+ writeIndex();
+ monitor.worked(1);
+
+ updateHeadRef();
+ monitor.worked(1);
+
+ writeHeadReflog();
+ monitor.worked(1);
+
+ refreshProjects();
+ monitor.worked(1);
+
+ monitor.done();
+ }
+
+ private void refreshProjects() {
+ final IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
+ .getProjects();
+ final File parentFile = repository.getWorkDir();
+ for (IProject p : projects) {
+ final File file = p.getLocation().toFile();
+ if (file.getAbsolutePath().startsWith(parentFile.getAbsolutePath())) {
+ try {
+ System.out.println("Refreshing " + p);
+ p.refreshLocal(IResource.DEPTH_INFINITE, null);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private void writeHeadReflog() throws TeamException {
+ try {
+ RefLogWriter.writeReflog(repository, oldCommit.getCommitId(),
+ newCommit.getCommitId(), "checkout: moving to " + refName,
+ Constants.HEAD);
+ } catch (IOException e) {
+ throw new TeamException("Writing HEAD's reflog", e);
+ }
+ }
+
+ private void updateHeadRef() throws TeamException {
+ try {
+ repository.writeSymref(Constants.HEAD, refName);
+ } catch (IOException e) {
+ throw new TeamException("Updating HEAD to ref: " + refName, e);
+ }
+ }
+
+ private void writeIndex() throws TeamException {
+ try {
+ index.write();
+ } catch (IOException e) {
+ throw new TeamException("Writing index", e);
+ }
+ }
+
+ private void checkoutTree() throws TeamException {
+ try {
+ new WorkDirCheckout(repository, repository.getWorkDir(), oldTree,
+ index, newTree).checkout();
+ } catch (CheckoutConflictException e) {
+ TeamException teamException = new TeamException(e.getMessage());
+ throw teamException;
+ } catch (IOException e) {
+ throw new TeamException("Problem while checking out:", e);
+ }
+ }
+
+ private void mapObjects() throws TeamException {
+ try {
+ oldTree = oldCommit.getTree();
+ index = repository.getIndex();
+ newTree = newCommit.getTree();
+ } catch (IOException e) {
+ throw new TeamException("Mapping trees", e);
+ }
+ }
+
+ private void lookupRefs() throws TeamException {
+ try {
+ newCommit = repository.mapCommit(refName);
+ } catch (IOException e) {
+ throw new TeamException("Mapping commit: " + refName, e);
+ }
+
+ try {
+ oldCommit = repository.mapCommit(Constants.HEAD);
+ } catch (IOException e) {
+ throw new TeamException("Mapping commit HEAD commit", e);
+ }
+ }
+
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/CloneOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/CloneOperation.java
new file mode 100644
index 000000000..57ea79b0e
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/CloneOperation.java
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URISyntaxException;
+import java.util.Collection;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.EclipseGitProgressTransformer;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.jgit.errors.NotSupportedException;
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryConfig;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.lib.WorkDirCheckout;
+import org.eclipse.jgit.transport.FetchResult;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
+
+/**
+ * Clones a repository from a remote location to a local location.
+ */
+public class CloneOperation implements IRunnableWithProgress {
+ private final URIish uri;
+
+ private final boolean allSelected;
+
+ private final Collection<Ref> selectedBranches;
+
+ private final File workdir;
+
+ private final String branch;
+
+ private final String remoteName;
+
+ private Repository local;
+
+ private RemoteConfig remoteConfig;
+
+ private FetchResult fetchResult;
+
+ /**
+ * Create a new clone operation.
+ *
+ * @param uri
+ * remote we should fetch from.
+ * @param allSelected
+ * true when all branches have to be fetched (indicates wildcard
+ * in created fetch refspec), false otherwise.
+ * @param selectedBranches
+ * collection of branches to fetch. Ignored when allSelected is
+ * true.
+ * @param workdir
+ * working directory to clone to. The directory may or may not
+ * already exist.
+ * @param branch
+ * branch to initially clone from.
+ * @param remoteName
+ * name of created remote config as source remote (typically
+ * named "origin").
+ */
+ public CloneOperation(final URIish uri, final boolean allSelected,
+ final Collection<Ref> selectedBranches, final File workdir,
+ final String branch, final String remoteName) {
+ this.uri = uri;
+ this.allSelected = allSelected;
+ this.selectedBranches = selectedBranches;
+ this.workdir = workdir;
+ this.branch = branch;
+ this.remoteName = remoteName;
+ }
+
+ public void run(final IProgressMonitor pm)
+ throws InvocationTargetException, InterruptedException {
+ final IProgressMonitor monitor;
+ if (pm == null)
+ monitor = new NullProgressMonitor();
+ else
+ monitor = pm;
+
+ try {
+ monitor.beginTask(NLS.bind(CoreText.CloneOperation_title, uri),
+ 5000);
+ try {
+ doInit(new SubProgressMonitor(monitor, 100));
+ doFetch(new SubProgressMonitor(monitor, 4000));
+ doCheckout(new SubProgressMonitor(monitor, 900));
+ } finally {
+ closeLocal();
+ }
+ } catch (final Exception e) {
+ delete(workdir);
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+ else
+ throw new InvocationTargetException(e);
+ } finally {
+ monitor.done();
+ }
+ }
+
+ private void closeLocal() {
+ if (local != null) {
+ local.close();
+ local = null;
+ }
+ }
+
+ private void doInit(final IProgressMonitor monitor)
+ throws URISyntaxException, IOException {
+ monitor.setTaskName("Initializing local repository");
+
+ final File gitdir = new File(workdir, ".git");
+ local = new Repository(gitdir);
+ local.create();
+ local.writeSymref(Constants.HEAD, branch);
+
+ remoteConfig = new RemoteConfig(local.getConfig(), remoteName);
+ remoteConfig.addURI(uri);
+
+ final String dst = Constants.R_REMOTES + remoteConfig.getName();
+ RefSpec wcrs = new RefSpec();
+ wcrs = wcrs.setForceUpdate(true);
+ wcrs = wcrs.setSourceDestination(Constants.R_HEADS + "*", dst + "/*");
+
+ if (allSelected) {
+ remoteConfig.addFetchRefSpec(wcrs);
+ } else {
+ for (final Ref ref : selectedBranches)
+ if (wcrs.matchSource(ref))
+ remoteConfig.addFetchRefSpec(wcrs.expandFromSource(ref));
+ }
+
+ // we're setting up for a clone with a checkout
+ local.getConfig().setBoolean("core", null, "bare", false);
+
+ remoteConfig.update(local.getConfig());
+
+ // branch is like 'Constants.R_HEADS + branchName', we need only
+ // the 'branchName' part
+ String branchName = branch.substring(Constants.R_HEADS.length());
+
+ // setup the default remote branch for branchName
+ local.getConfig().setString(RepositoryConfig.BRANCH_SECTION,
+ branchName, "remote", remoteName);
+ local.getConfig().setString(RepositoryConfig.BRANCH_SECTION,
+ branchName, "merge", branch);
+
+ local.getConfig().save();
+ }
+
+ private void doFetch(final IProgressMonitor monitor)
+ throws NotSupportedException, TransportException {
+ final Transport tn = Transport.open(local, remoteConfig);
+ try {
+ final EclipseGitProgressTransformer pm;
+ pm = new EclipseGitProgressTransformer(monitor);
+ fetchResult = tn.fetch(pm, null);
+ } finally {
+ tn.close();
+ }
+ }
+
+ private void doCheckout(final IProgressMonitor monitor) throws IOException {
+ final Ref head = fetchResult.getAdvertisedRef(branch);
+ if (head == null || head.getObjectId() == null)
+ return;
+
+ final GitIndex index = new GitIndex(local);
+ final Commit mapCommit = local.mapCommit(head.getObjectId());
+ final Tree tree = mapCommit.getTree();
+ final RefUpdate u;
+ final WorkDirCheckout co;
+
+ u = local.updateRef(Constants.HEAD);
+ u.setNewObjectId(mapCommit.getCommitId());
+ u.forceUpdate();
+
+ monitor.setTaskName("Checking out files");
+ co = new WorkDirCheckout(local, local.getWorkDir(), index, tree);
+ co.checkout();
+ monitor.setTaskName("Writing index");
+ index.write();
+ }
+
+ private static void delete(final File d) {
+ if (d.isDirectory()) {
+ final File[] items = d.listFiles();
+ if (items != null) {
+ for (final File c : items)
+ delete(c);
+ }
+ }
+ d.delete();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ConnectProviderOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ConnectProviderOperation.java
new file mode 100644
index 000000000..a85441841
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ConnectProviderOperation.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.util.Collection;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.GitProvider;
+import org.eclipse.egit.core.project.GitProjectData;
+import org.eclipse.egit.core.project.RepositoryFinder;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.team.core.RepositoryProvider;
+
+/**
+ * Connects Eclipse to an existing Git repository
+ */
+public class ConnectProviderOperation implements IWorkspaceRunnable {
+ private final IProject[] projects;
+
+ /**
+ * Create a new connection operation to execute within the workspace.
+ *
+ * @param proj
+ * the project to connect to the Git team provider.
+ */
+ public ConnectProviderOperation(final IProject proj) {
+ this(new IProject[] { proj });
+ }
+
+ /**
+ * Create a new connection operation to execute within the workspace.
+ *
+ * @param projects
+ * the projects to connect to the Git team provider.
+ */
+ public ConnectProviderOperation(final IProject[] projects) {
+ this.projects = projects;
+ }
+
+ public void run(IProgressMonitor m) throws CoreException {
+ if (m == null) {
+ m = new NullProgressMonitor();
+ }
+
+ m.beginTask(CoreText.ConnectProviderOperation_connecting,
+ 100 * projects.length);
+ try {
+
+ for (IProject project : projects) {
+ m.setTaskName(NLS.bind(
+ CoreText.ConnectProviderOperation_ConnectingProject,
+ project.getName()));
+ Activator.trace("Locating repository for " + project); //$NON-NLS-1$
+ Collection<RepositoryMapping> repos = new RepositoryFinder(
+ project).find(new SubProgressMonitor(m, 40));
+ if (repos.size() == 1) {
+ GitProjectData projectData = new GitProjectData(project);
+ try {
+ projectData.setRepositoryMappings(repos);
+ projectData.store();
+ } catch (CoreException ce) {
+ GitProjectData.delete(project);
+ throw ce;
+ } catch (RuntimeException ce) {
+ GitProjectData.delete(project);
+ throw ce;
+ }
+ RepositoryProvider
+ .map(project, GitProvider.class.getName());
+ projectData = GitProjectData.get(project);
+ project.refreshLocal(IResource.DEPTH_INFINITE,
+ new SubProgressMonitor(m, 50));
+ m.worked(10);
+ } else {
+ Activator
+ .trace("Attempted to share project without repository ignored :" //$NON-NLS-1$
+ + project);
+ m.worked(60);
+ }
+ }
+ } finally {
+ m.done();
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/DisconnectProviderOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/DisconnectProviderOperation.java
new file mode 100644
index 000000000..6f2b9ee07
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/DisconnectProviderOperation.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.util.Collection;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.team.core.RepositoryProvider;
+
+/**
+ * Disconnects the Git team provider from a project.
+ * <p>
+ * Once disconnected, Git operations will no longer be available on the project.
+ * </p>
+ */
+public class DisconnectProviderOperation implements IWorkspaceRunnable {
+ private final Collection projectList;
+
+ /**
+ * Create a new disconnect operation.
+ *
+ * @param projs
+ * the collection of {@link IProject}s which should be
+ * disconnected from the Git team provider, and returned to
+ * untracked/unmanaged status.
+ */
+ public DisconnectProviderOperation(final Collection projs) {
+ projectList = projs;
+ }
+
+ public void run(IProgressMonitor m) throws CoreException {
+ if (m == null) {
+ m = new NullProgressMonitor();
+ }
+
+ m.beginTask(CoreText.DisconnectProviderOperation_disconnecting,
+ projectList.size() * 200);
+ try {
+ for (Object obj : projectList) {
+ obj = ((IAdaptable)obj).getAdapter(IResource.class);
+ if (obj instanceof IProject) {
+ final IProject p = (IProject) obj;
+
+ Activator.trace("disconnect " + p.getName());
+ unmarkTeamPrivate(p);
+ RepositoryProvider.unmap(p);
+ m.worked(100);
+
+ p.refreshLocal(IResource.DEPTH_INFINITE,
+ new SubProgressMonitor(m, 100));
+ } else {
+ m.worked(200);
+ }
+ }
+ } finally {
+ m.done();
+ }
+ }
+
+ private void unmarkTeamPrivate(final IContainer p) throws CoreException {
+ final IResource[] c;
+ c = p.members(IContainer.INCLUDE_TEAM_PRIVATE_MEMBERS);
+ if (c != null) {
+ for (int k = 0; k < c.length; k++) {
+ if (c[k] instanceof IContainer) {
+ unmarkTeamPrivate((IContainer) c[k]);
+ }
+ if (c[k].isTeamPrivateMember()) {
+ Activator.trace("notTeamPrivate " + c[k]);
+ c[k].setTeamPrivateMember(false);
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ListRemoteOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ListRemoteOperation.java
new file mode 100644
index 000000000..6963d750d
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ListRemoteOperation.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jgit.errors.NotSupportedException;
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.Connection;
+import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
+
+/**
+ * Operation of listing remote repository advertised refs.
+ */
+public class ListRemoteOperation implements IRunnableWithProgress {
+ private final Repository localDb;
+
+ private final URIish uri;
+
+ private Map<String, Ref> remoteRefsMap;
+
+ /**
+ * Create listing operation for specified local repository (needed by
+ * transport) and remote repository URI.
+ *
+ * @param localDb
+ * local repository (needed for transport) where fetch would
+ * occur.
+ * @param uri
+ * URI of remote repository to list.
+ */
+ public ListRemoteOperation(final Repository localDb, final URIish uri) {
+ this.localDb = localDb;
+ this.uri = uri;
+ }
+
+ /**
+ * @return collection of refs advertised by remote side.
+ * @throws IllegalStateException
+ * if error occurred during earlier remote refs listing.
+ */
+ public Collection<Ref> getRemoteRefs() {
+ checkState();
+ return remoteRefsMap.values();
+ }
+
+ /**
+ * @param refName
+ * remote ref name to search for.
+ * @return ref with specified refName or null if not found.
+ * @throws IllegalStateException
+ * if error occurred during earlier remote refs listing.
+ */
+ public Ref getRemoteRef(final String refName) {
+ checkState();
+ return remoteRefsMap.get(refName);
+ }
+
+ public void run(IProgressMonitor pm) throws InvocationTargetException,
+ InterruptedException {
+ Transport transport = null;
+ Connection connection = null;
+ try {
+ transport = Transport.open(localDb, uri);
+
+ if (pm != null)
+ pm.beginTask(CoreText.ListRemoteOperation_title,
+ IProgressMonitor.UNKNOWN);
+ connection = transport.openFetch();
+ remoteRefsMap = connection.getRefsMap();
+ } catch (NotSupportedException e) {
+ throw new InvocationTargetException(e);
+ } catch (TransportException e) {
+ throw new InvocationTargetException(e);
+ } finally {
+ if (connection != null)
+ connection.close();
+ if (transport != null)
+ transport.close();
+ if (pm != null)
+ pm.done();
+ }
+ }
+
+ private void checkState() {
+ if (remoteRefsMap == null)
+ throw new IllegalStateException(
+ "Error occurred during remote repo listing, no refs available");
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperation.java
new file mode 100644
index 000000000..37ae51a3d
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperation.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.EclipseGitProgressTransformer;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.jgit.errors.NoRemoteRepositoryException;
+import org.eclipse.jgit.errors.NotSupportedException;
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.transport.PushResult;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
+
+/**
+ * Push operation: pushing from local repository to one or many remote ones.
+ */
+public class PushOperation implements IRunnableWithProgress {
+ private static final int WORK_UNITS_PER_TRANSPORT = 10;
+
+ private final Repository localDb;
+
+ private final PushOperationSpecification specification;
+
+ private final boolean dryRun;
+
+ private final RemoteConfig rc;
+
+ private final PushOperationResult operationResult = new PushOperationResult();
+
+ /**
+ * Create push operation for provided specification.
+ * <p>
+ * Operation is not performed within constructor,
+ * {@link #run(IProgressMonitor)} method must be called for that.
+ *
+ * @param localDb
+ * local repository.
+ * @param specification
+ * specification of ref updates for remote repositories.
+ * @param rc
+ * optional remote config to apply on used transports. May be
+ * null.
+ * @param dryRun
+ * true if push operation should just check for possible result
+ * and not really update remote refs, false otherwise - when push
+ * should act normally.
+ */
+ public PushOperation(final Repository localDb,
+ final PushOperationSpecification specification,
+ final boolean dryRun, final RemoteConfig rc) {
+ this.localDb = localDb;
+ this.specification = specification;
+ this.dryRun = dryRun;
+ this.rc = rc;
+ }
+
+ /**
+ * @return push operation result.
+ */
+ public PushOperationResult getOperationResult() {
+ return operationResult;
+ }
+
+ /**
+ * @return operation specification, as provided in constructor.
+ */
+ public PushOperationSpecification getSpecification() {
+ return specification;
+ }
+
+ /**
+ * Execute operation and store result. Operation is executed independently
+ * on each remote repository.
+ * <p>
+ *
+ * @throws InvocationTargetException
+ * Cause of this exceptions may include
+ * {@link TransportException}, {@link NotSupportedException} or
+ * some unexpected {@link RuntimeException}.
+ * @see IRunnableWithProgress#run(IProgressMonitor)
+ */
+ public void run(IProgressMonitor monitor) throws InvocationTargetException {
+ if (monitor == null)
+ monitor = new NullProgressMonitor();
+
+ final int totalWork = specification.getURIsNumber()
+ * WORK_UNITS_PER_TRANSPORT;
+ if (dryRun)
+ monitor.beginTask(CoreText.PushOperation_taskNameDryRun, totalWork);
+ else
+ monitor.beginTask(CoreText.PushOperation_taskNameNormalRun,
+ totalWork);
+
+ for (final URIish uri : specification.getURIs()) {
+ final SubProgressMonitor subMonitor = new SubProgressMonitor(
+ monitor, WORK_UNITS_PER_TRANSPORT,
+ SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+ Transport transport = null;
+ try {
+ if (monitor.isCanceled()) {
+ operationResult.addOperationResult(uri,
+ CoreText.PushOperation_resultCancelled);
+ continue;
+ }
+ transport = Transport.open(localDb, uri);
+
+ if (rc != null)
+ transport.applyConfig(rc);
+ transport.setDryRun(dryRun);
+ final EclipseGitProgressTransformer gitSubMonitor = new EclipseGitProgressTransformer(
+ subMonitor);
+ final PushResult pr = transport.push(gitSubMonitor,
+ specification.getRefUpdates(uri));
+ operationResult.addOperationResult(uri, pr);
+ } catch (final NoRemoteRepositoryException e) {
+ operationResult.addOperationResult(uri, NLS.bind(
+ CoreText.PushOperation_resultNoServiceError, e
+ .getMessage()));
+ } catch (final TransportException e) {
+ operationResult.addOperationResult(uri, NLS.bind(
+ CoreText.PushOperation_resultTransportError, e
+ .getMessage()));
+ } catch (final NotSupportedException e) {
+ operationResult.addOperationResult(uri, NLS.bind(
+ CoreText.PushOperation_resultNotSupported, e
+ .getMessage()));
+ } finally {
+ if (transport != null) {
+ transport.close();
+ }
+ // Dirty trick to get things always working.
+ subMonitor.beginTask("", WORK_UNITS_PER_TRANSPORT); //$NON-NLS-1$
+ subMonitor.done();
+ subMonitor.done();
+ }
+ }
+ monitor.done();
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperationResult.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperationResult.java
new file mode 100644
index 000000000..520951d21
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperationResult.java
@@ -0,0 +1,274 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Set;
+
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.transport.PushResult;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+import org.eclipse.jgit.transport.URIish;
+
+/**
+ * Data class for storing push operation results for each remote repository/URI
+ * being part of push operation.
+ * <p>
+ * One instance of this class is dedicated for result of one push operation:
+ * either to one URI or to many URIs.
+ *
+ * @see PushOperation
+ */
+public class PushOperationResult {
+ private LinkedHashMap<URIish, Entry> urisEntries;
+
+ /**
+ * Construct empty push operation result.
+ */
+ PushOperationResult() {
+ this.urisEntries = new LinkedHashMap<URIish, Entry>();
+ }
+
+ /**
+ * Add push result for the repository (URI) with successful connection.
+ *
+ * @param uri
+ * remote repository URI.
+ * @param result
+ * push result.
+ */
+ public void addOperationResult(final URIish uri, final PushResult result) {
+ urisEntries.put(uri, new Entry(result));
+ }
+
+ /**
+ * Add error message for the repository (URI) with unsuccessful connection.
+ *
+ * @param uri
+ * remote repository URI.
+ * @param errorMessage
+ * failure error message.
+ */
+ public void addOperationResult(final URIish uri, final String errorMessage) {
+ urisEntries.put(uri, new Entry(errorMessage));
+ }
+
+ /**
+ * @return set of remote repositories URIish. Set is ordered in addition
+ * sequence, which is usually the same as that from
+ * {@link PushOperationSpecification}.
+ */
+ public Set<URIish> getURIs() {
+ return Collections.unmodifiableSet(urisEntries.keySet());
+ }
+
+ /**
+ * @param uri
+ * remote repository URI.
+ * @return true if connection was successful for this repository (URI),
+ * false if this operation ended with unsuccessful connection.
+ */
+ public boolean isSuccessfulConnection(final URIish uri) {
+ return urisEntries.get(uri).isSuccessfulConnection();
+ }
+
+ /**
+ * @return true if connection was successful for any repository (URI), false
+ * otherwise.
+ */
+ public boolean isSuccessfulConnectionForAnyURI() {
+ for (final URIish uri : getURIs()) {
+ if (isSuccessfulConnection(uri))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param uri
+ * remote repository URI.
+ * @return push result for this repository (URI) or null if operation ended
+ * with unsuccessful connection for this URI.
+ */
+ public PushResult getPushResult(final URIish uri) {
+ return urisEntries.get(uri).getResult();
+ }
+
+ /**
+ * @param uri
+ * remote repository URI.
+ * @return error message for this repository (URI) or null if operation
+ * ended with successful connection for this URI.
+ */
+ public String getErrorMessage(final URIish uri) {
+ return urisEntries.get(uri).getErrorMessage();
+ }
+
+ /**
+ * @return string being list of failed URIs with their error messages.
+ */
+ public String getErrorStringForAllURis() {
+ final StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (final URIish uri : getURIs()) {
+ if (first)
+ first = false;
+ else
+ sb.append(", ");
+ sb.append(uri);
+ sb.append(" (");
+ sb.append(getErrorMessage(uri));
+ sb.append(")");
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Derive push operation specification from this push operation result.
+ * <p>
+ * Specification is created basing on URIs of remote repositories in this
+ * result that completed without connection errors, and remote ref updates
+ * from push results.
+ * <p>
+ * This method is targeted to provide support for 2-stage push, where first
+ * operation is dry run for user confirmation and second one is a real
+ * operation.
+ *
+ * @param requireUnchanged
+ * if true, newly created copies of remote ref updates have
+ * expected old object id set to previously advertised ref value
+ * (remote ref won't be updated if it change in the mean time),
+ * if false, newly create copies of remote ref updates have
+ * expected object id set up as in this result source
+ * specification.
+ * @return derived specification for another push operation.
+ * @throws IOException
+ * when some previously locally available source ref is not
+ * available anymore, or some error occurred during creation
+ * locally tracking ref update.
+ *
+ */
+ public PushOperationSpecification deriveSpecification(
+ final boolean requireUnchanged) throws IOException {
+ final PushOperationSpecification spec = new PushOperationSpecification();
+ for (final URIish uri : getURIs()) {
+ final PushResult pr = getPushResult(uri);
+ if (pr == null)
+ continue;
+
+ final Collection<RemoteRefUpdate> oldUpdates = pr
+ .getRemoteUpdates();
+ final ArrayList<RemoteRefUpdate> newUpdates = new ArrayList<RemoteRefUpdate>(
+ oldUpdates.size());
+ for (final RemoteRefUpdate rru : oldUpdates) {
+ final ObjectId expectedOldObjectId;
+ if (requireUnchanged) {
+ final Ref advertisedRef = getPushResult(uri)
+ .getAdvertisedRef(rru.getRemoteName());
+ if (advertisedRef == null)
+ expectedOldObjectId = ObjectId.zeroId();
+ else
+ expectedOldObjectId = advertisedRef.getObjectId();
+ } else
+ expectedOldObjectId = rru.getExpectedOldObjectId();
+ final RemoteRefUpdate newRru = new RemoteRefUpdate(rru,
+ expectedOldObjectId);
+ newUpdates.add(newRru);
+ }
+ spec.addURIRefUpdates(uri, newUpdates);
+ }
+ return spec;
+ }
+
+ /**
+ * This implementation returns true if all following conditions are met:
+ * <ul>
+ * <li>both objects result have the same set successfully connected
+ * repositories (URIs) - unsuccessful connections are discarded, AND <li>
+ * remote ref updates must match for each successful connection in sense of
+ * equal remoteName, equal status and equal newObjectId value.</li>
+ * </ul>
+ *
+ * @see Object#equals(Object)
+ * @param obj
+ * other push operation result to compare to.
+ * @return true if object is equal to this one in terms of conditions
+ * described above, false otherwise.
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (!(obj instanceof PushOperationResult))
+ return false;
+
+ final PushOperationResult other = (PushOperationResult) obj;
+
+ // Check successful connections/URIs two-ways:
+ final Set<URIish> otherURIs = other.getURIs();
+ for (final URIish uri : getURIs()) {
+ if (isSuccessfulConnection(uri)
+ && (!otherURIs.contains(uri) || !other
+ .isSuccessfulConnection(uri)))
+ return false;
+ }
+ for (final URIish uri : other.getURIs()) {
+ if (other.isSuccessfulConnection(uri)
+ && (!urisEntries.containsKey(uri) || !isSuccessfulConnection(uri)))
+ return false;
+ }
+
+ for (final URIish uri : getURIs()) {
+ if (!isSuccessfulConnection(uri))
+ continue;
+
+ final PushResult otherPushResult = other.getPushResult(uri);
+ for (final RemoteRefUpdate rru : getPushResult(uri)
+ .getRemoteUpdates()) {
+ final RemoteRefUpdate otherRru = otherPushResult
+ .getRemoteUpdate(rru.getRemoteName());
+ if (otherRru == null)
+ return false;
+ if (otherRru.getStatus() != rru.getStatus()
+ || otherRru.getNewObjectId() != rru.getNewObjectId())
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static class Entry {
+ private String errorMessage;
+
+ private PushResult result;
+
+ Entry(final PushResult result) {
+ this.result = result;
+ }
+
+ Entry(final String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ boolean isSuccessfulConnection() {
+ return result != null;
+ }
+
+ String getErrorMessage() {
+ return errorMessage;
+ }
+
+ PushResult getResult() {
+ return result;
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperationSpecification.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperationSpecification.java
new file mode 100644
index 000000000..6369f5a53
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/PushOperationSpecification.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Set;
+
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+import org.eclipse.jgit.transport.URIish;
+
+/**
+ * Data class storing push operation update specifications for each remote
+ * repository.
+ * <p>
+ * One instance is dedicated for one push operation: either push to one URI or
+ * to many URIs.
+ *
+ * @see PushOperation
+ */
+public class PushOperationSpecification {
+ private LinkedHashMap<URIish, Collection<RemoteRefUpdate>> urisRefUpdates;
+
+ /**
+ * Create empty instance of specification.
+ * <p>
+ * URIs and ref updates should be configured
+ * {@link #addURIRefUpdates(URIish, Collection)} method.
+ */
+ public PushOperationSpecification() {
+ this.urisRefUpdates = new LinkedHashMap<URIish, Collection<RemoteRefUpdate>>();
+ }
+
+ /**
+ * Add remote repository URI with ref updates specification.
+ * <p>
+ * Ref updates are not in constructor - pay attention to not share them
+ * between different URIs ref updates or push operations.
+ * <p>
+ * Note that refUpdates can differ between URIs <b>only</b> by expected old
+ * object id field: {@link RemoteRefUpdate#getExpectedOldObjectId()}.
+ *
+ * @param uri
+ * remote repository URI.
+ * @param refUpdates
+ * collection of remote ref updates specifications.
+ */
+ public void addURIRefUpdates(final URIish uri,
+ Collection<RemoteRefUpdate> refUpdates) {
+ urisRefUpdates.put(uri, refUpdates);
+ }
+
+ /**
+ * @return set of remote repositories URIish. Set is ordered in addition
+ * sequence.
+ */
+ public Set<URIish> getURIs() {
+ return Collections.unmodifiableSet(urisRefUpdates.keySet());
+ }
+
+ /**
+ * @return number of remote repositories URI for this push operation.
+ */
+ public int getURIsNumber() {
+ return urisRefUpdates.keySet().size();
+ }
+
+ /**
+ * @param uri
+ * remote repository URI.
+ * @return remote ref updates as specified by user for this URI.
+ */
+ public Collection<RemoteRefUpdate> getRefUpdates(final URIish uri) {
+ return Collections.unmodifiableCollection(urisRefUpdates.get(uri));
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ResetOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ResetOperation.java
new file mode 100644
index 000000000..1b046632b
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/ResetOperation.java
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.RefLogWriter;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Tag;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.lib.WorkDirCheckout;
+
+/**
+ * A class for changing a ref and possibly index and workdir too.
+ */
+public class ResetOperation implements IWorkspaceRunnable {
+ /**
+ * Kind of reset
+ */
+ public enum ResetType {
+ /**
+ * Just change the ref. The index and workdir are not changed.
+ */
+ SOFT,
+
+ /**
+ * Change the ref and the index. The workdir is not changed.
+ */
+ MIXED,
+
+ /**
+ * Change the ref, the index and the workdir
+ */
+ HARD
+ }
+
+ private final Repository repository;
+ private final String refName;
+ private final ResetType type;
+
+ private Commit commit;
+ private Commit previousCommit;
+ private Tree newTree;
+ private GitIndex index;
+
+ /**
+ * Construct a {@link ResetOperation}
+ *
+ * @param repository
+ * @param refName
+ * @param type
+ */
+ public ResetOperation(Repository repository, String refName, ResetType type) {
+ this.repository = repository;
+ this.refName = refName;
+ this.type = type;
+ }
+
+ public void run(IProgressMonitor monitor) throws CoreException {
+ monitor.beginTask("Performing " + type.toString().toLowerCase() + " reset to " + refName, 7);
+
+ mapObjects();
+ monitor.worked(1);
+
+ writeRef();
+ monitor.worked(1);
+
+ if (type != ResetType.SOFT) {
+ if (type == ResetType.MIXED)
+ resetIndex();
+ else
+ readIndex();
+ writeIndex();
+ }
+ monitor.worked(1);
+
+ if (type == ResetType.HARD) {
+ checkoutIndex();
+ }
+ monitor.worked(1);
+
+ if (type != ResetType.SOFT) {
+ refreshIndex();
+ }
+ monitor.worked(1);
+
+ writeReflogs();
+ monitor.worked(1);
+
+ refreshProjects();
+
+ monitor.done();
+ }
+
+ private void refreshIndex() throws TeamException {
+// File workdir = repository.getDirectory().getParentFile();
+// for (Entry e : newIndex.getMembers()) {
+// try {
+// e.update(new File(workdir, e.getName()));
+// } catch (IOException ignore) {}
+// }
+ try {
+ index.write();
+ } catch (IOException e1) {
+ throw new TeamException("Writing index", e1);
+ }
+ }
+
+ private void refreshProjects() {
+ final IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ final File parentFile = repository.getWorkDir();
+ for (IProject p : projects) {
+ final File file = p.getLocation().toFile();
+ if (file.getAbsolutePath().startsWith(parentFile.getAbsolutePath())) {
+ try {
+ System.out.println("Refreshing " + p);
+ p.refreshLocal(IResource.DEPTH_INFINITE, null);
+ } catch (CoreException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private void mapObjects() throws TeamException {
+ final ObjectId commitId;
+ try {
+ commitId = repository.resolve(refName);
+ } catch (IOException e) {
+ throw new TeamException("looking up ref " + refName, e);
+ }
+ try {
+ commit = repository.mapCommit(commitId);
+ } catch (IOException e) {
+ try {
+ Tag t = repository.mapTag(refName, commitId);
+ commit = repository.mapCommit(t.getObjId());
+ } catch (IOException e2) {
+ throw new TeamException("looking up commit " + commitId, e2);
+ }
+ }
+
+ try {
+ previousCommit = repository.mapCommit(repository.resolve(Constants.HEAD));
+ } catch (IOException e) {
+ throw new TeamException("looking up HEAD commit", e);
+ }
+ }
+
+ private void writeRef() throws TeamException {
+ try {
+ final RefUpdate ru = repository.updateRef(Constants.HEAD);
+ ru.setNewObjectId(commit.getCommitId());
+ ru.setRefLogMessage("reset", false);
+ if (ru.forceUpdate() == RefUpdate.Result.LOCK_FAILURE)
+ throw new TeamException("Can't update " + ru.getName());
+ } catch (IOException e) {
+ throw new TeamException("Updating " + Constants.HEAD + " failed", e);
+ }
+ }
+
+ private void readIndex() throws TeamException {
+ try {
+ newTree = commit.getTree();
+ index = repository.getIndex();
+ } catch (IOException e) {
+ throw new TeamException("Reading index", e);
+ }
+ }
+
+ private void resetIndex() throws TeamException {
+ try {
+ newTree = commit.getTree();
+ index = repository.getIndex();
+ index.readTree(newTree);
+ } catch (IOException e) {
+ throw new TeamException("Reading index", e);
+ }
+ }
+
+ private void writeIndex() throws CoreException {
+ try {
+ index.write();
+ } catch (IOException e) {
+ throw new TeamException("Writing index", e);
+ }
+ }
+
+ private void checkoutIndex() throws TeamException {
+ final File parentFile = repository.getWorkDir();
+ try {
+ WorkDirCheckout workDirCheckout =
+ new WorkDirCheckout(repository, parentFile, index, newTree);
+ workDirCheckout.setFailOnConflict(false);
+ workDirCheckout.checkout();
+ } catch (IOException e) {
+ throw new TeamException("mapping tree for commit", e);
+ }
+ }
+
+
+ private void writeReflog(String reflogRelPath) throws IOException {
+ String name = refName;
+ if (name.startsWith("refs/heads/"))
+ name = name.substring(11);
+ if (name.startsWith("refs/remotes/"))
+ name = name.substring(13);
+
+ String message = "reset --" + type.toString().toLowerCase() + " " + name;
+
+ RefLogWriter.writeReflog(repository, previousCommit.getCommitId(), commit.getCommitId(), message, reflogRelPath);
+ }
+
+ private void writeReflogs() throws TeamException {
+ try {
+ writeReflog(Constants.HEAD);
+ writeReflog(repository.getFullBranch());
+ } catch (IOException e) {
+ throw new TeamException("Writing reflogs", e);
+ }
+ }
+}
+
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/TrackOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/TrackOperation.java
new file mode 100644
index 000000000..cd431a484
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/TrackOperation.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+
+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.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.team.core.Team;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.GitIndex.Entry;
+
+/**
+ * Add one or more new files/folders to the Git repository.
+ * <p>
+ * Accepts a collection of resources (files and/or directories) which should be
+ * added to the their corresponding Git repositories. Resources in the
+ * collection can be associated with multiple repositories. The operation will
+ * automatically associate each resource with the nearest containing Git
+ * repository.
+ * </p>
+ * <p>
+ * Resources are only scheduled for addition in the index.
+ * </p>
+ */
+public class TrackOperation implements IWorkspaceRunnable {
+ private final Collection rsrcList;
+
+ /**
+ * Create a new operation to track additional files/folders.
+ *
+ * @param rsrcs
+ * collection of {@link IResource}s which should be added to the
+ * relevant Git repositories.
+ */
+ public TrackOperation(final Collection rsrcs) {
+ rsrcList = rsrcs;
+ }
+
+ public void run(IProgressMonitor m) throws CoreException {
+ if (m == null) {
+ m = new NullProgressMonitor();
+ }
+
+ final IdentityHashMap<RepositoryMapping, Boolean> tomerge = new IdentityHashMap<RepositoryMapping, Boolean>();
+ m.beginTask(CoreText.AddOperation_adding, rsrcList.size() * 200);
+ try {
+ for (Object obj : rsrcList) {
+ obj = ((IAdaptable)obj).getAdapter(IResource.class);
+ if (obj instanceof IResource) {
+ final IResource toAdd = (IResource)obj;
+ final RepositoryMapping rm = RepositoryMapping.getMapping(toAdd);
+ final GitIndex index = rm.getRepository().getIndex();
+
+ if (obj instanceof IFile) {
+ String repoPath = rm.getRepoRelativePath((IResource) obj);
+ Entry entry = index.getEntry(repoPath);
+ if (entry != null) {
+ if (!entry.isAssumedValid()) {
+ System.out.println("Already tracked - skipping");
+ continue;
+ }
+ }
+ }
+
+ tomerge.put(rm, Boolean.TRUE);
+ if (toAdd instanceof IContainer) {
+ ((IContainer)toAdd).accept(new IResourceVisitor() {
+ public boolean visit(IResource resource) throws CoreException {
+ try {
+ String repoPath = rm.getRepoRelativePath(resource);
+ // We use add to reset the assume valid bit, so we check the bit
+ // first. If a resource within a ignored folder is marked
+ // we ignore it here, i.e. there is no way to unmark it expect
+ // by explicitly selecting and invoking track on it.
+ boolean isIgnored = Team.isIgnoredHint(resource);
+ if (resource.getType() == IResource.FILE) {
+ Entry entry = index.getEntry(repoPath);
+ if (!isIgnored || entry != null && entry.isAssumedValid()) {
+ entry = index.add(rm.getWorkDir(), new File(rm.getWorkDir(), repoPath));
+ entry.setAssumeValid(false);
+ }
+ }
+ if (isIgnored)
+ return false;
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw Activator.error(CoreText.AddOperation_failed, e);
+ }
+ return true;
+ }
+ },IResource.DEPTH_INFINITE, IContainer.EXCLUDE_DERIVED);
+ } else {
+ Entry entry = index.add(rm.getWorkDir(), new File(rm.getWorkDir(),rm.getRepoRelativePath(toAdd)));
+ entry.setAssumeValid(false);
+
+ }
+ }
+ m.worked(200);
+ }
+ for (RepositoryMapping rm : tomerge.keySet()) {
+ m.setTaskName("Writing index for "+rm.getRepository().getDirectory());
+ rm.getRepository().getIndex().write();
+ }
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw Activator.error(CoreText.AddOperation_failed, e);
+ } catch (IOException e) {
+ e.printStackTrace();
+ throw Activator.error(CoreText.AddOperation_failed, e);
+ } finally {
+ try {
+ final Iterator i = tomerge.keySet().iterator();
+ while (i.hasNext()) {
+ final RepositoryMapping r = (RepositoryMapping) i.next();
+ r.getRepository().getIndex().read();
+ r.fireRepositoryChanged();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ m.done();
+ }
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/UntrackOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/UntrackOperation.java
new file mode 100644
index 000000000..39bd827ae
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/UntrackOperation.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.project.GitProjectData;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheEditor;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Remove one or more existing files/folders from the Git repository.
+ * <p>
+ * Accepts a collection of resources (files and/or directories) which should be
+ * removed from the their corresponding Git repositories. Resources in the
+ * collection can be associated with multiple repositories. The operation will
+ * automatically remove each resource from the correct Git repository.
+ * </p>
+ * <p>
+ * Resources are only scheduled for removal in the index-
+ * </p>
+ */
+public class UntrackOperation implements IWorkspaceRunnable {
+ private final Collection rsrcList;
+
+ private final IdentityHashMap<Repository, DirCacheEditor> edits;
+
+ private final IdentityHashMap<RepositoryMapping, Object> mappings;
+
+ /**
+ * Create a new operation to stop tracking existing files/folders.
+ *
+ * @param rsrcs
+ * collection of {@link IResource}s which should be removed from
+ * the relevant Git repositories.
+ */
+ public UntrackOperation(final Collection rsrcs) {
+ rsrcList = rsrcs;
+ edits = new IdentityHashMap<Repository, DirCacheEditor>();
+ mappings = new IdentityHashMap<RepositoryMapping, Object>();
+ }
+
+ public void run(IProgressMonitor m) throws CoreException {
+ if (m == null)
+ m = new NullProgressMonitor();
+
+ edits.clear();
+ mappings.clear();
+
+ m.beginTask(CoreText.AddOperation_adding, rsrcList.size() * 200);
+ try {
+ for (Object obj : rsrcList) {
+ obj = ((IAdaptable) obj).getAdapter(IResource.class);
+ if (obj instanceof IResource)
+ remove((IResource) obj);
+ m.worked(200);
+ }
+
+ for (Map.Entry<Repository, DirCacheEditor> e : edits.entrySet()) {
+ final Repository db = e.getKey();
+ final DirCacheEditor editor = e.getValue();
+ m.setTaskName("Writing index for " + db.getDirectory());
+ editor.commit();
+ }
+ } catch (RuntimeException e) {
+ throw Activator.error(CoreText.UntrackOperation_failed, e);
+ } catch (IOException e) {
+ throw Activator.error(CoreText.UntrackOperation_failed, e);
+ } finally {
+ for (final RepositoryMapping rm : mappings.keySet())
+ rm.fireRepositoryChanged();
+ edits.clear();
+ mappings.clear();
+ m.done();
+ }
+ }
+
+ private void remove(final IResource path) throws CoreException {
+ final IProject proj = path.getProject();
+ final GitProjectData pd = GitProjectData.get(proj);
+ if (pd == null)
+ return;
+ final RepositoryMapping rm = pd.getRepositoryMapping(path);
+ if (rm == null)
+ return;
+ final Repository db = rm.getRepository();
+
+ DirCacheEditor e = edits.get(db);
+ if (e == null) {
+ try {
+ e = DirCache.lock(db).editor();
+ } catch (IOException err) {
+ throw Activator.error(CoreText.UntrackOperation_failed, err);
+ }
+ edits.put(db, e);
+ mappings.put(rm, rm);
+ }
+
+ if (path instanceof IContainer)
+ e.add(new DirCacheEditor.DeleteTree(rm.getRepoRelativePath(path)));
+ else
+ e.add(new DirCacheEditor.DeletePath(rm.getRepoRelativePath(path)));
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/UpdateOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/UpdateOperation.java
new file mode 100644
index 000000000..1120da993
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/UpdateOperation.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.op;
+
+import java.util.Collection;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.internal.UpdateJob;
+
+/**
+ * Updates the Git index for the selected resources. Only tracked resources
+ * are updated.
+ * <p>
+ * Accepts a collection of resources (files and/or directories) whose content
+ * should be updated in the corresponding Git repositories. Resources in the
+ * collection can be associated with multiple repositories.
+ * </p>
+ */
+public class UpdateOperation implements IWorkspaceRunnable {
+ private final Collection rsrcList;
+
+ /**
+ * Create a new operation to update files/folders.
+ *
+ * @param rsrcs
+ * collection of {@link IResource}s which should be added to the
+ * relevant Git repositories.
+ */
+ public UpdateOperation(final Collection rsrcs) {
+ rsrcList = rsrcs;
+ }
+
+ public void run(IProgressMonitor m) throws CoreException {
+ new UpdateJob(rsrcList).schedule();
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/GitProjectData.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/GitProjectData.java
new file mode 100644
index 000000000..32ac2f0fe
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/GitProjectData.java
@@ -0,0 +1,491 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.project;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+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.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.egit.core.CoreText;
+import org.eclipse.egit.core.GitCorePreferences;
+import org.eclipse.egit.core.GitProvider;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.WindowCache;
+import org.eclipse.jgit.lib.WindowCacheConfig;
+
+/**
+ * This class keeps information about how a project is mapped to
+ * a Git repository.
+ */
+public class GitProjectData {
+ private static final Map<IProject, GitProjectData> projectDataCache = new HashMap<IProject, GitProjectData>();
+
+ private static final Map<File, WeakReference> repositoryCache = new HashMap<File, WeakReference>();
+
+ private static Set<RepositoryChangeListener> repositoryChangeListeners = new HashSet<RepositoryChangeListener>();
+
+ @SuppressWarnings("synthetic-access")
+ private static final IResourceChangeListener rcl = new RCL();
+
+ private static class RCL implements IResourceChangeListener {
+ @SuppressWarnings("synthetic-access")
+ public void resourceChanged(final IResourceChangeEvent event) {
+ switch (event.getType()) {
+ case IResourceChangeEvent.PRE_CLOSE:
+ uncache((IProject) event.getResource());
+ break;
+ case IResourceChangeEvent.PRE_DELETE:
+ delete((IProject) event.getResource());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private static QualifiedName MAPPING_KEY = new QualifiedName(
+ GitProjectData.class.getName(), "RepositoryMapping");
+
+ /**
+ * Start listening for resource changes.
+ *
+ * @param includeChange true to listen to content changes
+ */
+ public static void attachToWorkspace(final boolean includeChange) {
+ trace("attachToWorkspace - addResourceChangeListener");
+ ResourcesPlugin.getWorkspace().addResourceChangeListener(
+ rcl,
+ (includeChange ? IResourceChangeEvent.POST_CHANGE : 0)
+ | IResourceChangeEvent.PRE_CLOSE
+ | IResourceChangeEvent.PRE_DELETE);
+ }
+
+ /**
+ * Stop listening to resource changes
+ */
+ public static void detachFromWorkspace() {
+ trace("detachFromWorkspace - removeResourceChangeListener");
+ ResourcesPlugin.getWorkspace().removeResourceChangeListener(rcl);
+ }
+
+ /**
+ * Register a new listener for repository modification events.
+ * <p>
+ * This is a no-op if <code>objectThatCares</code> has already been
+ * registered.
+ * </p>
+ *
+ * @param objectThatCares
+ * the new listener to register. Must not be null.
+ */
+ public static synchronized void addRepositoryChangeListener(
+ final RepositoryChangeListener objectThatCares) {
+ if (objectThatCares == null)
+ throw new NullPointerException();
+ repositoryChangeListeners.add(objectThatCares);
+ }
+
+ /**
+ * Remove a registered {@link RepositoryChangeListener}
+ *
+ * @param objectThatCares
+ * The listener to remove
+ */
+ public static synchronized void removeRepositoryChangeListener(
+ final RepositoryChangeListener objectThatCares) {
+ repositoryChangeListeners.remove(objectThatCares);
+ }
+
+ /**
+ * Notify registered {@link RepositoryChangeListener}s of a change.
+ *
+ * @param which
+ * the repository which has had changes occur within it.
+ */
+ static void fireRepositoryChanged(final RepositoryMapping which) {
+ for (RepositoryChangeListener listener : getRepositoryChangeListeners())
+ listener.repositoryChanged(which);
+ }
+
+ /**
+ * Get a copy of the current set of repository change listeners
+ * <p>
+ * The array has no references, so is safe for iteration and modification
+ *
+ * @return a copy of the current repository change listeners
+ */
+ private static synchronized RepositoryChangeListener[] getRepositoryChangeListeners() {
+ return repositoryChangeListeners
+ .toArray(new RepositoryChangeListener[repositoryChangeListeners
+ .size()]);
+ }
+
+ /**
+ * @param p
+ * @return {@link GitProjectData} for the specified project
+ */
+ public synchronized static GitProjectData get(final IProject p) {
+ try {
+ GitProjectData d = lookup(p);
+ if (d == null
+ && RepositoryProvider.getProvider(p) instanceof GitProvider) {
+ d = new GitProjectData(p).load();
+ cache(p, d);
+ }
+ return d;
+ } catch (IOException err) {
+ Activator.logError(CoreText.GitProjectData_missing, err);
+ return null;
+ }
+ }
+
+ /**
+ * Drop the Eclipse project from our association of projects/repositories
+ *
+ * @param p Eclipse project
+ */
+ public static void delete(final IProject p) {
+ trace("delete(" + p.getName() + ")");
+ GitProjectData d = lookup(p);
+ if (d == null) {
+ try {
+ d = new GitProjectData(p).load();
+ } catch (IOException ioe) {
+ d = new GitProjectData(p);
+ }
+ }
+ d.delete();
+ }
+
+ static void trace(final String m) {
+ Activator.trace("(GitProjectData) " + m);
+ }
+
+ private synchronized static void cache(final IProject p,
+ final GitProjectData d) {
+ projectDataCache.put(p, d);
+ }
+
+ private synchronized static void uncache(final IProject p) {
+ if (projectDataCache.remove(p) != null) {
+ trace("uncacheDataFor(" + p.getName() + ")");
+ }
+ }
+
+ private synchronized static GitProjectData lookup(final IProject p) {
+ return projectDataCache.get(p);
+ }
+
+ private synchronized static Repository lookupRepository(final File gitDir)
+ throws IOException {
+ final Iterator i = repositoryCache.entrySet().iterator();
+ while (i.hasNext()) {
+ final Map.Entry e = (Map.Entry) i.next();
+ if (((Reference) e.getValue()).get() == null) {
+ i.remove();
+ }
+ }
+
+ final Reference r = repositoryCache.get(gitDir);
+ Repository d = r != null ? (Repository) r.get() : null;
+ if (d == null) {
+ d = new Repository(gitDir);
+ repositoryCache.put(gitDir, new WeakReference<Repository>(d));
+ }
+ return d;
+ }
+
+ /**
+ * Update the settings for the global window cache of the workspace.
+ */
+ public static void reconfigureWindowCache() {
+ final WindowCacheConfig c = new WindowCacheConfig();
+ Preferences p = Activator.getDefault().getPluginPreferences();
+ c.setPackedGitLimit(p.getInt(GitCorePreferences.core_packedGitLimit));
+ c.setPackedGitWindowSize(p.getInt(GitCorePreferences.core_packedGitWindowSize));
+ c.setPackedGitMMAP(p.getBoolean(GitCorePreferences.core_packedGitMMAP));
+ c.setDeltaBaseCacheLimit(p.getInt(GitCorePreferences.core_deltaBaseCacheLimit));
+ WindowCache.reconfigure(c);
+ }
+
+ private final IProject project;
+
+ private final Collection<RepositoryMapping> mappings = new ArrayList<RepositoryMapping>();
+
+ private final Set<IResource> protectedResources = new HashSet<IResource>();
+
+ /**
+ * Construct a {@link GitProjectData} for the mapping
+ * of a project.
+ *
+ * @param p Eclipse project
+ */
+ public GitProjectData(final IProject p) {
+ project = p;
+ }
+
+ /**
+ * @return the Eclipse project mapped through this resource.
+ */
+ public IProject getProject() {
+ return project;
+ }
+
+ /**
+ * TODO: is this right?
+ *
+ * @param newMappings
+ */
+ public void setRepositoryMappings(final Collection<RepositoryMapping> newMappings) {
+ mappings.clear();
+ mappings.addAll(newMappings);
+ remapAll();
+ }
+
+ /**
+ * Hide our private parts from the navigators other browsers.
+ *
+ * @throws CoreException
+ */
+ public void markTeamPrivateResources() throws CoreException {
+ for (final Object rmObj : mappings) {
+ final RepositoryMapping rm = (RepositoryMapping)rmObj;
+ final IContainer c = rm.getContainer();
+ if (c == null)
+ continue; // Not fully mapped yet?
+
+ final IResource dotGit = c.findMember(".git");
+ if (dotGit != null) {
+ try {
+ final Repository r = rm.getRepository();
+ final File dotGitDir = dotGit.getLocation().toFile()
+ .getCanonicalFile();
+ if (dotGitDir.equals(r.getDirectory())) {
+ trace("teamPrivate " + dotGit);
+ dotGit.setTeamPrivateMember(true);
+ }
+ } catch (IOException err) {
+ throw Activator.error(CoreText.Error_CanonicalFile, err);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param f
+ * @return true if a resource is protected in this repository
+ */
+ public boolean isProtected(final IResource f) {
+ return protectedResources.contains(f);
+ }
+
+ /**
+ * @param r any workbench resource contained within this project.
+ * @return the mapping for the specified project
+ */
+ public RepositoryMapping getRepositoryMapping(IResource r) {
+ try {
+ for (; r != null; r = r.getParent()) {
+ final RepositoryMapping m;
+
+ if (!r.isAccessible())
+ continue;
+ m = (RepositoryMapping) r.getSessionProperty(MAPPING_KEY);
+ if (m != null)
+ return m;
+ }
+ } catch (CoreException err) {
+ Activator.logError("Failed finding RepositoryMapping", err);
+ }
+ return null;
+ }
+
+ private void delete() {
+ final File dir = propertyFile().getParentFile();
+ final File[] todel = dir.listFiles();
+ if (todel != null) {
+ for (int k = 0; k < todel.length; k++) {
+ if (todel[k].isFile()) {
+ todel[k].delete();
+ }
+ }
+ }
+ dir.delete();
+ trace("deleteDataFor(" + getProject().getName() + ")");
+ uncache(getProject());
+ }
+
+ /**
+ * Store information about the repository connection in the workspace
+ *
+ * @throws CoreException
+ */
+ public void store() throws CoreException {
+ final File dat = propertyFile();
+ final File tmp;
+ boolean ok = false;
+
+ try {
+ trace("save " + dat);
+ tmp = File.createTempFile("gpd_", ".prop", dat.getParentFile());
+ final FileOutputStream o = new FileOutputStream(tmp);
+ try {
+ final Properties p = new Properties();
+ final Iterator i = mappings.iterator();
+ while (i.hasNext()) {
+ ((RepositoryMapping) i.next()).store(p);
+ }
+ p.store(o, "GitProjectData");
+ ok = true;
+ } finally {
+ o.close();
+ if (!ok) {
+ tmp.delete();
+ }
+ }
+ } catch (IOException ioe) {
+ throw Activator.error(NLS.bind(CoreText.GitProjectData_saveFailed,
+ dat), ioe);
+ }
+
+ dat.delete();
+ if (!tmp.renameTo(dat)) {
+ tmp.delete();
+ throw Activator.error(NLS.bind(CoreText.GitProjectData_saveFailed,
+ dat), null);
+ }
+ }
+
+ private File propertyFile() {
+ return new File(getProject()
+ .getWorkingLocation(Activator.getPluginId()).toFile(),
+ "GitProjectData.properties");
+ }
+
+ private GitProjectData load() throws IOException {
+ final File dat = propertyFile();
+ trace("load " + dat);
+
+ final FileInputStream o = new FileInputStream(dat);
+ try {
+ final Properties p = new Properties();
+ p.load(o);
+
+ mappings.clear();
+ final Iterator keyItr = p.keySet().iterator();
+ while (keyItr.hasNext()) {
+ final String key = keyItr.next().toString();
+ if (RepositoryMapping.isInitialKey(key)) {
+ mappings.add(new RepositoryMapping(p, key));
+ }
+ }
+ } finally {
+ o.close();
+ }
+
+ remapAll();
+ return this;
+ }
+
+ private void remapAll() {
+ protectedResources.clear();
+ final Iterator i = mappings.iterator();
+ while (i.hasNext()) {
+ map((RepositoryMapping) i.next());
+ }
+ }
+
+ private void map(final RepositoryMapping m) {
+ final IResource r;
+ final File git;
+ final IResource dotGit;
+ IContainer c = null;
+
+ m.clear();
+ r = getProject().findMember(m.getContainerPath());
+ if (r instanceof IContainer) {
+ c = (IContainer) r;
+ } else {
+ c = (IContainer) r.getAdapter(IContainer.class);
+ }
+
+ if (c == null) {
+ Activator.logError(CoreText.GitProjectData_mappedResourceGone,
+ new FileNotFoundException(m.getContainerPath().toString()));
+ m.clear();
+ return;
+ }
+ m.setContainer(c);
+
+ git = c.getLocation().append(m.getGitDirPath()).toFile();
+ if (!git.isDirectory() || !new File(git, "config").isFile()) {
+ Activator.logError(CoreText.GitProjectData_mappedResourceGone,
+ new FileNotFoundException(m.getContainerPath().toString()));
+ m.clear();
+ return;
+ }
+
+ try {
+ m.setRepository(lookupRepository(git));
+ } catch (IOException ioe) {
+ Activator.logError(CoreText.GitProjectData_mappedResourceGone,
+ new FileNotFoundException(m.getContainerPath().toString()));
+ m.clear();
+ return;
+ }
+
+ m.fireRepositoryChanged();
+
+ trace("map " + c + " -> " + m.getRepository());
+ try {
+ c.setSessionProperty(MAPPING_KEY, m);
+ } catch (CoreException err) {
+ Activator.logError("Failed to cache RepositoryMapping", err);
+ }
+
+ dotGit = c.findMember(".git");
+ if (dotGit != null && dotGit.getLocation().toFile().equals(git)) {
+ protect(dotGit);
+ }
+ }
+
+ private void protect(IResource c) {
+ while (c != null && !c.equals(getProject())) {
+ trace("protect " + c);
+ protectedResources.add(c);
+ c = c.getParent();
+ }
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryChangeListener.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryChangeListener.java
new file mode 100644
index 000000000..401400a5e
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryChangeListener.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.project;
+
+/**
+ * Receives notification of a repository change event.
+ * <p>
+ * A change listener may be called from any thread, especially background job
+ * threads, but also from the UI thread. Implementors are encouraged to complete
+ * quickly, and make arrange for their tasks to run on the UI event thread if
+ * necessary.
+ * </p>
+ */
+public interface RepositoryChangeListener {
+ /**
+ * Invoked when a repository has had some or all of its contents change.
+ *
+ * @param which
+ * the affected repository. Never null.
+ */
+ public void repositoryChanged(RepositoryMapping which);
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryFinder.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryFinder.java
new file mode 100644
index 000000000..fbd9addc3
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryFinder.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.project;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+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.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.egit.core.CoreText;
+
+/**
+ * Searches for existing Git repositories associated with a project's files.
+ * <p>
+ * This finder algorithm searches a project's contained files to see if any of
+ * them are located within the working directory of an existing Git repository.
+ * The finder searches through linked resources, as the EGit core is capable of
+ * dealing with linked directories spanning multiple repositories in the same
+ * project.
+ * </p>
+ * <p>
+ * The search algorithm is exhaustive, it will find all matching repositories.
+ * For the project itself as well as for each linked container within the
+ * project it scans down the local filesystem trees to locate any Git
+ * repositories which may be found there. It also scans up the local filesystem
+ * tree to locate any Git repository which may be outside of Eclipse's
+ * workspace-view of the world, but which contains the project or a linked
+ * resource within the project. In short, if there is a Git repository
+ * associated, it finds it.
+ * </p>
+ */
+public class RepositoryFinder {
+ private final IProject proj;
+
+ private final Collection<RepositoryMapping> results = new ArrayList<RepositoryMapping>();
+
+ /**
+ * Create a new finder to locate Git repositories for a project.
+ *
+ * @param p
+ * the project this new finder should locate the existing Git
+ * repositories of.
+ */
+ public RepositoryFinder(final IProject p) {
+ proj = p;
+ }
+
+ /**
+ * Run the search algorithm.
+ *
+ * @param m
+ * a progress monitor to report feedback to; may be null.
+ * @return all found {@link RepositoryMapping} instances associated with the
+ * project supplied to this instance's constructor.
+ * @throws CoreException
+ * Eclipse was unable to access its workspace, and threw up on
+ * us. We're throwing it back at the caller.
+ */
+ public Collection<RepositoryMapping> find(IProgressMonitor m) throws CoreException {
+ if (m == null) {
+ m = new NullProgressMonitor();
+ }
+ find(m, proj);
+ return results;
+ }
+
+ private void find(final IProgressMonitor m, final IContainer c)
+ throws CoreException {
+ final IPath loc = c.getLocation();
+
+ m.beginTask("", 101);
+ m.subTask(CoreText.RepositoryFinder_finding);
+ try {
+ if (loc != null) {
+ final File fsLoc = loc.toFile();
+ final File ownCfg = configFor(fsLoc);
+ final IResource[] children;
+
+ if (ownCfg.isFile()) {
+ register(c, ownCfg.getParentFile());
+ } else if (c.isLinked() || c instanceof IProject) {
+ File p = fsLoc.getParentFile();
+ while (p != null) {
+ final File pCfg = configFor(p);
+ if (pCfg.isFile()) {
+ register(c, pCfg.getParentFile());
+ break;
+ }
+ p = p.getParentFile();
+ }
+ }
+ m.worked(1);
+
+ children = c.members();
+ if (children != null && children.length > 0) {
+ final int scale = 100 / children.length;
+ for (int k = 0; k < children.length; k++) {
+ final IResource o = children[k];
+ if (o instanceof IContainer
+ && !o.getName().equals(".git")) {
+ find(new SubProgressMonitor(m, scale),
+ (IContainer) o);
+ } else {
+ m.worked(scale);
+ }
+ }
+ }
+ }
+ } finally {
+ m.done();
+ }
+ }
+
+ private File configFor(final File fsLoc) {
+ return new File(new File(fsLoc, ".git"), "config");
+ }
+
+ private void register(final IContainer c, final File gitdir) {
+ File f;
+ try {
+ f = gitdir.getCanonicalFile();
+ } catch (IOException ioe) {
+ f = gitdir.getAbsoluteFile();
+ }
+ results.add(new RepositoryMapping(c, f));
+ }
+}
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java
new file mode 100644
index 000000000..18238cc83
--- /dev/null
+++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/project/RepositoryMapping.java
@@ -0,0 +1,248 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Shunichi Fuji <palglowr@gmail.com>
+ * Copyright (C) 2008, Google Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.core.project;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Properties;
+
+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.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.egit.core.GitProvider;
+import org.eclipse.team.core.RepositoryProvider;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.lib.TreeEntry;
+import org.eclipse.jgit.lib.GitIndex.Entry;
+
+/**
+ * This class keeps track
+ */
+public class RepositoryMapping {
+ static boolean isInitialKey(final String key) {
+ return key.endsWith(".gitdir");
+ }
+
+ private final String containerPath;
+
+ private final String gitdirPath;
+
+ private Repository db;
+
+ private String workdirPrefix;
+
+ private IContainer container;
+
+ /**
+ * Construct a {@link RepositoryMapping} for a previously connected project.
+ *
+ * @param p TODO
+ * @param initialKey TODO
+ */
+ public RepositoryMapping(final Properties p, final String initialKey) {
+ final int dot = initialKey.lastIndexOf('.');
+
+ containerPath = initialKey.substring(0, dot);
+ gitdirPath = p.getProperty(initialKey);
+ }
+
+ /**
+ * Construct a {@link RepositoryMapping} for previously
+ * unknown project.
+ *
+ * @param mappedContainer
+ * @param gitDir
+ */
+ public RepositoryMapping(final IContainer mappedContainer, final File gitDir) {
+ final IPath cLoc = mappedContainer.getLocation()
+ .removeTrailingSeparator();
+ final IPath gLoc = Path.fromOSString(gitDir.getAbsolutePath())
+ .removeTrailingSeparator();
+ final IPath gLocParent = gLoc.removeLastSegments(1);
+ String p;
+ int cnt;
+
+ container = mappedContainer;
+ containerPath = container.getProjectRelativePath().toPortableString();
+
+ if (cLoc.isPrefixOf(gLoc)) {
+ gitdirPath = gLoc.removeFirstSegments(
+ gLoc.matchingFirstSegments(cLoc)).toPortableString();
+ } else if (gLocParent.isPrefixOf(cLoc)) {
+ cnt = cLoc.segmentCount() - cLoc.matchingFirstSegments(gLocParent);
+ p = "";
+ while (cnt-- > 0) {
+ p += "../";
+ }
+ p += gLoc.segment(gLoc.segmentCount() - 1);
+ gitdirPath = p;
+ } else {
+ gitdirPath = gLoc.toPortableString();
+ }
+ }
+
+ IPath getContainerPath() {
+ return Path.fromPortableString(containerPath);
+ }
+
+ IPath getGitDirPath() {
+ return Path.fromPortableString(gitdirPath);
+ }
+
+ /**
+ * @return the workdir file, i.e. where the files are checked out
+ */
+ public File getWorkDir() {
+ return getRepository().getWorkDir();
+ }
+
+ synchronized void clear() {
+ db = null;
+ workdirPrefix = null;
+ container = null;
+ }
+
+ /**
+ * @return a reference to the repository object handled by this mapping
+ */
+ public synchronized Repository getRepository() {
+ return db;
+ }
+
+ synchronized void setRepository(final Repository r) {
+ db = r;
+
+ try {
+ workdirPrefix = getWorkDir().getCanonicalPath();
+ } catch (IOException err) {
+ workdirPrefix = getWorkDir().getAbsolutePath();
+ }
+ workdirPrefix = workdirPrefix.replace('\\', '/');
+ if (!workdirPrefix.endsWith("/"))
+ workdirPrefix += "/";
+ }
+
+ /**
+ * @return the mapped container (currently project)
+ */
+ public synchronized IContainer getContainer() {
+ return container;
+ }
+
+ synchronized void setContainer(final IContainer c) {
+ container = c;
+ }
+
+ /**
+ * Notify registered {@link RepositoryChangeListener}s of a change.
+ *
+ * @see GitProjectData#addRepositoryChangeListener(RepositoryChangeListener)
+ */
+ public void fireRepositoryChanged() {
+ GitProjectData.fireRepositoryChanged(this);
+ }
+
+ synchronized void store(final Properties p) {
+ p.setProperty(containerPath + ".gitdir", gitdirPath);
+ }
+
+ public String toString() {
+ return "RepositoryMapping[" + containerPath + " -> " + gitdirPath + "]";
+ }
+
+ /**
+ * Check whether a resource has been changed relative to the checked out
+ * version. Content is assumed changed by this routine if the resource's
+ * modification time differs from what is recorded in the index, but the
+ * real content hasn't changed. The reason is performance.
+ *
+ * @param rsrc
+ * @return true if a resource differs in the workdir or index relative to
+ * HEAD
+ *
+ * @throws IOException
+ * @throws UnsupportedEncodingException
+ */
+ public boolean isResourceChanged(IResource rsrc) throws IOException, UnsupportedEncodingException {
+ Repository repository = getRepository();
+ GitIndex index = repository.getIndex();
+ String repoRelativePath = getRepoRelativePath(rsrc);
+ Tree headTree = repository.mapTree(Constants.HEAD);
+ TreeEntry blob = headTree!=null ? headTree.findBlobMember(repoRelativePath) : null;
+ Entry entry = index.getEntry(repoRelativePath);
+ if (rsrc instanceof IFile && entry == null && blob == null)
+ return false;
+ if (entry == null)
+ return true; // flags new resources as changes
+ if (blob == null)
+ return true; // added in index
+ boolean hashesDiffer = !entry.getObjectId().equals(blob.getId());
+ return hashesDiffer || entry.isModified(getWorkDir());
+ }
+
+ /**
+ * @param rsrc
+ * @return the path relative to the Git repository, including base name.
+ */
+ public String getRepoRelativePath(final IResource rsrc) {
+ // We should only be called for resources that are actually
+ // in this repository, so we can safely assume that their
+ // path prefix matches workdirPrefix. Testing that here is
+ // rather expensive so we don't bother.
+ //
+ final int pfxLen = workdirPrefix.length();
+ final String p = rsrc.getLocation().toString();
+ final int pLen = p.length();
+ if (pLen > pfxLen)
+ return p.substring(pfxLen);
+ else if (p.length() == pfxLen - 1)
+ return "";
+ return null;
+ }
+
+ /**
+ * Get the repository mapping for a resource
+ *
+ * @param resource
+ * @return the RepositoryMapping for this resource,
+ * or null for non GitProvider.
+ */
+ public static RepositoryMapping getMapping(final IResource resource) {
+ final IProject project = resource.getProject();
+ if (project == null)
+ return null;
+
+ final RepositoryProvider rp = RepositoryProvider.getProvider(project);
+ if (!(rp instanceof GitProvider))
+ return null;
+
+ if (((GitProvider)rp).getData() == null)
+ return null;
+
+ return ((GitProvider)rp).getData().getRepositoryMapping(resource);
+ }
+
+ /**
+ * @return the name of the .git directory
+ */
+ public String getGitDir() {
+ return gitdirPath;
+ }
+}
diff --git a/org.eclipse.egit.ui/.classpath b/org.eclipse.egit.ui/.classpath
new file mode 100644
index 000000000..304e86186
--- /dev/null
+++ b/org.eclipse.egit.ui/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.egit.ui/.gitignore b/org.eclipse.egit.ui/.gitignore
new file mode 100644
index 000000000..ba077a403
--- /dev/null
+++ b/org.eclipse.egit.ui/.gitignore
@@ -0,0 +1 @@
+bin
diff --git a/org.eclipse.egit.ui/.options b/org.eclipse.egit.ui/.options
new file mode 100644
index 000000000..d18ab4865
--- /dev/null
+++ b/org.eclipse.egit.ui/.options
@@ -0,0 +1 @@
+org.eclipse.egit.ui/trace/verbose = false
diff --git a/org.eclipse.egit.ui/.project b/org.eclipse.egit.ui/.project
new file mode 100644
index 000000000..d97ce5220
--- /dev/null
+++ b/org.eclipse.egit.ui/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.egit.ui</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.jem.beaninfo.BeanInfoNature</nature>
+ </natures>
+</projectDescription>
diff --git a/org.eclipse.egit.ui/.settings/org.eclipse.core.resources.prefs b/org.eclipse.egit.ui/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 000000000..2f242b310
--- /dev/null
+++ b/org.eclipse.egit.ui/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:47:19 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.egit.ui/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.egit.ui/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 000000000..d1478c619
--- /dev/null
+++ b/org.eclipse.egit.ui/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:54:29 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.egit.ui/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.egit.ui/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..b52927e3d
--- /dev/null
+++ b/org.eclipse.egit.ui/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,328 @@
+#Sun Jun 14 18:21:07 CEST 2009
+eclipse.preferences.version=1
+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.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=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=warning
+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=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=error
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
+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.uncheckedTypeOperation=warning
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error
+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=error
+org.eclipse.jdt.core.compiler.problem.unusedLabel=error
+org.eclipse.jdt.core.compiler.problem.unusedLocal=error
+org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
+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=error
+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.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=1
+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_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=false
+org.eclipse.jdt.core.formatter.comment.format_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_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=80
+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=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_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.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=80
+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
diff --git a/org.eclipse.egit.ui/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.egit.ui/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 000000000..709a44074
--- /dev/null
+++ b/org.eclipse.egit.ui/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,9 @@
+#Wed May 09 00:20:24 CEST 2007
+eclipse.preferences.version=1
+formatter_profile=_JGit
+formatter_settings_version=10
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=java;javax;org;com;
+org.eclipse.jdt.ui.ondemandthreshold=99
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
diff --git a/org.eclipse.egit.ui/META-INF/MANIFEST.MF b/org.eclipse.egit.ui/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..3af14b57d
--- /dev/null
+++ b/org.eclipse.egit.ui/META-INF/MANIFEST.MF
@@ -0,0 +1,27 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %plugin_name
+Bundle-SymbolicName: org.eclipse.egit.ui;singleton:=true
+Bundle-Version: 0.5.0.qualifier
+Bundle-Activator: org.eclipse.egit.ui.Activator
+Bundle-Vendor: %provider_name
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.core.filesystem,
+ org.eclipse.core.net,
+ org.eclipse.ui,
+ org.eclipse.team.core;bundle-version="3.4.0",
+ org.eclipse.team.ui,
+ org.eclipse.jface.text,
+ org.eclipse.ui.ide,
+ org.eclipse.ui.workbench.texteditor,
+ org.eclipse.compare,
+ org.eclipse.jgit,
+ org.eclipse.egit.core,
+ org.eclipse.ui.ide,
+ org.eclipse.jsch.ui;bundle-version="1.1.100"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Import-Package: org.eclipse.jsch.core,
+ org.eclipse.jsch.internal.core
diff --git a/org.eclipse.egit.ui/build.properties b/org.eclipse.egit.ui/build.properties
new file mode 100644
index 000000000..6b4afb7a5
--- /dev/null
+++ b/org.eclipse.egit.ui/build.properties
@@ -0,0 +1,7 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ icons/,\
+ plugin.properties
diff --git a/org.eclipse.egit.ui/icons/checkboxes/disabled_checked.gif b/org.eclipse.egit.ui/icons/checkboxes/disabled_checked.gif
new file mode 100644
index 000000000..47b9e321d
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/checkboxes/disabled_checked.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/checkboxes/disabled_unchecked.gif b/org.eclipse.egit.ui/icons/checkboxes/disabled_unchecked.gif
new file mode 100644
index 000000000..d6a2cda06
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/checkboxes/disabled_unchecked.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/checkboxes/enabled_checked.gif b/org.eclipse.egit.ui/icons/checkboxes/enabled_checked.gif
new file mode 100644
index 000000000..252f76221
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/checkboxes/enabled_checked.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/checkboxes/enabled_unchecked.gif b/org.eclipse.egit.ui/icons/checkboxes/enabled_unchecked.gif
new file mode 100644
index 000000000..4399d9105
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/checkboxes/enabled_unchecked.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/add.gif b/org.eclipse.egit.ui/icons/elcl16/add.gif
new file mode 100644
index 000000000..252d7ebcb
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/add.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/author.gif b/org.eclipse.egit.ui/icons/elcl16/author.gif
new file mode 100644
index 000000000..c4ae8cda9
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/author.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/clear.gif b/org.eclipse.egit.ui/icons/elcl16/clear.gif
new file mode 100644
index 000000000..af30a42f8
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/clear.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/comment.gif b/org.eclipse.egit.ui/icons/elcl16/comment.gif
new file mode 100644
index 000000000..0f6e19e60
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/comment.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/commit.gif b/org.eclipse.egit.ui/icons/elcl16/commit.gif
new file mode 100644
index 000000000..38f00288e
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/commit.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/committer.gif b/org.eclipse.egit.ui/icons/elcl16/committer.gif
new file mode 100644
index 000000000..c31e9619e
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/committer.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/delete.gif b/org.eclipse.egit.ui/icons/elcl16/delete.gif
new file mode 100644
index 000000000..b6922ac11
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/delete.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/filterfolder.gif b/org.eclipse.egit.ui/icons/elcl16/filterfolder.gif
new file mode 100644
index 000000000..55843e768
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/filterfolder.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/filterproject.gif b/org.eclipse.egit.ui/icons/elcl16/filterproject.gif
new file mode 100644
index 000000000..a24b94dcf
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/filterproject.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/filterrepo.gif b/org.eclipse.egit.ui/icons/elcl16/filterrepo.gif
new file mode 100644
index 000000000..c1cfa7bed
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/filterrepo.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/find.gif b/org.eclipse.egit.ui/icons/elcl16/find.gif
new file mode 100644
index 000000000..eba31f754
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/find.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/next.gif b/org.eclipse.egit.ui/icons/elcl16/next.gif
new file mode 100644
index 000000000..cd84203b6
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/next.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/previous.gif b/org.eclipse.egit.ui/icons/elcl16/previous.gif
new file mode 100644
index 000000000..a53606bdb
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/previous.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/elcl16/trash.gif b/org.eclipse.egit.ui/icons/elcl16/trash.gif
new file mode 100644
index 000000000..bf961b3e0
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/elcl16/trash.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/etool16/newconnect_wiz.gif b/org.eclipse.egit.ui/icons/etool16/newconnect_wiz.gif
new file mode 100644
index 000000000..d698b00f3
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/etool16/newconnect_wiz.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/obj16/import_obj.gif b/org.eclipse.egit.ui/icons/obj16/import_obj.gif
new file mode 100644
index 000000000..9035f0be3
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/obj16/import_obj.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/ovr/assume_valid.gif b/org.eclipse.egit.ui/icons/ovr/assume_valid.gif
new file mode 100644
index 000000000..b6d7167cb
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/ovr/assume_valid.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/ovr/conflict.gif b/org.eclipse.egit.ui/icons/ovr/conflict.gif
new file mode 100644
index 000000000..fce456a49
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/ovr/conflict.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/ovr/staged.gif b/org.eclipse.egit.ui/icons/ovr/staged.gif
new file mode 100644
index 000000000..dc0b8c016
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/ovr/staged.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/ovr/staged_added.gif b/org.eclipse.egit.ui/icons/ovr/staged_added.gif
new file mode 100644
index 000000000..c65d16a19
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/ovr/staged_added.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/ovr/staged_removed.gif b/org.eclipse.egit.ui/icons/ovr/staged_removed.gif
new file mode 100644
index 000000000..8aaadfb9b
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/ovr/staged_removed.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/ovr/untracked.gif b/org.eclipse.egit.ui/icons/ovr/untracked.gif
new file mode 100644
index 000000000..45ca32060
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/ovr/untracked.gif
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/checkoutd.png b/org.eclipse.egit.ui/icons/toolbar/checkoutd.png
new file mode 100644
index 000000000..1de81619f
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/checkoutd.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/checkoute.png b/org.eclipse.egit.ui/icons/toolbar/checkoute.png
new file mode 100644
index 000000000..2e76612b7
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/checkoute.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/commitd.png b/org.eclipse.egit.ui/icons/toolbar/commitd.png
new file mode 100644
index 000000000..28fd488cd
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/commitd.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/commite.png b/org.eclipse.egit.ui/icons/toolbar/commite.png
new file mode 100644
index 000000000..09f34a23f
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/commite.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/fetchd.png b/org.eclipse.egit.ui/icons/toolbar/fetchd.png
new file mode 100644
index 000000000..4433c543f
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/fetchd.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/fetche.png b/org.eclipse.egit.ui/icons/toolbar/fetche.png
new file mode 100644
index 000000000..0ffeb419e
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/fetche.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/pushd.png b/org.eclipse.egit.ui/icons/toolbar/pushd.png
new file mode 100644
index 000000000..22c3f7bf1
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/pushd.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/pushe.png b/org.eclipse.egit.ui/icons/toolbar/pushe.png
new file mode 100644
index 000000000..1f99f0a70
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/pushe.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/resetd.png b/org.eclipse.egit.ui/icons/toolbar/resetd.png
new file mode 100644
index 000000000..bc7405edb
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/resetd.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/resete.png b/org.eclipse.egit.ui/icons/toolbar/resete.png
new file mode 100644
index 000000000..d65d171a0
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/resete.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/trackd.png b/org.eclipse.egit.ui/icons/toolbar/trackd.png
new file mode 100644
index 000000000..1ae9b5abd
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/trackd.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/toolbar/tracke.png b/org.eclipse.egit.ui/icons/toolbar/tracke.png
new file mode 100644
index 000000000..b06c26581
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/toolbar/tracke.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/wizban/import_wiz.png b/org.eclipse.egit.ui/icons/wizban/import_wiz.png
new file mode 100644
index 000000000..b3207b35f
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/wizban/import_wiz.png
Binary files differ
diff --git a/org.eclipse.egit.ui/icons/wizban/newconnect_wizban.png b/org.eclipse.egit.ui/icons/wizban/newconnect_wizban.png
new file mode 100644
index 000000000..ec9a393fb
--- /dev/null
+++ b/org.eclipse.egit.ui/icons/wizban/newconnect_wizban.png
Binary files differ
diff --git a/org.eclipse.egit.ui/plugin.properties b/org.eclipse.egit.ui/plugin.properties
new file mode 100644
index 000000000..989dbb927
--- /dev/null
+++ b/org.eclipse.egit.ui/plugin.properties
@@ -0,0 +1,79 @@
+###############################################################################
+# Copyright (c) 2005, 2009 Shawn Pearce and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+###############################################################################
+
+plugin_name=Git Team Provider (UI) (Incubation)
+provider_name=eclipse.org
+
+Git=Git
+
+Git_clone_category=Git
+Git_clone_wizard=Git Repository
+Git_clone_description=Clone an existing Git repository.
+
+SharingWizard_name=Git
+GitRemoteQuickDiffProvider_label=A Git Revision
+
+DisconnectAction_label=Disconnect
+DisconnectAction_tooltip=Disconnect the Git team provider.
+
+AssumeUnchangedAction_label=Assume unchanged
+AssumeUnchangedAction_tooltip=Assume selected folders/files are unchanged
+
+TrackAction_label=&Add to Version Control
+TrackAction_tooltip=Track selected files/folders with Git.
+
+UntrackAction_label=&Remove from Version Control
+UntrackAction_tooltip=Stop tracking selected files/folders with Git.
+
+UpdateAction_label=Update Index (Refresh)
+UpdateAction_tooltip=Update Git's index with current version
+
+Decorator_name=Git
+Decorator_description=Shows Git specific information on resources in projects under version control.
+
+CompareWithRevisionAction_label=Compare With Git Revision
+CompareWithRevisionAction_tooltip=Compare With a Git Revision
+
+CompareWithIndexAction_label=Git Index
+CompareWithIndexAction_tooltip=Compare with Git's index version
+
+ShowResourceInHistoryAction_label=Show in Resource History
+ShowResourceInHistoryAction_tooltip=Show selected files in the resource history view.
+
+CommitAction_label=&Commit...
+CommitAction_tooltip=Commit changes to your current branch
+
+ResetAction_label=&Reset To...
+ResetAction_tooltip=Reset the current branch to the same or another commit
+
+BranchAction_label=&Branch...
+BranchAction_tooltip=Switch to another branch
+
+FetchAction_label=&Fetch From...
+FetchAction_tooltip=Fetch from another repository
+
+PushAction_label=&Push To...
+PushAction_tooltip=Push to another repository
+
+GitActions_label=Git
+GitMenu_label=&Git
+
+
+Theme_label=Git
+Theme_CommitGraphNormalFont_label=Commit graph normal font
+Theme_CommitGraphNormalFont_description=This font is used to draw the revision history.
+Theme_CommitGraphHighlightFont_label=Commit graph highlight font
+Theme_CommitGraphHighlightFont_description=This font is used to highlight matching commits in the revision history.
+Theme_CommitMessageFont_label=Commit message font
+Theme_CommitMessageFont_description=This font is used to show a commit message.
+
+GitPreferences_name=Git
+GitPreferences_HistoryPreferencePage_name=History
+GitPreferences_WindowCachePreferencePage_name=Window Cache
+GitPreferences_DecoratorPreferencePage_name=Label Decorations
diff --git a/org.eclipse.egit.ui/plugin.xml b/org.eclipse.egit.ui/plugin.xml
new file mode 100644
index 000000000..032a72e08
--- /dev/null
+++ b/org.eclipse.egit.ui/plugin.xml
@@ -0,0 +1,391 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.0"?>
+<plugin>
+ <extension point="org.eclipse.core.runtime.preferences">
+ <initializer class="org.eclipse.egit.ui.PluginPreferenceInitializer"/>
+ </extension>
+
+ <extension point="org.eclipse.ui.importWizards">
+ <category name="%Git_clone_category"
+ id="org.eclipse.egit.ui.internal.clone.gitclonecategory"/>
+ <wizard name="%Git_clone_wizard"
+ icon="icons/obj16/import_obj.gif"
+ class="org.eclipse.egit.ui.internal.clone.GitCloneWizard"
+ id="org.eclipse.egit.ui.internal.clone.GitCloneWizard"
+ category="org.eclipse.egit.ui.internal.clone.gitclonecategory">
+ <description>%Git_clone_description</description>
+ </wizard>
+ </extension>
+
+ <extension point="org.eclipse.team.ui.configurationWizards">
+ <wizard name="%SharingWizard_name"
+ icon="icons/etool16/newconnect_wiz.gif"
+ class="org.eclipse.egit.ui.internal.sharing.SharingWizard"
+ id="org.eclipse.egit.ui.internal.sharing.SharingWizard">
+ </wizard>
+ </extension>
+
+ <extension point="org.eclipse.ui.popupMenus">
+ <objectContribution id="org.eclipse.egit.ui.projectContributions"
+ objectClass="org.eclipse.core.resources.IProject"
+ adaptable="true">
+ <filter name="projectPersistentProperty"
+ value="org.eclipse.team.core.repository=org.eclipse.egit.core.GitProvider">
+ </filter>
+ <action
+ label="%DisconnectAction_label"
+ tooltip="%DisconnectAction_tooltip"
+ class="org.eclipse.egit.ui.internal.actions.Disconnect"
+ menubarPath="team.main/projectGroup"
+ id="org.eclipse.egit.ui.internal.actions.Disconnect">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.FetchAction"
+ id="org.eclipse.egit.ui.internal.actions.FetchAction"
+ label="%FetchAction_label"
+ menubarPath="team.main/projectGroup"
+ tooltip="%FetchAction_tooltip"/>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.PushAction"
+ id="org.eclipse.egit.ui.internal.actions.PushAction"
+ label="%PushAction_label"
+ menubarPath="team.main/projectGroup"
+ tooltip="%PushAction_tooltip"/>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.ResetAction"
+ id="org.eclipse.egit.ui.internal.actions.ResetAction"
+ label="%ResetAction_label"
+ menubarPath="team.main/projectGroup"
+ tooltip="%ResetAction_tooltip">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.BranchAction"
+ id="org.eclipse.egit.ui.internal.actions.BranchAction"
+ label="%BranchAction_label"
+ menubarPath="team.main/projectGroup"
+ tooltip="%BranchAction_tooltip"/>
+ </objectContribution>
+ <objectContribution
+ adaptable="true"
+ id="org.eclipse.egit.ui.fileFolderContributions"
+ objectClass="org.eclipse.core.resources.IResource">
+ <filter name="projectPersistentProperty"
+ value="org.eclipse.team.core.repository=org.eclipse.egit.core.GitProvider">
+ </filter>
+ <action
+ label="%UntrackAction_label"
+ class="org.eclipse.egit.ui.internal.actions.Untrack"
+ tooltip="%UntrackAction_tooltip"
+ menubarPath="team.main/group1"
+ id="org.eclipse.egit.ui.internal.actions.Untrack"/>
+ <action
+ label="%TrackAction_label"
+ class="org.eclipse.egit.ui.internal.actions.Track"
+ tooltip="%TrackAction_tooltip"
+ menubarPath="team.main/group1"
+ id="org.eclipse.egit.ui.internal.actions.Track"/>
+ <action
+ label="%AssumeUnchangedAction_label"
+ class="org.eclipse.egit.ui.internal.actions.AssumeUnchanged"
+ tooltip="%AssumeUnchangedAction_tooltip"
+ menubarPath="team.main/group1"
+ id="org.eclipse.egit.ui.internal.actions.AssumeUnchanged"/>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.ShowResourceInHistoryAction"
+ id="org.eclipse.egit.ui.internal.actions.ShowResourceInHistoryAction"
+ label="%ShowResourceInHistoryAction_label"
+ menubarPath="team.main/group1"
+ tooltip="%ShowResourceInHistoryAction_tooltip"/>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.Update"
+ id="org.eclipse.egit.ui.internal.actions.Update"
+ label="%UpdateAction_label"
+ menubarPath="team.main/group1"
+ tooltip="%UpdateAction_tooltip"/>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.CommitAction"
+ id="org.eclipse.egit.ui.internal.actions.CommitAction"
+ label="%CommitAction_label"
+ menubarPath="team.main/group1"
+ tooltip="%CommitAction_tooltip"/>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.CompareWithIndexAction"
+ id="org.eclipse.egit.ui.internal.actions.CompareWithIndexAction"
+ label="%CompareWithIndexAction_label"
+ menubarPath="compareWithMenu/gitCompareWithGroup"
+ tooltip="&amp;CompareWithIndexAction_tooltip">
+ </action>
+ </objectContribution>
+ <objectContribution
+ id="org.eclipse.egit.ui.resetto"
+ objectClass="org.eclipse.jgit.revwalk.RevCommit">
+ <action
+ class="org.eclipse.egit.ui.internal.actions.SoftResetToRevisionAction"
+ id="org.eclipse.egit.ui.softresettorevision"
+ label="Soft Reset"
+ menubarPath="additions"
+ enablesFor="1"
+ tooltip="Resets HEAD but not working directory nor index">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.MixedResetToRevisionAction"
+ id="org.eclipse.egit.ui.mixedresettorevision"
+ label="Mixed Reset"
+ menubarPath="additions"
+ enablesFor="1"
+ tooltip="Resets HEAD and index, but not working directory">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.HardResetToRevisionAction"
+ id="org.eclipse.egit.ui.hardresettorevision"
+ label="Hard Reset"
+ menubarPath="additions"
+ enablesFor="1"
+ tooltip="Resets HEAD and index, and working directory (changed in tracked files will be lost)">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.SetQuickdiffBaselineAction"
+ enablesFor="1"
+ id="org.eclipse.egit.ui.setquickdiffbaseline"
+ label="Set as quickdiff baseline"
+ menubarPath="additions">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.ResetQuickdiffBaselineAction"
+ enablesFor="*"
+ id="org.eclipse.egit.ui.resetquickdiffbaseline"
+ label="Reset quickdiff baseline to HEAD"
+ menubarPath="additions">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.ResetQuickdiffBaselineHeadParentAction"
+ enablesFor="*"
+ id="org.eclipse.egit.ui.resetquickdiffheadparentbaseline"
+ label="Reset quickdiff baseline to first parent of HEAD"
+ menubarPath="additions">
+ </action>
+ </objectContribution>
+ </extension>
+
+ <extension
+ point="org.eclipse.core.runtime.adapters">
+ <factory
+ adaptableType="org.eclipse.egit.core.internal.storage.GitFileHistoryProvider"
+ class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory">
+ <adapter
+ type="org.eclipse.team.ui.history.IHistoryPageSource">
+ </adapter>
+ </factory>
+ <factory
+ adaptableType="org.eclipse.core.resources.IResource"
+ class="org.eclipse.egit.ui.internal.factories.GitAdapterFactory">
+ <adapter
+ type="org.eclipse.team.ui.history.IHistoryPageSource">
+ </adapter>
+ </factory>
+ </extension>
+
+ <extension point="org.eclipse.ui.preferencePages">
+ <page name="%GitPreferences_name"
+ category="org.eclipse.team.ui.TeamPreferences"
+ class="org.eclipse.egit.ui.internal.preferences.GitPreferenceRoot"
+ id="org.eclipse.egit.ui.GitPreferences" />
+
+ <page name="%GitPreferences_HistoryPreferencePage_name"
+ category="org.eclipse.egit.ui.GitPreferences"
+ class="org.eclipse.egit.ui.internal.preferences.HistoryPreferencePage"
+ id="org.eclipse.egit.ui.internal.preferences.HistoryPreferencePage" >
+ <keywordReference
+ id="org.eclipse.egit.ui.keyword.git">
+ </keywordReference>
+ </page>
+ <page name="%GitPreferences_WindowCachePreferencePage_name"
+ category="org.eclipse.egit.ui.GitPreferences"
+ class="org.eclipse.egit.ui.internal.preferences.WindowCachePreferencePage"
+ id="org.eclipse.egit.ui.internal.preferences.WindowCachePreferencePage" >
+ <keywordReference
+ id="org.eclipse.egit.ui.keyword.git">
+ </keywordReference>
+ </page>
+ <page name="%GitPreferences_DecoratorPreferencePage_name"
+ category="org.eclipse.egit.ui.GitPreferences"
+ class="org.eclipse.egit.ui.internal.preferences.GitDecoratorPreferencePage"
+ id="org.eclipse.egit.ui.internal.preferences.GitDecoratorPreferencePage" >
+ <keywordReference
+ id="org.eclipse.egit.ui.keyword.git">
+ </keywordReference>
+ </page>
+ </extension>
+
+ <extension point="org.eclipse.ui.propertyPages">
+ <page
+ name="%Git"
+ class="org.eclipse.egit.ui.internal.preferences.GitProjectPropertyPage"
+ id="org.eclipse.egit.ui.preferences.GitProjectPropertyPage">
+ <enabledWhen>
+ <adapt type="org.eclipse.core.resources.IProject">
+ <test
+ property="projectPersistentProperty org.eclipse.team.core.repository" value="org.eclipse.egit.core.GitProvider">
+ </test>
+ </adapt>
+ </enabledWhen>
+ <filter
+ name="projectPersistentProperty"
+ value="org.eclipse.team.core.repository=org.eclipse.egit.core.GitProvider">
+ </filter>
+ </page>
+ </extension>
+
+ <extension point="org.eclipse.ui.keywords">
+ <keyword
+ id="org.eclipse.egit.ui.keyword.git"
+ label="git">
+ </keyword>
+ </extension>
+
+ <extension point="org.eclipse.ui.decorators">
+ <decorator
+ lightweight="true"
+ adaptable="true"
+ label="%Decorator_name"
+ class="org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator"
+ state="true"
+ location="BOTTOM_RIGHT"
+ id="org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator">
+ <enablement>
+ <objectClass name="org.eclipse.core.resources.IResource"/>
+ </enablement>
+ <description>
+ %Decorator_description
+ </description>
+ </decorator>
+ </extension>
+
+ <extension point="org.eclipse.ui.themes">
+ <themeElementCategory
+ id="org.eclipse.egit.ui.GitTheme"
+ label="%Theme_label"/>
+ <fontDefinition
+ id="org.eclipse.egit.ui.CommitGraphNormalFont"
+ categoryId="org.eclipse.egit.ui.GitTheme"
+ label="%Theme_CommitGraphNormalFont_label"
+ defaultsTo="org.eclipse.jface.dialogfont">
+ <description>
+ %Theme_CommitGraphNormalFont_description
+ </description>
+ </fontDefinition>
+ <fontDefinition
+ id="org.eclipse.egit.ui.CommitGraphHighlightFont"
+ categoryId="org.eclipse.egit.ui.GitTheme"
+ label="%Theme_CommitGraphHighlightFont_label"
+ defaultsTo="org.eclipse.jface.dialogfont">
+ <description>
+ %Theme_CommitGraphHighlightFont_description
+ </description>
+ </fontDefinition>
+ <fontDefinition
+ id="org.eclipse.egit.ui.CommitMessageFont"
+ categoryId="org.eclipse.egit.ui.GitTheme"
+ label="%Theme_CommitMessageFont_label"
+ defaultsTo="org.eclipse.jface.textfont">
+ <description>
+ %Theme_CommitMessageFont_description
+ </description>
+ </fontDefinition>
+ </extension>
+
+<!-- ********** QuickDiff text editor support ************** -->
+ <extension
+ point="org.eclipse.ui.workbench.texteditor.quickDiffReferenceProvider">
+ <referenceprovider
+ label="%GitRemoteQuickDiffProvider_label"
+ class="org.eclipse.egit.ui.internal.decorators.GitQuickDiffProvider"
+ id="org.eclipse.egit.ui.internal.decorators.GitQuickDiffProvider">
+ </referenceprovider>
+ </extension>
+ <extension
+ point="org.eclipse.ui.actionSets">
+ <actionSet
+ description="Common things to do with Git"
+ id="org.eclipse.egit.ui.gitaction"
+ label="%GitActions_label"
+ visible="false"
+ >
+ <menu
+ id="org.eclipse.egit.ui.gitmenu"
+ label="%GitMenu_label"
+ path="additions"
+ >
+ <separator
+ name="repositoryGroup">
+ </separator>
+ </menu>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.FetchAction"
+ disabledIcon="icons/toolbar/fetchd.png"
+ icon="icons/toolbar/fetche.png"
+ id="org.eclipse.egit.ui.actionfetch"
+ label="%FetchAction_label"
+ menubarPath="org.eclipse.egit.ui.gitmenu/repo"
+ style="push"
+ toolbarPath="org.eclipse.egit.ui"
+ tooltip="%FetchAction_tooltip">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.PushAction"
+ disabledIcon="icons/toolbar/pushd.png"
+ icon="icons/toolbar/pushe.png"
+ id="org.eclipse.egit.ui.actionpush"
+ label="%PushAction_label"
+ menubarPath="org.eclipse.egit.ui.gitmenu/repo"
+ style="push"
+ toolbarPath="org.eclipse.egit.ui"
+ tooltip="%PushAction_tooltip">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.BranchAction"
+ disabledIcon="icons/toolbar/checkoutd.png"
+ icon="icons/toolbar/checkoute.png"
+ id="org.eclipse.egit.ui.actionbranch"
+ label="%BranchAction_label"
+ style="push"
+ menubarPath="org.eclipse.egit.ui.gitmenu/repositoryGroup"
+ toolbarPath="Normal/additions"
+ tooltip="%BranchAction_tooltip">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.CommitAction"
+ disabledIcon="icons/toolbar/commitd.png"
+ icon="icons/toolbar/commite.png"
+ id="org.eclipse.egit.ui.actioncommit"
+ label="%CommitAction_label"
+ style="push"
+ menubarPath="org.eclipse.egit.ui.gitmenu/repositoryGroup"
+ toolbarPath="Normal/additions"
+ tooltip="%CommitAction_tooltip">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.ResetAction"
+ disabledIcon="icons/toolbar/resetd.png"
+ icon="icons/toolbar/resete.png"
+ id="org.eclipse.egit.ui.actionreset"
+ label="%ResetAction_label"
+ style="push"
+ menubarPath="org.eclipse.egit.ui.gitmenu/repositoryGroup"
+ toolbarPath="Normal/additions"
+ tooltip="%ResetAction_tooltip">
+ </action>
+ <action
+ class="org.eclipse.egit.ui.internal.actions.Track"
+ disabledIcon="icons/toolbar/trackd.png"
+ icon="icons/toolbar/tracke.png"
+ id="org.eclipse.egit.ui.trackaction"
+ label="%TrackAction_label"
+ style="push"
+ menubarPath="org.eclipse.egit.ui.gitmenu/repositoryGroup"
+ toolbarPath="Normal/additions"
+ tooltip="%TrackAction_tooltip">
+ </action>
+ </actionSet>
+ </extension>
+</plugin>
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java
new file mode 100644
index 000000000..7d3c652ce
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/Activator.java
@@ -0,0 +1,397 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import java.net.Authenticator;
+import java.net.ProxySelector;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.net.proxy.IProxyService;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+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.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jsch.core.IJSchService;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.eclipse.ui.themes.ITheme;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.eclipse.jgit.lib.IndexChangedEvent;
+import org.eclipse.jgit.lib.RefsChangedEvent;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryListener;
+import org.eclipse.jgit.transport.SshSessionFactory;
+
+/**
+ * This is a plugin singleton mostly controlling logging.
+ */
+public class Activator extends AbstractUIPlugin {
+
+ /**
+ * The one and only instance
+ */
+ private static Activator plugin;
+
+ /**
+ * Property listeners for plugin specific events
+ */
+ private static List<IPropertyChangeListener> propertyChangeListeners =
+ new ArrayList<IPropertyChangeListener>(5);
+
+ /**
+ * Property constant indicating the decorator configuration has changed.
+ */
+ public static final String DECORATORS_CHANGED = "org.eclipse.egit.ui.DECORATORS_CHANGED"; //$NON-NLS-1$
+
+ /**
+ * @return the {@link Activator} singleton.
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * @return the id of the egit ui plugin
+ */
+ public static String getPluginId() {
+ return getDefault().getBundle().getSymbolicName();
+ }
+
+ /**
+ * Returns the standard display to be used. The method first checks, if the
+ * thread calling this method has an associated display. If so, this display
+ * is returned. Otherwise the method returns the default display.
+ *
+ * @return the display to use
+ */
+ public static Display getStandardDisplay() {
+ Display display = Display.getCurrent();
+ if (display == null) {
+ display = Display.getDefault();
+ }
+ return display;
+ }
+
+ /**
+ * Instantiate an error exception.
+ *
+ * @param message
+ * description of the error
+ * @param thr
+ * cause of the error or null
+ * @return an initialized {@link CoreException}
+ */
+ public static CoreException error(final String message, final Throwable thr) {
+ return new CoreException(new Status(IStatus.ERROR, getPluginId(), 0,
+ message, thr));
+ }
+
+ /**
+ * Log an error via the Eclipse logging routines.
+ *
+ * @param message
+ * @param thr
+ * cause of error
+ */
+ public static void logError(final String message, final Throwable thr) {
+ getDefault().getLog().log(
+ new Status(IStatus.ERROR, getPluginId(), 0, message, thr));
+ }
+
+ /**
+ * @param optionId
+ * name of debug option
+ * @return whether a named debug option is set
+ */
+ private static boolean isOptionSet(final String optionId) {
+ final String option = getPluginId() + optionId;
+ final String value = Platform.getDebugOption(option);
+ return value != null && value.equals("true");
+ }
+
+ /**
+ * Log a debug message
+ *
+ * @param what
+ * message to log
+ */
+ public static void trace(final String what) {
+ if (getDefault().traceVerbose) {
+ System.out.println("[" + getPluginId() + "] " + what);
+ }
+ }
+
+ /**
+ * Get the theme used by this plugin.
+ *
+ * @return our theme.
+ */
+ public static ITheme getTheme() {
+ return plugin.getWorkbench().getThemeManager().getCurrentTheme();
+ }
+
+ /**
+ * Get a font known to this plugin.
+ *
+ * @param id
+ * one of our THEME_* font preference ids (see
+ * {@link UIPreferences});
+ * @return the configured font, borrowed from the registry.
+ */
+ public static Font getFont(final String id) {
+ return getTheme().getFontRegistry().get(id);
+ }
+
+ /**
+ * Get a font known to this plugin, but with bold style applied over top.
+ *
+ * @param id
+ * one of our THEME_* font preference ids (see
+ * {@link UIPreferences});
+ * @return the configured font, borrowed from the registry.
+ */
+ public static Font getBoldFont(final String id) {
+ return getTheme().getFontRegistry().getBold(id);
+ }
+
+ private boolean traceVerbose;
+ private RCS rcs;
+ private RIRefresh refreshJob;
+
+ /**
+ * Constructor for the egit ui plugin singleton
+ */
+ public Activator() {
+ plugin = this;
+ }
+
+ public void start(final BundleContext context) throws Exception {
+ super.start(context);
+ traceVerbose = isOptionSet("/trace/verbose");
+ setupSSH(context);
+ setupProxy(context);
+ setupRepoChangeScanner();
+ setupRepoIndexRefresh();
+ }
+
+ private void setupRepoIndexRefresh() {
+ refreshJob = new RIRefresh();
+ Repository.addAnyRepositoryChangedListener(refreshJob);
+ }
+
+ /**
+ * Register for changes made to Team properties.
+ *
+ * @param listener
+ * The listener to register
+ */
+ public static synchronized void addPropertyChangeListener(
+ IPropertyChangeListener listener) {
+ propertyChangeListeners.add(listener);
+ }
+
+ /**
+ * Remove a Team property changes.
+ *
+ * @param listener
+ * The listener to remove
+ */
+ public static synchronized void removePropertyChangeListener(
+ IPropertyChangeListener listener) {
+ propertyChangeListeners.remove(listener);
+ }
+
+ /**
+ * Broadcast a Team property change.
+ *
+ * @param event
+ * The event to broadcast
+ */
+ public static synchronized void broadcastPropertyChange(PropertyChangeEvent event) {
+ for (IPropertyChangeListener listener : propertyChangeListeners)
+ listener.propertyChange(event);
+ }
+
+ static class RIRefresh extends Job implements RepositoryListener {
+
+ RIRefresh() {
+ super("Git index refresh Job");
+ }
+
+ private Set<IProject> projectsToScan = new LinkedHashSet<IProject>();
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ monitor.beginTask("Refreshing git managed projects", projects.length);
+
+ while (projectsToScan.size() > 0) {
+ IProject p;
+ synchronized (projectsToScan) {
+ if (projectsToScan.size() == 0)
+ break;
+ Iterator<IProject> i = projectsToScan.iterator();
+ p = i.next();
+ i.remove();
+ }
+ ISchedulingRule rule = p.getWorkspace().getRuleFactory().refreshRule(p);
+ try {
+ getJobManager().beginRule(rule, monitor);
+ p.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 1));
+ } catch (CoreException e) {
+ logError("Failed to refresh projects from index changes", e);
+ return new Status(IStatus.ERROR, getPluginId(), e.getMessage());
+ } finally {
+ getJobManager().endRule(rule);
+ }
+ }
+ monitor.done();
+ return Status.OK_STATUS;
+ }
+
+ public void indexChanged(IndexChangedEvent e) {
+ // Check the workspace setting "refresh automatically" setting first
+ if (!ResourcesPlugin.getPlugin().getPluginPreferences().getBoolean(
+ ResourcesPlugin.PREF_AUTO_REFRESH))
+ return;
+
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ Set<IProject> toRefresh= new HashSet<IProject>();
+ for (IProject p : projects) {
+ RepositoryMapping mapping = RepositoryMapping.getMapping(p);
+ if (mapping != null && mapping.getRepository() == e.getRepository()) {
+ toRefresh.add(p);
+ }
+ }
+ synchronized (projectsToScan) {
+ projectsToScan.addAll(toRefresh);
+ }
+ if (projectsToScan.size() > 0)
+ schedule();
+ }
+
+ public void refsChanged(RefsChangedEvent e) {
+ // Do not react here
+ }
+
+ }
+
+ static class RCS extends Job {
+ RCS() {
+ super("Repository Change Scanner");
+ }
+
+ // FIXME, need to be more intelligent about this to avoid too much work
+ private static final long REPO_SCAN_INTERVAL = 10000L;
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ // A repository can contain many projects, only scan once
+ // (a project could in theory be distributed among many
+ // repositories. We discard that as being ugly and stupid for
+ // the moment.
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ monitor.beginTask("Scanning Git repositories for changes", projects.length);
+ Set<Repository> scanned = new HashSet<Repository>();
+ for (IProject p : projects) {
+ RepositoryMapping mapping = RepositoryMapping.getMapping(p);
+ if (mapping != null) {
+ Repository r = mapping.getRepository();
+ if (!scanned.contains(r)) {
+ if (monitor.isCanceled())
+ break;
+ trace("Scanning " + r + " for changes");
+ scanned.add(r);
+ ISchedulingRule rule = p.getWorkspace().getRuleFactory().modifyRule(p);
+ getJobManager().beginRule(rule, monitor);
+ try {
+ r.scanForRepoChanges();
+ } finally {
+ getJobManager().endRule(rule);
+ }
+ }
+ }
+ monitor.worked(1);
+ }
+ monitor.done();
+ trace("Rescheduling " + getName() + " job");
+ schedule(REPO_SCAN_INTERVAL);
+ } catch (Exception e) {
+ trace("Stopped rescheduling " + getName() + "job");
+ return new Status(
+ IStatus.ERROR,
+ getPluginId(),
+ 0,
+ "An error occurred while scanning for changes. Scanning aborted",
+ e);
+ }
+ return Status.OK_STATUS;
+ }
+ }
+
+ private void setupRepoChangeScanner() {
+ rcs = new RCS();
+ rcs.schedule(RCS.REPO_SCAN_INTERVAL);
+ }
+
+ private void setupSSH(final BundleContext context) {
+ final ServiceReference ssh;
+
+ ssh = context.getServiceReference(IJSchService.class.getName());
+ if (ssh != null) {
+ SshSessionFactory.setInstance(new EclipseSshSessionFactory(
+ (IJSchService) context.getService(ssh)));
+ }
+ }
+
+ private void setupProxy(final BundleContext context) {
+ final ServiceReference proxy;
+
+ proxy = context.getServiceReference(IProxyService.class.getName());
+ if (proxy != null) {
+ ProxySelector.setDefault(new EclipseProxySelector(
+ (IProxyService) context.getService(proxy)));
+ Authenticator.setDefault(new EclipseAuthenticator(
+ (IProxyService) context.getService(proxy)));
+ }
+ }
+
+ public void stop(final BundleContext context) throws Exception {
+ trace("Trying to cancel " + rcs.getName() + " job");
+ rcs.cancel();
+ trace("Trying to cancel " + refreshJob.getName() + " job");
+ refreshJob.cancel();
+
+ rcs.join();
+ refreshJob.join();
+
+ trace("Jobs terminated");
+ super.stop(context);
+ plugin = null;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseAuthenticator.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseAuthenticator.java
new file mode 100644
index 000000000..0aebe09c1
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseAuthenticator.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import java.net.Authenticator;
+import java.net.InetAddress;
+import java.net.PasswordAuthentication;
+import java.net.UnknownHostException;
+
+import org.eclipse.core.net.proxy.IProxyData;
+import org.eclipse.core.net.proxy.IProxyService;
+
+class EclipseAuthenticator extends Authenticator {
+ private final IProxyService service;
+
+ EclipseAuthenticator(final IProxyService s) {
+ service = s;
+ }
+
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ final IProxyData[] data = service.getProxyData();
+ if (data == null)
+ return null;
+ for (final IProxyData d : data) {
+ if (d.getUserId() == null || d.getHost() == null)
+ continue;
+ if (d.getPort() == getRequestingPort() && hostMatches(d))
+ return auth(d);
+ }
+ return null;
+ }
+
+ private PasswordAuthentication auth(final IProxyData d) {
+ final String user = d.getUserId();
+ final String pass = d.getPassword();
+ final char[] passChar = pass != null ? pass.toCharArray() : new char[0];
+ return new PasswordAuthentication(user, passChar);
+ }
+
+ private boolean hostMatches(final IProxyData d) {
+ try {
+ final InetAddress dHost = InetAddress.getByName(d.getHost());
+ InetAddress rHost = getRequestingSite();
+ if (rHost == null)
+ rHost = InetAddress.getByName(getRequestingHost());
+ return dHost.equals(rHost);
+ } catch (UnknownHostException err) {
+ return false;
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseProxySelector.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseProxySelector.java
new file mode 100644
index 000000000..a7b9dc8ef
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseProxySelector.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.net.proxy.IProxyData;
+import org.eclipse.core.net.proxy.IProxyService;
+
+class EclipseProxySelector extends ProxySelector {
+ private final IProxyService service;
+
+ EclipseProxySelector(final IProxyService s) {
+ service = s;
+ }
+
+ @Override
+ public List<Proxy> select(final URI uri) {
+ final ArrayList<Proxy> r = new ArrayList<Proxy>();
+ final String host = uri.getHost();
+
+ String type = IProxyData.SOCKS_PROXY_TYPE;
+ if ("http".equals(uri.getScheme()))
+ type = IProxyData.HTTP_PROXY_TYPE;
+ else if ("ftp".equals(uri.getScheme()))
+ type = IProxyData.HTTP_PROXY_TYPE;
+ else if ("https".equals(uri.getScheme()))
+ type = IProxyData.HTTPS_PROXY_TYPE;
+
+ final IProxyData data = service.getProxyDataForHost(host, type);
+ if (data != null) {
+ if (IProxyData.HTTP_PROXY_TYPE.equals(data.getType()))
+ addProxy(r, Proxy.Type.HTTP, data);
+ else if (IProxyData.HTTPS_PROXY_TYPE.equals(data.getType()))
+ addProxy(r, Proxy.Type.HTTP, data);
+ else if (IProxyData.SOCKS_PROXY_TYPE.equals(data.getType()))
+ addProxy(r, Proxy.Type.SOCKS, data);
+ }
+ if (r.isEmpty())
+ r.add(Proxy.NO_PROXY);
+ return r;
+ }
+
+ private void addProxy(final ArrayList<Proxy> r, final Proxy.Type type,
+ final IProxyData d) {
+ try {
+ r.add(new Proxy(type, new InetSocketAddress(InetAddress.getByName(d
+ .getHost()), d.getPort())));
+ } catch (UnknownHostException uhe) {
+ // Oh well.
+ }
+ }
+
+ @Override
+ public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+ // Don't tell Eclipse.
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java
new file mode 100644
index 000000000..d0c97c88e
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/EclipseSshSessionFactory.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2009, Google, Inc.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import org.eclipse.jsch.core.IJSchService;
+import org.eclipse.jsch.ui.UserInfoPrompter;
+import org.eclipse.jgit.transport.OpenSshConfig;
+import org.eclipse.jgit.transport.SshConfigSessionFactory;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+class EclipseSshSessionFactory extends SshConfigSessionFactory {
+ private final IJSchService provider;
+
+ EclipseSshSessionFactory(final IJSchService p) {
+ provider = p;
+ }
+
+ @Override
+ protected JSch createDefaultJSch() throws JSchException {
+ // Forcing a dummy session to be created will cause the known hosts
+ // and configured private keys to be initialized. This is needed by
+ // our parent class in case non-default JSch instances need to be made.
+ //
+ provider.createSession("127.0.0.1", 0, "eclipse");
+ return provider.getJSch();
+ }
+
+ @Override
+ protected Session createSession(final OpenSshConfig.Host hc,
+ final String user, final String host, final int port)
+ throws JSchException {
+ final JSch jsch = getJSch(hc);
+ if (jsch == provider.getJSch()) {
+ // If its the default JSch desired, let the provider
+ // manage the session creation for us.
+ //
+ return provider.createSession(host, port, user);
+ } else {
+ // This host configuration is using a different IdentityFile,
+ // one that is not available through the default JSch.
+ //
+ return jsch.getSession(user, host, port);
+ }
+ }
+
+ @Override
+ protected void configure(final OpenSshConfig.Host hc, final Session session) {
+ if (!hc.isBatchMode())
+ new UserInfoPrompter(session);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/GitHistoryPageSource.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/GitHistoryPageSource.java
new file mode 100644
index 000000000..8c9fac7cf
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/GitHistoryPageSource.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.egit.core.ResourceList;
+import org.eclipse.egit.ui.internal.history.GitHistoryPage;
+import org.eclipse.team.ui.history.HistoryPageSource;
+import org.eclipse.ui.part.Page;
+
+/**
+ * A helper class for constructing the {@link GitHistoryPage}.
+ */
+public class GitHistoryPageSource extends HistoryPageSource {
+ public boolean canShowHistoryFor(final Object object) {
+ return GitHistoryPage.canShowHistoryFor(object);
+ }
+
+ public Page createPage(final Object object) {
+ final ResourceList input;
+
+ if (object instanceof ResourceList)
+ input = (ResourceList) object;
+ else if (object instanceof IResource)
+ input = new ResourceList(new IResource[] { (IResource) object });
+ else
+ input = new ResourceList(new IResource[0]);
+
+ final GitHistoryPage pg = new GitHistoryPage();
+ pg.setInput(input);
+ return pg;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java
new file mode 100644
index 000000000..95dda4133
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/PluginPreferenceInitializer.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+
+/**
+ * Plugin extension point to initialize the plugin runtime preferences.
+ */
+public class PluginPreferenceInitializer extends AbstractPreferenceInitializer {
+
+ /**
+ * Calls super constructor.
+ */
+ public PluginPreferenceInitializer() {
+ super();
+ }
+
+ /**
+ * This method initializes the plugin preferences with default values.
+ */
+ public void initializeDefaultPreferences() {
+ Preferences prefs = Activator.getDefault().getPluginPreferences();
+ int[] w;
+
+ prefs.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_WRAP, true);
+ prefs.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_REV_DETAIL, true);
+ prefs.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_REV_COMMENT, true);
+ prefs.setDefault(UIPreferences.RESOURCEHISTORY_SHOW_TOOLTIPS, false);
+
+ prefs.setDefault(UIPreferences.DECORATOR_RECOMPUTE_ANCESTORS, true);
+ prefs.setDefault(UIPreferences.DECORATOR_RECURSIVE_LIMIT,
+ Integer.MAX_VALUE);
+ prefs.setDefault(UIPreferences.DECORATOR_FILETEXT_DECORATION,
+ UIText.DecoratorPreferencesPage_fileFormatDefault);
+ prefs.setDefault(UIPreferences.DECORATOR_FOLDERTEXT_DECORATION,
+ UIText.DecoratorPreferencesPage_folderFormatDefault);
+ prefs.setDefault(UIPreferences.DECORATOR_PROJECTTEXT_DECORATION,
+ UIText.DecoratorPreferencesPage_projectFormatDefault);
+ prefs.setDefault(UIPreferences.DECORATOR_SHOW_TRACKED_ICON, true);
+ prefs.setDefault(UIPreferences.DECORATOR_SHOW_UNTRACKED_ICON, true);
+ prefs.setDefault(UIPreferences.DECORATOR_SHOW_STAGED_ICON, true);
+ prefs.setDefault(UIPreferences.DECORATOR_SHOW_CONFLICTS_ICON, true);
+ prefs.setDefault(UIPreferences.DECORATOR_SHOW_ASSUME_VALID_ICON, true);
+
+ w = new int[] { 500, 500 };
+ UIPreferences.setDefault(prefs,
+ UIPreferences.RESOURCEHISTORY_GRAPH_SPLIT, w);
+ w = new int[] { 700, 300 };
+ UIPreferences.setDefault(prefs,
+ UIPreferences.RESOURCEHISTORY_REV_SPLIT, w);
+
+ prefs.setDefault(UIPreferences.FINDTOOLBAR_IGNORE_CASE, true);
+ prefs.setDefault(UIPreferences.FINDTOOLBAR_FIND_IN, 2);
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIIcons.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIIcons.java
new file mode 100644
index 000000000..b66ebb322
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIIcons.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+
+/**
+ * Icons for the the Eclipse plugin. Mostly decorations.
+ */
+public class UIIcons {
+
+ /** Decoration for resource in the index but not yet committed. */
+ public static final ImageDescriptor OVR_STAGED;
+
+ /** Decoration for resource added to index but not yet committed. */
+ public static final ImageDescriptor OVR_STAGED_ADD;
+
+ /** Decoration for resource removed from the index but not commit. */
+ public static final ImageDescriptor OVR_STAGED_REMOVE;
+
+ /** Decoration for resource not being tracked by Git */
+ public static final ImageDescriptor OVR_UNTRACKED;
+
+ /** Decoration for tracked resource with a merge conflict. */
+ public static final ImageDescriptor OVR_CONFLICT;
+
+ /** Decoration for tracked resources that we want to ignore changes in. */
+ public static final ImageDescriptor OVR_ASSUMEVALID;
+
+ /** Find icon */
+ public static final ImageDescriptor ELCL16_FIND;
+ /** Next arrow icon */
+ public static final ImageDescriptor ELCL16_NEXT;
+ /** Previous arrow icon */
+ public static final ImageDescriptor ELCL16_PREVIOUS;
+ /** Commit icon */
+ public static final ImageDescriptor ELCL16_COMMIT;
+ /** Comments icon */
+ public static final ImageDescriptor ELCL16_COMMENTS;
+ /** Author icon */
+ public static final ImageDescriptor ELCL16_AUTHOR;
+ /** Committer icon */
+ public static final ImageDescriptor ELCL16_COMMITTER;
+ /** Delete icon */
+ public static final ImageDescriptor ELCL16_DELETE;
+ /** Add icon */
+ public static final ImageDescriptor ELCL16_ADD;
+ /** Trash icon */
+ public static final ImageDescriptor ELCL16_TRASH;
+ /** Clear icon */
+ public static final ImageDescriptor ELCL16_CLEAR;
+
+ /** Enabled, checked, checkbox image */
+ public static final ImageDescriptor CHECKBOX_ENABLED_CHECKED;
+ /** Enabled, unchecked, checkbox image */
+ public static final ImageDescriptor CHECKBOX_ENABLED_UNCHECKED;
+ /** Disabled, checked, checkbox image */
+ public static final ImageDescriptor CHECKBOX_DISABLED_CHECKED;
+ /** Disabled, unchecked, checkbox image */
+ public static final ImageDescriptor CHECKBOX_DISABLED_UNCHECKED;
+
+ /** Import Wizard banner */
+ public static final ImageDescriptor WIZBAN_IMPORT_REPO;
+
+ /** Connect Wizard banner */
+ public static final ImageDescriptor WIZBAN_CONNECT_REPO;
+
+ /** History filter, select all version in repo */
+ public static ImageDescriptor FILTERREPO;
+
+ /** History filter, select all version in same project */
+ public static ImageDescriptor FILTERPROJECT;
+
+ /** History filter, select all version in same folder */
+ public static ImageDescriptor FILTERFOLDER;
+
+ private static final URL base;
+
+ static {
+ base = init();
+ OVR_STAGED = map("ovr/staged.gif");
+ OVR_STAGED_ADD = map("ovr/staged_added.gif");
+ OVR_STAGED_REMOVE = map("ovr/staged_removed.gif");
+ OVR_UNTRACKED = map("ovr/untracked.gif");
+ OVR_CONFLICT = map("ovr/conflict.gif");
+ OVR_ASSUMEVALID = map("ovr/assume_valid.gif");
+ ELCL16_FIND = map("elcl16/find.gif");
+ ELCL16_NEXT = map("elcl16/next.gif");
+ ELCL16_PREVIOUS = map("elcl16/previous.gif");
+ WIZBAN_IMPORT_REPO = map("wizban/import_wiz.png");
+ WIZBAN_CONNECT_REPO = map("wizban/newconnect_wizban.png");
+ ELCL16_COMMIT = map("elcl16/commit.gif");
+ ELCL16_COMMENTS = map("elcl16/comment.gif");
+ ELCL16_AUTHOR = map("elcl16/author.gif");
+ ELCL16_COMMITTER = map("elcl16/committer.gif");
+ ELCL16_DELETE = map("elcl16/delete.gif");
+ ELCL16_ADD = map("elcl16/add.gif");
+ ELCL16_TRASH = map("elcl16/trash.gif");
+ ELCL16_CLEAR = map("elcl16/clear.gif");
+ CHECKBOX_ENABLED_CHECKED = map("checkboxes/enabled_checked.gif");
+ CHECKBOX_ENABLED_UNCHECKED = map("checkboxes/enabled_unchecked.gif");
+ CHECKBOX_DISABLED_CHECKED = map("checkboxes/disabled_checked.gif");
+ CHECKBOX_DISABLED_UNCHECKED = map("checkboxes/disabled_unchecked.gif");
+ FILTERREPO = map("elcl16/filterrepo.gif");
+ FILTERPROJECT = map("elcl16/filterproject.gif");
+ FILTERFOLDER = map("elcl16/filterfolder.gif");
+ }
+
+ private static ImageDescriptor map(final String icon) {
+ if (base != null) {
+ try {
+ return ImageDescriptor.createFromURL(new URL(base, icon));
+ } catch (MalformedURLException mux) {
+ Activator.logError("Can't load plugin image.", mux);
+ }
+ }
+ return ImageDescriptor.getMissingImageDescriptor();
+ }
+
+ private static URL init() {
+ try {
+ return new URL(Activator.getDefault().getBundle().getEntry("/"),
+ "icons/");
+ } catch (MalformedURLException mux) {
+ Activator.logError("Can't determine icon base.", mux);
+ return null;
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java
new file mode 100644
index 000000000..a69b5ed8c
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIPreferences.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import org.eclipse.core.runtime.Preferences;
+
+/**
+ * Preferences used by the plugin.
+ * All plugin preferences shall be referenced by a constant in this class.
+ */
+public class UIPreferences {
+ /** */
+ public final static String RESOURCEHISTORY_SHOW_COMMENT_WRAP = "resourcehistory_show_comment_wrap";
+ /** */
+ public static final String RESOURCEHISTORY_SHOW_COMMENT_FILL = "resourcehistory_fill_comment_paragraph";
+ /** */
+ public final static String RESOURCEHISTORY_SHOW_REV_DETAIL = "resourcehistory_show_rev_detail";
+ /** */
+ public final static String RESOURCEHISTORY_SHOW_REV_COMMENT = "resourcehistory_show_rev_comment";
+ /** */
+ public final static String RESOURCEHISTORY_GRAPH_SPLIT = "resourcehistory_graph_split";
+ /** */
+ public final static String RESOURCEHISTORY_REV_SPLIT = "resourcehistory_rev_split";
+ /** */
+ public final static String RESOURCEHISTORY_SHOW_TOOLTIPS = "resourcehistory_show_tooltips";
+ /** */
+ public final static String RESOURCEHISTORY_SHOW_FINDTOOLBAR = "resourcehistory_show_findtoolbar";
+ /** */
+ public final static String FINDTOOLBAR_IGNORE_CASE = "findtoolbar_ignore_case";
+ /** */
+ public final static String FINDTOOLBAR_COMMIT_ID = "findtoolbar_commit_id";
+ /** */
+ public final static String FINDTOOLBAR_COMMENTS = "findtoolbar_comments";
+ /** */
+ public final static String FINDTOOLBAR_AUTHOR = "findtoolbar_author";
+ /** */
+ public final static String FINDTOOLBAR_COMMITTER = "findtoolbar_committer";
+ /** */
+ public final static String FINDTOOLBAR_FIND_IN = "findtoolbar_find_in";
+
+ /** */
+ public final static String THEME_CommitGraphNormalFont = "org.eclipse.egit.ui.CommitGraphNormalFont";
+ /** */
+ public final static String THEME_CommitGraphHighlightFont = "org.eclipse.egit.ui.CommitGraphHighlightFont";
+ /** */
+ public final static String THEME_CommitMessageFont = "org.eclipse.egit.ui.CommitMessageFont";
+
+ /** */
+ public final static String DECORATOR_RECOMPUTE_ANCESTORS = "decorator_recompute_ancestors";
+ /** */
+ public final static String DECORATOR_RECURSIVE_LIMIT = "decorator_recursive_limit";
+ /** */
+ public final static String DECORATOR_FILETEXT_DECORATION = "decorator_filetext_decoration";
+ /** */
+ public final static String DECORATOR_FOLDERTEXT_DECORATION = "decorator_foldertext_decoration";
+ /** */
+ public final static String DECORATOR_PROJECTTEXT_DECORATION = "decorator_projecttext_decoration";
+ /** */
+ public final static String DECORATOR_SHOW_TRACKED_ICON = "decorator_show_tracked_icon";
+ /** */
+ public final static String DECORATOR_SHOW_UNTRACKED_ICON = "decorator_show_untracked_icon";
+ /** */
+ public final static String DECORATOR_SHOW_STAGED_ICON = "decorator_show_staged_icon";
+ /** */
+ public final static String DECORATOR_SHOW_CONFLICTS_ICON = "decorator_show_conflicts_icon";
+ /** */
+ public final static String DECORATOR_SHOW_ASSUME_VALID_ICON = "decorator_show_assume_valid_icon";
+
+ /**
+ * Get the preference values associated with a fixed integer array.
+ *
+ * @param prefs
+ * the store to read.
+ * @param key
+ * key name.
+ * @param cnt
+ * number of entries in the returned array.
+ * @return the preference values for the array.
+ */
+ public static int[] getIntArray(final Preferences prefs, final String key,
+ final int cnt) {
+ final String s = prefs.getString(key);
+ final int[] r = new int[cnt];
+ if (s != null) {
+ final String[] e = s.split(",");
+ for (int i = 0; i < Math.min(e.length, r.length); i++)
+ r[i] = Integer.parseInt(e[i].trim());
+ }
+ return r;
+ }
+
+ /**
+ * Set the preference values associated with a fixed integer array.
+ *
+ * @param prefs
+ * the store to read.
+ * @param key
+ * key name.
+ * @param data
+ * entries to store.
+ */
+ public static void setValue(final Preferences prefs, final String key,
+ final int[] data) {
+ final StringBuilder s = new StringBuilder();
+ for (int i = 0; i < data.length; i++) {
+ if (i > 0)
+ s.append(',');
+ s.append(data[i]);
+ }
+ prefs.setValue(key, s.toString());
+ }
+
+ /**
+ * Set the preference values associated with a fixed integer array.
+ *
+ * @param prefs
+ * the store to read.
+ * @param key
+ * key nam
+ * @param data
+ * entries to store.
+ */
+ public static void setDefault(final Preferences prefs, final String key,
+ final int[] data) {
+ final StringBuilder s = new StringBuilder();
+ for (int i = 0; i < data.length; i++) {
+ if (i > 0)
+ s.append(',');
+ s.append(data[i]);
+ }
+ prefs.setDefault(key, s.toString());
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
new file mode 100644
index 000000000..fafecacb6
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java
@@ -0,0 +1,1088 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Text resources for the plugin. Strings here can be i18n-ed simpler and avoid
+ * duplicating strings.
+ */
+public class UIText extends NLS {
+ /** */
+ public static String WizardProjectsImportPage_ImportProjectsTitle;
+
+ /** */
+ public static String WizardProjectsImportPage_ImportProjectsDescription;
+
+ /** */
+ public static String WizardProjectsImportPage_ProjectsListTitle;
+
+ /** */
+ public static String WizardProjectsImportPage_selectAll;
+
+ /** */
+ public static String WizardProjectsImportPage_deselectAll;
+
+ /** */
+ public static String WizardProjectsImportPage_projectLabel;
+
+ /** */
+ public static String WizardProjectsImportPage_SearchingMessage;
+
+ /** */
+ public static String WizardProjectsImportPage_ProcessingMessage;
+
+ /** */
+ public static String WizardProjectsImportPage_projectsInWorkspace;
+
+ /** */
+ public static String WizardProjectsImportPage_CheckingMessage;
+
+ /** */
+ public static String WizardProjectsImportPage_SelectDialogTitle;
+
+ /** */
+ public static String WizardProjectImportPage_errorMessage;
+
+ /** */
+ public static String WizardProjectsImportPage_CreateProjectsTask;
+
+ /** */
+ public static String WizardProjectsImportPage_enableGit;
+
+ /** */
+ public static String SharingWizard_windowTitle;
+
+ /** */
+ public static String SharingWizard_failed;
+
+ /** */
+ public static String GenericOperationFailed;
+
+ /** */
+ public static String ExistingOrNewPage_CreateButton;
+
+ /** */
+ public static String ExistingOrNewPage_title;
+
+ /** */
+ public static String ExistingOrNewPage_description;
+
+ /** */
+ public static String ExistingOrNewPage_ErrorFailedToCreateRepository;
+
+ /** */
+ public static String ExistingOrNewPage_ErrorFailedToRefreshRepository;
+
+ /** */
+ public static String ExistingOrNewPage_HeaderPath;
+
+ /** */
+ public static String ExistingOrNewPage_HeaderProject;
+
+ /** */
+ public static String ExistingOrNewPage_HeaderRepository;
+
+ /** */
+ public static String ExistingOrNewPage_SymbolicValueEmptyMapping;
+
+ /** */
+ public static String GitCloneWizard_title;
+
+ /** */
+ public static String GitCloneWizard_jobName;
+
+ /** */
+ public static String GitCloneWizard_failed;
+
+ /** */
+ public static String GitCloneWizard_errorCannotCreate;
+
+ /** */
+ public static String GitProjectPropertyPage_LabelBranch;
+
+ /** */
+ public static String GitProjectPropertyPage_LabelGitDir;
+
+ /** */
+ public static String GitProjectPropertyPage_LabelId;
+
+ /** */
+ public static String GitProjectPropertyPage_LabelState;
+
+ /** */
+ public static String GitProjectPropertyPage_LabelWorkdir;
+
+ /** */
+ public static String GitProjectPropertyPage_ValueEmptyRepository;
+
+ /** */
+ public static String GitProjectPropertyPage_ValueUnbornBranch;
+
+ /** */
+ public static String RepositorySelectionPage_sourceSelectionTitle;
+
+ /** */
+ public static String RepositorySelectionPage_sourceSelectionDescription;
+
+ /** */
+ public static String RepositorySelectionPage_destinationSelectionTitle;
+
+ /** */
+ public static String RepositorySelectionPage_destinationSelectionDescription;
+
+ /** */
+ public static String RepositorySelectionPage_groupLocation;
+
+ /** */
+ public static String RepositorySelectionPage_groupAuthentication;
+
+ /** */
+ public static String RepositorySelectionPage_groupConnection;
+
+ /** */
+ public static String RepositorySelectionPage_promptURI;
+
+ /** */
+ public static String RepositorySelectionPage_promptHost;
+
+ /** */
+ public static String RepositorySelectionPage_promptPath;
+
+ /** */
+ public static String RepositorySelectionPage_promptUser;
+
+ /** */
+ public static String RepositorySelectionPage_promptPassword;
+
+ /** */
+ public static String RepositorySelectionPage_promptScheme;
+
+ /** */
+ public static String RepositorySelectionPage_promptPort;
+
+ /** */
+ public static String RepositorySelectionPage_fieldRequired;
+
+ /** */
+ public static String RepositorySelectionPage_fieldNotSupported;
+
+ /** */
+ public static String RepositorySelectionPage_fileNotFound;
+
+ /** */
+ public static String RepositorySelectionPage_internalError;
+
+ /** */
+ public static String RepositorySelectionPage_configuredRemoteChoice;
+
+ /** */
+ public static String RepositorySelectionPage_uriChoice;
+
+ /** */
+ public static String SourceBranchPage_title;
+
+ /** */
+ public static String SourceBranchPage_description;
+
+ /** */
+ public static String SourceBranchPage_branchList;
+
+ /** */
+ public static String SourceBranchPage_selectAll;
+
+ /** */
+ public static String SourceBranchPage_selectNone;
+
+ /** */
+ public static String SourceBranchPage_errorBranchRequired;
+
+ /** */
+ public static String SourceBranchPage_transportError;
+
+ /** */
+ public static String SourceBranchPage_cannotListBranches;
+
+ /** */
+ public static String SourceBranchPage_remoteListingCancelled;
+
+ /** */
+ public static String SourceBranchPage_cannotCreateTemp;
+
+ /** */
+ public static String CloneDestinationPage_title;
+
+ /** */
+ public static String CloneDestinationPage_description;
+
+ /** */
+ public static String CloneDestinationPage_groupDestination;
+
+ /** */
+ public static String CloneDestinationPage_groupConfiguration;
+
+ /** */
+ public static String CloneDestinationPage_promptDirectory;
+
+ /** */
+ public static String CloneDestinationPage_promptInitialBranch;
+
+ /** */
+ public static String CloneDestinationPage_promptRemoteName;
+
+ /** */
+ public static String CloneDestinationPage_fieldRequired;
+
+ /** */
+ public static String CloneDestinationPage_browseButton;
+
+ /** */
+ public static String CloneDestinationPage_errorNotEmptyDir;
+
+ /** */
+ public static String CloneDestinationPage_workspaceImport;
+
+ /** */
+ public static String CloneDestinationPage_importProjectsAfterClone;
+
+ /** */
+ public static String RefSpecPanel_refChooseSome;
+
+ /** */
+ public static String RefSpecPanel_refChooseSomeWildcard;
+
+ /** */
+ public static String RefSpecPanel_refChooseRemoteName;
+
+ /** */
+ public static String RefSpecPanel_clickToChange;
+
+ /** */
+ public static String RefSpecPanel_columnDst;
+
+ /** */
+ public static String RefSpecPanel_columnForce;
+
+ /** */
+ public static String RefSpecPanel_columnMode;
+
+ /** */
+ public static String RefSpecPanel_columnRemove;
+
+ /** */
+ public static String RefSpecPanel_columnSrc;
+
+ /** */
+ public static String RefSpecPanel_creationButton;
+
+ /** */
+ public static String RefSpecPanel_creationButtonDescription;
+
+ /** */
+ public static String RefSpecPanel_creationDst;
+
+ /** */
+ public static String RefSpecPanel_creationGroup;
+
+ /** */
+ public static String RefSpecPanel_creationSrc;
+
+ /** */
+ public static String RefSpecPanel_deletionButton;
+
+ /** */
+ public static String RefSpecPanel_deletionButtonDescription;
+
+ /** */
+ public static String RefSpecPanel_deletionGroup;
+
+ /** */
+ public static String RefSpecPanel_deletionRef;
+
+ /** */
+ public static String RefSpecPanel_dstDeletionDescription;
+
+ /** */
+ public static String RefSpecPanel_dstFetchDescription;
+
+ /** */
+ public static String RefSpecPanel_dstPushDescription;
+
+ /** */
+ public static String RefSpecPanel_errorRemoteConfigDescription;
+
+ /** */
+ public static String RefSpecPanel_errorRemoteConfigTitle;
+
+ /** */
+ public static String RefSpecPanel_fetch;
+
+ /** */
+ public static String RefSpecPanel_srcFetchDescription;
+
+ /** */
+ public static String RefSpecPanel_forceAll;
+
+ /** */
+ public static String RefSpecPanel_forceAllDescription;
+
+ /** */
+ public static String RefSpecPanel_forceDeleteDescription;
+
+ /** */
+ public static String RefSpecPanel_forceFalseDescription;
+
+ /** */
+ public static String RefSpecPanel_forceTrueDescription;
+
+ /** */
+ public static String RefSpecPanel_modeDelete;
+
+ /** */
+ public static String RefSpecPanel_modeDeleteDescription;
+
+ /** */
+ public static String RefSpecPanel_modeUpdate;
+
+ /** */
+ public static String RefSpecPanel_modeUpdateDescription;
+
+ /** */
+ public static String RefSpecPanel_predefinedAll;
+
+ /** */
+ public static String RefSpecPanel_predefinedAllDescription;
+
+ /** */
+ public static String RefSpecPanel_predefinedConfigured;
+
+ /** */
+ public static String RefSpecPanel_predefinedConfiguredDescription;
+
+ /** */
+ public static String RefSpecPanel_predefinedGroup;
+
+ /** */
+ public static String RefSpecPanel_predefinedTags;
+
+ /** */
+ public static String RefSpecPanel_predefinedTagsDescription;
+
+ /** */
+ public static String RefSpecPanel_push;
+
+ /** */
+ public static String RefSpecPanel_srcPushDescription;
+
+ /** */
+ public static String RefSpecPanel_removeAll;
+
+ /** */
+ public static String RefSpecPanel_removeAllDescription;
+
+ /** */
+ public static String RefSpecPanel_removeDescription;
+
+ /** */
+ public static String RefSpecPanel_specifications;
+
+ /** */
+ public static String RefSpecPanel_srcDeleteDescription;
+
+ /** */
+ public static String RefSpecPanel_validationDstInvalidExpression;
+
+ /** */
+ public static String RefSpecPanel_validationDstRequired;
+
+ /** */
+ public static String RefSpecPanel_validationRefDeleteRequired;
+
+ /** */
+ public static String RefSpecPanel_validationRefDeleteWildcard;
+
+ /** */
+ public static String RefSpecPanel_validationRefInvalidExpression;
+
+ /** */
+ public static String RefSpecPanel_validationRefInvalidLocal;
+
+ /** */
+ public static String RefSpecPanel_validationRefNonExistingRemote;
+
+ /** */
+ public static String RefSpecPanel_validationRefNonExistingRemoteDelete;
+
+ /** */
+ public static String RefSpecPanel_validationRefNonMatchingLocal;
+
+ /** */
+ public static String RefSpecPanel_validationRefNonMatchingRemote;
+
+ /** */
+ public static String RefSpecPanel_validationSpecificationsOverlappingDestination;
+
+ /** */
+ public static String RefSpecPanel_validationSrcUpdateRequired;
+
+ /** */
+ public static String RefSpecPanel_validationWildcardInconsistent;
+
+ /** */
+ public static String RefSpecPage_descriptionFetch;
+
+ /** */
+ public static String RefSpecPage_descriptionPush;
+
+ /** */
+ public static String RefSpecPage_errorDontMatchSrc;
+
+ /** */
+ public static String RefSpecPage_errorTransportDialogMessage;
+
+ /** */
+ public static String RefSpecPage_errorTransportDialogTitle;
+
+ /** */
+ public static String RefSpecPage_operationCancelled;
+
+ /** */
+ public static String RefSpecPage_saveSpecifications;
+
+ /** */
+ public static String RefSpecPage_titleFetch;
+
+ /** */
+ public static String RefSpecPage_titlePush;
+
+ /** */
+ public static String RefSpecPage_annotatedTagsGroup;
+
+ /** */
+ public static String RefSpecPage_annotatedTagsAutoFollow;
+
+ /** */
+ public static String RefSpecPage_annotatedTagsFetchTags;
+
+ /** */
+ public static String RefSpecPage_annotatedTagsNoTags;
+
+ /** */
+ public static String QuickDiff_failedLoading;
+
+ /** */
+ public static String ResourceHistory_toggleCommentWrap;
+
+ /** */
+ public static String ResourceHistory_toggleCommentFill;
+
+ /** */
+ public static String ResourceHistory_toggleRevDetail;
+
+ /** */
+ public static String ResourceHistory_toggleRevComment;
+
+ /** */
+ public static String ResourceHistory_toggleTooltips;
+
+ /** */
+ public static String HistoryPage_authorColumn;
+
+ /** */
+ public static String HistoryPage_dateColumn;
+
+ /** */
+ public static String HistoryPage_pathnameColumn;
+
+ /** */
+ public static String HistoryPage_refreshJob;
+
+ /** */
+ public static String HistoryPage_findbar_findTooltip;
+
+ /** */
+ public static String HistoryPage_findbar_find;
+
+ /** */
+ public static String HistoryPage_findbar_next;
+
+ /** */
+ public static String HistoryPage_findbar_previous;
+
+ /** */
+ public static String HistoryPage_findbar_ignorecase;
+
+ /** */
+ public static String HistoryPage_findbar_commit;
+
+ /** */
+ public static String HistoryPage_findbar_comments;
+
+ /** */
+ public static String HistoryPage_findbar_author;
+
+ /** */
+ public static String HistoryPage_findbar_committer;
+
+ /** */
+ public static String HistoryPage_findbar_changeto_commit;
+
+ /** */
+ public static String HistoryPage_findbar_changeto_comments;
+
+ /** */
+ public static String HistoryPage_findbar_changeto_author;
+
+ /** */
+ public static String HistoryPage_findbar_changeto_committer;
+
+ /** */
+ public static String HistoryPage_findbar_exceeded;
+
+ /** */
+ public static String HistoryPage_findbar_notFound;
+
+ /** */
+ public static String HistoryPreferencePage_title;
+
+ /** */
+ public static String PushAction_wrongURIDescription;
+
+ /** */
+ public static String PushAction_wrongURITitle;
+
+ /** */
+ public static String PushWizard_cantConnectToAny;
+
+ /** */
+ public static String PushWizard_cantPrepareUpdatesMessage;
+
+ /** */
+ public static String PushWizard_cantPrepareUpdatesTitle;
+
+ /** */
+ public static String PushWizard_cantSaveMessage;
+
+ /** */
+ public static String PushWizard_cantSaveTitle;
+
+ /** */
+ public static String PushWizard_jobName;
+
+ /** */
+ public static String PushWizard_missingRefsMessage;
+
+ /** */
+ public static String PushWizard_missingRefsTitle;
+
+ /** */
+ public static String PushWizard_unexpectedError;
+
+ /** */
+ public static String PushWizard_windowTitleDefault;
+
+ /** */
+ public static String PushWizard_windowTitleWithDestination;
+
+ /** */
+ public static String CommitDialog_AddFileOnDiskToIndex;
+
+ /** */
+ public static String CommitDialog_AddSOB;
+
+ /** */
+ public static String CommitDialog_AmendPreviousCommit;
+
+ /** */
+ public static String CommitDialog_Author;
+
+ /** */
+ public static String CommitDialog_Commit;
+
+ /** */
+ public static String CommitDialog_CommitChanges;
+
+ /** */
+ public static String CommitDialog_Committer;
+
+ /** */
+ public static String CommitDialog_CommitMessage;
+
+ /** */
+ public static String CommitDialog_DeselectAll;
+
+ /** */
+ public static String CommitDialog_ErrorInvalidAuthor;
+
+ /** */
+ public static String CommitDialog_ErrorInvalidAuthorSpecified;
+
+ /** */
+ public static String CommitDialog_ErrorInvalidCommitterSpecified;
+
+ /** */
+ public static String CommitDialog_ErrorMustEnterCommitMessage;
+
+ /** */
+ public static String CommitDialog_ErrorNoItemsSelected;
+
+ /** */
+ public static String CommitDialog_ErrorNoItemsSelectedToBeCommitted;
+
+ /** */
+ public static String CommitDialog_ErrorNoMessage;
+
+ /** */
+ public static String CommitDialog_File;
+
+ /** */
+ public static String CommitDialog_SelectAll;
+
+ /** */
+ public static String CommitDialog_Status;
+
+ /** */
+ public static String CommitDialog_StatusAdded;
+
+ /** */
+ public static String CommitDialog_StatusAddedIndexDiff;
+
+ /** */
+ public static String CommitDialog_StatusModified;
+
+ /** */
+ public static String CommitDialog_StatusModifiedIndexDiff;
+
+ /** */
+ public static String CommitDialog_StatusModifiedNotStaged;
+
+ /** */
+ public static String CommitDialog_StatusRemoved;
+
+ /** */
+ public static String CommitDialog_StatusRemovedNotStaged;
+
+ /** */
+ public static String CommitDialog_StatusUnknown;
+
+ /** */
+ public static String ConfirmationPage_cantConnectToAnyTitle;
+
+ /** */
+ public static String ConfirmationPage_cantConnectToAny;
+
+ /** */
+ public static String ConfirmationPage_description;
+
+ /** */
+ public static String ConfirmationPage_errorCantResolveSpecs;
+
+ /** */
+ public static String ConfirmationPage_errorInterrupted;
+
+ /** */
+ public static String ConfirmationPage_errorRefsChangedNoMatch;
+
+ /** */
+ public static String ConfirmationPage_errorUnexpected;
+
+ /** */
+ public static String ConfirmationPage_requireUnchangedButton;
+
+ /** */
+ public static String ConfirmationPage_showOnlyIfChanged;
+
+ /** */
+ public static String ConfirmationPage_title;
+
+ /** */
+ public static String PushResultTable_columnStatusRepo;
+
+ /** */
+ public static String PushResultTable_columnDst;
+
+ /** */
+ public static String PushResultTable_columnSrc;
+
+ /** */
+ public static String PushResultTable_columnMode;
+
+ /** */
+ public static String PushResultTable_statusUnexpected;
+
+ /** */
+ public static String PushResultTable_statusConnectionFailed;
+
+ /** */
+ public static String PushResultTable_statusDetailChanged;
+
+ /** */
+ public static String PushResultTable_refNonExisting;
+
+ /** */
+ public static String PushResultTable_statusDetailDeleted;
+
+ /** */
+ public static String PushResultTable_statusDetailNonFastForward;
+
+ /** */
+ public static String PushResultTable_statusDetailNoDelete;
+
+ /** */
+ public static String PushResultTable_statusDetailNonExisting;
+
+ /** */
+ public static String PushResultTable_statusDetailForcedUpdate;
+
+ /** */
+ public static String PushResultTable_statusDetailFastForward;
+
+ /** */
+ public static String PushResultTable_statusRemoteRejected;
+
+ /** */
+ public static String PushResultTable_statusRejected;
+
+ /** */
+ public static String PushResultTable_statusNoMatch;
+
+ /** */
+ public static String PushResultTable_statusUpToDate;
+
+ /** */
+ public static String PushResultTable_statusOkDeleted;
+
+ /** */
+ public static String PushResultTable_statusOkNewBranch;
+
+ /** */
+ public static String PushResultTable_statusOkNewTag;
+
+ /** */
+ public static String ResultDialog_title;
+
+ /** */
+ public static String ResultDialog_label;
+
+ /** */
+ public static String FetchAction_wrongURITitle;
+
+ /** */
+ public static String FetchAction_wrongURIMessage;
+
+ /** */
+ public static String FetchResultDialog_labelEmptyResult;
+
+ /** */
+ public static String FetchResultDialog_labelNonEmptyResult;
+
+ /** */
+ public static String FetchResultDialog_title;
+
+ /** */
+ public static String FetchResultTable_columnDst;
+
+ /** */
+ public static String FetchResultTable_columnSrc;
+
+ /** */
+ public static String FetchResultTable_columnStatus;
+
+ /** */
+ public static String FetchResultTable_statusDetailCouldntLock;
+
+ /** */
+ public static String FetchResultTable_statusDetailFastForward;
+
+ /** */
+ public static String FetchResultTable_statusDetailIOError;
+
+ /** */
+ public static String FetchResultTable_statusDetailNonFastForward;
+
+ /** */
+ public static String FetchResultTable_statusIOError;
+
+ /** */
+ public static String FetchResultTable_statusLockFailure;
+
+ /** */
+ public static String FetchResultTable_statusNewBranch;
+
+ /** */
+ public static String FetchResultTable_statusNew;
+
+ /** */
+ public static String FetchResultTable_statusNewTag;
+
+ /** */
+ public static String FetchResultTable_statusRejected;
+
+ /** */
+ public static String FetchResultTable_statusUnexpected;
+
+ /** */
+ public static String FetchResultTable_statusUpToDate;
+
+ /** */
+ public static String FetchWizard_cantSaveMessage;
+
+ /** */
+ public static String FetchWizard_cantSaveTitle;
+
+ /** */
+ public static String FetchWizard_fetchNotSupported;
+
+ /** */
+ public static String FetchWizard_jobName;
+
+ /** */
+ public static String FetchWizard_transportError;
+
+ /** */
+ public static String FetchWizard_transportNotSupportedMessage;
+
+ /** */
+ public static String FetchWizard_transportNotSupportedTitle;
+
+ /** */
+ public static String FetchWizard_windowTitleDefault;
+
+ /** */
+ public static String FetchWizard_windowTitleWithSource;
+
+ /** */
+ public static String WindowCachePreferencePage_title;
+
+ /** */
+ public static String WindowCachePreferencePage_packedGitWindowSize;
+
+ /** */
+ public static String WindowCachePreferencePage_packedGitLimit;
+
+ /** */
+ public static String WindowCachePreferencePage_deltaBaseCacheLimit;
+
+ /** */
+ public static String WindowCachePreferencePage_packedGitMMAP;
+
+ /** */
+ public static String BranchSelectionDialog_TitleCheckout;
+
+ /** */
+ public static String BranchSelectionDialog_TitleReset;
+
+ /** */
+ public static String BranchSelectionDialog_OkReset;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorCouldNotRefreshBranchList;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorCouldNotCreateNewRef;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorCouldNotRefresh;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorCouldNotRenameRef;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorCouldNotRenameRef2;
+
+ /** */
+ public static String BranchSelectionDialog_BranchSelectionDialog_CreateFailedTitle;
+
+ /** */
+ public static String BranchSelectionDialog_BranchSelectionDialog_RenamedFailedTitle;
+
+ /** */
+ public static String BranchSelectionDialog_BranchSuffix_Current;
+
+ /** */
+ public static String BranchSelectionDialog_ResetType;
+
+ /** */
+ public static String BranchSelectionDialog_ResetTypeSoft;
+
+ /** */
+ public static String BranchSelectionDialog_ResetTypeMixed;
+
+ /** */
+ public static String BranchSelectionDialog_ResetTypeHard;
+
+ /** */
+ public static String BranchSelectionDialog_Tags;
+
+ /** */
+ public static String BranchSelectionDialog_RemoteBranches;
+
+ /** */
+ public static String BranchSelectionDialog_LocalBranches;
+
+ /** */
+ public static String BranchSelectionDialog_NoBranchSeletectTitle;
+
+ /** */
+ public static String BranchSelectionDialog_ReallyResetTitle;
+
+ /** */
+ public static String BranchSelectionDialog_ReallyResetMessage;
+
+ /** */
+ public static String BranchSelectionDialog_QuestionNewBranchTitle;
+
+ /** */
+ public static String BranchSelectionDialog_QuestionNewBranchNameTitle;
+
+ /** */
+ public static String BranchSelectionDialog_QuestionNewBranchNameMessage;
+
+ /** */
+ public static String BranchSelectionDialog_QuestionNewBranchMessage;
+
+ /** */
+ public static String BranchSelectionDialog_NewBranch;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorAlreadyExists;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorCouldNotResolve;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorInvalidRefName;
+
+ /** */
+ public static String BranchSelectionDialog_ErrorRenameFailed;
+
+ /** */
+ public static String BranchSelectionDialog_OkCheckout;
+
+ /** */
+ public static String BranchSelectionDialog_NoBranchSeletectMessage;
+
+ /** */
+ public static String BranchSelectionDialog_Refs;
+
+ /** */
+ public static String BranchSelectionDialog_Rename;
+
+ /** */
+ public static String HistoryPage_ShowAllVersionsForProject;
+
+ /** */
+ public static String HistoryPage_ShowAllVersionsForRepo;
+
+ /** */
+ public static String HistoryPage_ShowAllVersionsForFolder;
+
+ /** */
+ public static String Decorator_exceptionMessage;
+
+ /** */
+ public static String DecoratorPreferencesPage_addVariablesTitle;
+
+ /** */
+ public static String DecoratorPreferencesPage_addVariablesAction;
+
+ /** */
+ public static String DecoratorPreferencesPage_recomputeAncestorDecorations;
+
+ /** */
+ public static String DecoratorPreferencesPage_recomputeAncestorDecorationsTooltip;
+
+ /** */
+ public static String DecoratorPreferencesPage_computeRecursiveLimit;
+
+ /** */
+ public static String DecoratorPreferencesPage_computeRecursiveLimitTooltip;
+
+ /** */
+ public static String DecoratorPreferencesPage_invalidInput;
+
+ /** */
+ public static String DecoratorPreferencesPage_description;
+
+ /** */
+ public static String DecoratorPreferencesPage_decorationSettings;
+
+ /** */
+ public static String DecoratorPreferencesPage_preview;
+
+ /** */
+ public static String DecoratorPreferencesPage_fileFormatLabel;
+
+ /** */
+ public static String DecoratorPreferencesPage_folderFormatLabel;
+
+ /** */
+ public static String DecoratorPreferencesPage_projectFormatLabel;
+
+ /** */
+ public static String DecoratorPreferencesPage_fileFormatDefault;
+
+ /** */
+ public static String DecoratorPreferencesPage_projectFormatDefault;
+
+ /** */
+ public static String DecoratorPreferencesPage_folderFormatDefault;
+
+ /** */
+ public static String DecoratorPreferencesPage_generalTabFolder;
+
+ /** */
+ public static String DecoratorPreferencesPage_bindingResourceName;
+
+ /** */
+ public static String DecoratorPreferencesPage_bindingBranchName;
+
+ /** */
+ public static String DecoratorPreferencesPage_bindingDirtyFlag;
+
+ /** */
+ public static String DecoratorPreferencesPage_bindingStagedFlag;
+
+ /** */
+ public static String DecoratorPreferencesPage_selectFormats;
+
+ /** */
+ public static String DecoratorPreferencesPage_selectVariablesToAdd;
+
+ /** */
+ public static String DecoratorPreferencesPage_textLabel;
+
+ /** */
+ public static String DecoratorPreferencesPage_iconLabel;
+
+ /** */
+ public static String DecoratorPreferencesPage_labelDecorationsLink;
+
+ /** */
+ public static String DecoratorPreferencesPage_iconsShowTracked;
+
+ /** */
+ public static String DecoratorPreferencesPage_iconsShowUntracked;
+
+ /** */
+ public static String DecoratorPreferencesPage_iconsShowStaged;
+
+ /** */
+ public static String DecoratorPreferencesPage_iconsShowConflicts;
+
+ /** */
+ public static String DecoratorPreferencesPage_iconsShowAssumeValid;
+
+ static {
+ initializeMessages("org.eclipse.egit.ui.uitext", UIText.class);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java
new file mode 100644
index 000000000..a24ed34fb
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/EditableRevision.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * Copyright (C) 2009, Yann Simon <yann.simon.fr@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.eclipse.compare.IContentChangeListener;
+import org.eclipse.compare.IContentChangeNotifier;
+import org.eclipse.compare.IEditableContent;
+import org.eclipse.compare.ISharedDocumentAdapter;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.internal.ContentChangeNotifier;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.internal.ui.history.FileRevisionTypedElement;
+import org.eclipse.team.internal.ui.synchronize.EditableSharedDocumentAdapter;
+
+/**
+ * @author simon
+ *
+ */
+public class EditableRevision extends FileRevisionTypedElement implements
+ ITypedElement, IEditableContent, IContentChangeNotifier {
+
+ private byte[] modifiedContent;
+
+ private ContentChangeNotifier fChangeNotifier;
+
+ private EditableSharedDocumentAdapter sharedDocumentAdapter;
+
+ /**
+ * @param fileRevision
+ */
+ public EditableRevision(IFileRevision fileRevision) {
+ super(fileRevision);
+ }
+
+ public boolean isEditable() {
+ return true;
+ }
+
+ public ITypedElement replace(ITypedElement dest, ITypedElement src) {
+ return null;
+ }
+
+ @Override
+ public InputStream getContents() throws CoreException {
+ if (modifiedContent != null) {
+ return new ByteArrayInputStream(modifiedContent);
+ }
+ return super.getContents();
+ }
+
+ public void setContent(byte[] newContent) {
+ modifiedContent = newContent;
+ fireContentChanged();
+ }
+
+ /**
+ * @return the modified content
+ */
+ public byte[] getModifiedContent() {
+ return modifiedContent;
+ }
+
+ public Object getAdapter(Class adapter) {
+ if (adapter == ISharedDocumentAdapter.class) {
+ return getSharedDocumentAdapter();
+ }
+ return Platform.getAdapterManager().getAdapter(this, adapter);
+ }
+
+ private synchronized ISharedDocumentAdapter getSharedDocumentAdapter() {
+ if (sharedDocumentAdapter == null)
+ sharedDocumentAdapter = new EditableSharedDocumentAdapter(
+ new EditableSharedDocumentAdapter.ISharedDocumentAdapterListener() {
+ public void handleDocumentConnected() {
+ }
+
+ public void handleDocumentFlushed() {
+ }
+
+ public void handleDocumentDeleted() {
+ }
+
+ public void handleDocumentSaved() {
+ }
+
+ public void handleDocumentDisconnected() {
+ }
+ });
+ return sharedDocumentAdapter;
+ }
+
+ public void addContentChangeListener(IContentChangeListener listener) {
+ if (fChangeNotifier == null)
+ fChangeNotifier = new ContentChangeNotifier(this);
+ fChangeNotifier.addContentChangeListener(listener);
+ }
+
+ public void removeContentChangeListener(IContentChangeListener listener) {
+ if (fChangeNotifier != null) {
+ fChangeNotifier.removeContentChangeListener(listener);
+ if (fChangeNotifier.isEmpty())
+ fChangeNotifier = null;
+ }
+ }
+
+ /**
+ * Notifies all registered <code>IContentChangeListener</code>s of a content
+ * change.
+ */
+ protected void fireContentChanged() {
+ if (fChangeNotifier == null || fChangeNotifier.isEmpty()) {
+ return;
+ }
+ fChangeNotifier.fireContentChanged();
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java
new file mode 100644
index 000000000..60d7da185
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitCompareFileRevisionEditorInput.java
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.compare.CompareConfiguration;
+import org.eclipse.compare.IEditableContent;
+import org.eclipse.compare.IResourceProvider;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.structuremergeviewer.DiffNode;
+import org.eclipse.compare.structuremergeviewer.Differencer;
+import org.eclipse.compare.structuremergeviewer.ICompareInput;
+import org.eclipse.compare.structuremergeviewer.IDiffElement;
+import org.eclipse.compare.structuremergeviewer.IStructureComparator;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFileState;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IStorage;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.egit.core.Activator;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.team.internal.core.history.LocalFileRevision;
+import org.eclipse.team.internal.ui.TeamUIMessages;
+import org.eclipse.team.internal.ui.TeamUIPlugin;
+import org.eclipse.team.internal.ui.Utils;
+import org.eclipse.team.internal.ui.history.FileRevisionTypedElement;
+import org.eclipse.team.internal.ui.synchronize.LocalResourceTypedElement;
+import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+
+/**
+ * The input provider for the compare editor when working on resources
+ * under Git control.
+ */
+public class GitCompareFileRevisionEditorInput extends SaveableCompareEditorInput {
+
+ private ITypedElement left;
+ private ITypedElement right;
+
+ /**
+ * Creates a new CompareFileRevisionEditorInput.
+ * @param left
+ * @param right
+ * @param page
+ */
+ public GitCompareFileRevisionEditorInput(ITypedElement left, ITypedElement right, IWorkbenchPage page) {
+ super(new CompareConfiguration(), page);
+ this.left = left;
+ this.right = right;
+ }
+
+ FileRevisionTypedElement getRightRevision() {
+ if (right instanceof FileRevisionTypedElement) {
+ return (FileRevisionTypedElement) right;
+ }
+ return null;
+ }
+
+ FileRevisionTypedElement getLeftRevision() {
+ if (left instanceof FileRevisionTypedElement) {
+ return (FileRevisionTypedElement) left;
+ }
+ return null;
+ }
+
+ private static void ensureContentsCached(FileRevisionTypedElement left, FileRevisionTypedElement right,
+ IProgressMonitor monitor) {
+ if (left != null) {
+ try {
+ left.cacheContents(monitor);
+ } catch (CoreException e) {
+ TeamUIPlugin.log(e);
+ }
+ }
+ if (right != null) {
+ try {
+ right.cacheContents(monitor);
+ } catch (CoreException e) {
+ TeamUIPlugin.log(e);
+ }
+ }
+ }
+
+ private boolean isLeftEditable(ICompareInput input) {
+ Object tmpLeft = input.getLeft();
+ return isEditable(tmpLeft);
+ }
+
+ private boolean isRightEditable(ICompareInput input) {
+ Object tmpRight = input.getRight();
+ return isEditable(tmpRight);
+ }
+
+ private boolean isEditable(Object object) {
+ if (object instanceof IEditableContent) {
+ return ((IEditableContent) object).isEditable();
+ }
+ return false;
+ }
+
+ private IResource getResource(ICompareInput input) {
+ if (getLocalElement() != null) {
+ return ((IResourceProvider) getLocalElement()).getResource();
+ }
+ return null;
+ }
+
+ private ICompareInput createCompareInput() {
+ return compare(left, right);
+ }
+
+ private DiffNode compare(ITypedElement left, ITypedElement right) {
+ if (left.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ // return new MyDiffContainer(null, left,right);
+ DiffNode diffNode = new DiffNode(null,Differencer.CHANGE,null,left,right);
+ ITypedElement[] lc = (ITypedElement[])((IStructureComparator)left).getChildren();
+ ITypedElement[] rc = (ITypedElement[])((IStructureComparator)right).getChildren();
+ int li=0;
+ int ri=0;
+ while (li<lc.length && ri<rc.length) {
+ ITypedElement ln = lc[li];
+ ITypedElement rn = rc[ri];
+ int compareTo = ln.getName().compareTo(rn.getName());
+ // TODO: Git ordering!
+ if (compareTo == 0) {
+ if (!ln.equals(rn))
+ diffNode.add(compare(ln,rn));
+ ++li;
+ ++ri;
+ } else if (compareTo < 0) {
+ DiffNode childDiffNode = new DiffNode(Differencer.ADDITION, null, ln, null);
+ diffNode.add(childDiffNode);
+ if (ln.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)ln).getChildren();
+ if(children != null && children.length > 0) {
+ for (ITypedElement child : children) {
+ childDiffNode.add(addDirectoryFiles(child, Differencer.ADDITION));
+ }
+ }
+ }
+ ++li;
+ } else {
+ DiffNode childDiffNode = new DiffNode(Differencer.DELETION, null, null, rn);
+ diffNode.add(childDiffNode);
+ if (rn.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)rn).getChildren();
+ if(children != null && children.length > 0) {
+ for (ITypedElement child : children) {
+ childDiffNode.add(addDirectoryFiles(child, Differencer.DELETION));
+ }
+ }
+ }
+ ++ri;
+ }
+ }
+ while (li<lc.length) {
+ ITypedElement ln = lc[li];
+ DiffNode childDiffNode = new DiffNode(Differencer.ADDITION, null, ln, null);
+ diffNode.add(childDiffNode);
+ if (ln.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)ln).getChildren();
+ if(children != null && children.length > 0) {
+ for (ITypedElement child : children) {
+ childDiffNode.add(addDirectoryFiles(child, Differencer.ADDITION));
+ }
+ }
+ }
+ ++li;
+ }
+ while (ri<rc.length) {
+ ITypedElement rn = rc[ri];
+ DiffNode childDiffNode = new DiffNode(Differencer.DELETION, null, null, rn);
+ diffNode.add(childDiffNode);
+ if (rn.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)rn).getChildren();
+ if(children != null && children.length > 0) {
+ for (ITypedElement child : children) {
+ childDiffNode.add(addDirectoryFiles(child, Differencer.DELETION));
+ }
+ }
+ }
+ ++ri;
+ }
+ return diffNode;
+ } else {
+ return new DiffNode(left, right);
+ }
+ }
+
+ private DiffNode addDirectoryFiles(ITypedElement elem, int diffType) {
+ ITypedElement l = null;
+ ITypedElement r = null;
+ if (diffType == Differencer.DELETION) {
+ r = elem;
+ } else {
+ l = elem;
+ }
+
+ if (elem.getType().equals(ITypedElement.FOLDER_TYPE)) {
+ DiffNode diffNode = null;
+ diffNode = new DiffNode(null,Differencer.CHANGE,null,l,r);
+ ITypedElement[] children = (ITypedElement[])((IStructureComparator)elem).getChildren();
+ for (ITypedElement child : children) {
+ diffNode.add(addDirectoryFiles(child, diffType));
+ }
+ return diffNode;
+ } else {
+ return new DiffNode(diffType, null, l, r);
+ }
+ }
+
+ private void initLabels(ICompareInput input) {
+ CompareConfiguration cc = getCompareConfiguration();
+ if(left != null && left instanceof GitResourceNode) {
+ String ci = ((GitResourceNode)left).getContentIdentifier();
+ if(ci != null) {
+ cc.setLeftLabel(ci.substring(0, 7) + "..");
+ }
+ }
+ if(right != null && right instanceof GitResourceNode) {
+ String ci = ((GitResourceNode)right).getContentIdentifier();
+ if(ci != null) {
+ cc.setRightLabel(ci.substring(0, 7) + "..");
+ }
+ }
+ if (getLeftRevision() != null) {
+ String leftLabel = getFileRevisionLabel(getLeftRevision());
+ cc.setLeftLabel(leftLabel);
+ } else if (getResource(input) != null) {
+ String label = NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_workspace, new Object[]{ input.getLeft().getName() });
+ cc.setLeftLabel(label);
+ }
+ if (getRightRevision() != null) {
+ String rightLabel = getFileRevisionLabel(getRightRevision());
+ cc.setRightLabel(rightLabel);
+ }
+ }
+
+ private String getFileRevisionLabel(FileRevisionTypedElement element) {
+ Object fileObject = element.getFileRevision();
+ if (fileObject instanceof LocalFileRevision){
+ return NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_localRevision, new Object[]{element.getName(), element.getTimestamp()});
+ } else {
+ return NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_repository, new Object[]{ element.getName(), element.getContentIdentifier()});
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.compare.CompareEditorInput#getToolTipText()
+ */
+ public String getToolTipText() {
+ Object[] titleObject = new Object[3];
+ titleObject[0] = getLongName(left);
+ titleObject[1] = getContentIdentifier(getLeftRevision());
+ titleObject[2] = getContentIdentifier(getRightRevision());
+ return NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_compareResourceAndVersions, titleObject);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.compare.CompareEditorInput#getTitle()
+ */
+ public String getTitle() {
+ Object[] titleObject = new Object[3];
+ titleObject[0] = getShortName(left);
+ titleObject[1] = getContentIdentifier(getLeftRevision());
+ titleObject[2] = getContentIdentifier(getRightRevision());
+ return NLS.bind(TeamUIMessages.CompareFileRevisionEditorInput_compareResourceAndVersions, titleObject);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.compare.CompareEditorInput#getAdapter(java.lang.Class)
+ */
+ public Object getAdapter(Class adapter) {
+ if (adapter == IFile.class || adapter == IResource.class) {
+ if (getLocalElement() != null) {
+ return getLocalElement().getResource();
+ }
+ return null;
+ }
+ return super.getAdapter(adapter);
+ }
+
+ private String getShortName(ITypedElement element) {
+ if (element instanceof FileRevisionTypedElement){
+ FileRevisionTypedElement fileRevisionElement = (FileRevisionTypedElement) element;
+ return fileRevisionElement.getName();
+ }
+ else if (element instanceof LocalResourceTypedElement){
+ LocalResourceTypedElement typedContent = (LocalResourceTypedElement) element;
+ return typedContent.getResource().getName();
+ }
+ return element.getName();
+ }
+
+ private String getLongName(ITypedElement element) {
+ if (element instanceof FileRevisionTypedElement){
+ FileRevisionTypedElement fileRevisionElement = (FileRevisionTypedElement) element;
+ return fileRevisionElement.getPath();
+ }
+ else if (element instanceof LocalResourceTypedElement){
+ LocalResourceTypedElement typedContent = (LocalResourceTypedElement) element;
+ return typedContent.getResource().getFullPath().toString();
+ }
+ return element.getName();
+ }
+
+ private String getContentIdentifier(ITypedElement element){
+ if (element instanceof FileRevisionTypedElement){
+ FileRevisionTypedElement fileRevisionElement = (FileRevisionTypedElement) element;
+ Object fileObject = fileRevisionElement.getFileRevision();
+ if (fileObject instanceof LocalFileRevision){
+ try {
+ IStorage storage = ((LocalFileRevision) fileObject).getStorage(new NullProgressMonitor());
+ if (Utils.getAdapter(storage, IFileState.class) != null){
+ //local revision
+ return TeamUIMessages.CompareFileRevisionEditorInput_0;
+ } else if (Utils.getAdapter(storage, IFile.class) != null) {
+ //current revision
+ return TeamUIMessages.CompareFileRevisionEditorInput_1;
+ }
+ } catch (CoreException e) {
+ Activator.logError("Problem getting content identifier", e);
+ }
+ } else {
+ return fileRevisionElement.getContentIdentifier();
+ }
+ }
+ return TeamUIMessages.CompareFileRevisionEditorInput_2;
+ }
+
+ @Override
+ protected void fireInputChange() {
+ }
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.team.ui.synchronize.SaveableCompareEditorInput#contentsCreated()
+// */
+// protected void contentsCreated() {
+// super.contentsCreated();
+// notifier.initialize();
+// }
+//
+// /* (non-Javadoc)
+// * @see org.eclipse.team.ui.synchronize.SaveableCompareEditorInput#handleDispose()
+// */
+// protected void handleDispose() {
+// super.handleDispose();
+// notifier.dispose();
+// if (getLocalElement() != null) {
+// getLocalElement().discardBuffer();
+// }
+// }
+//
+ private LocalResourceTypedElement getLocalElement() {
+ if (left instanceof LocalResourceTypedElement) {
+ return (LocalResourceTypedElement) left;
+ }
+ return null;
+ }
+
+ @Override
+ protected ICompareInput prepareCompareInput(IProgressMonitor monitor)
+ throws InvocationTargetException, InterruptedException {
+ ICompareInput input = createCompareInput();
+ getCompareConfiguration().setLeftEditable(isLeftEditable(input));
+ getCompareConfiguration().setRightEditable(isRightEditable(input));
+ ensureContentsCached(getLeftRevision(), getRightRevision(), monitor);
+ initLabels(input);
+ setTitle(NLS.bind(TeamUIMessages.SyncInfoCompareInput_title, new String[] { input.getName() }));
+
+ // The compare editor (Structure Compare) will show the diff filenames
+ // with their project relative path. So, no need to also show directory entries.
+ DiffNode flatDiffNode = new DiffNode(null,Differencer.CHANGE,null,left,right);
+ flatDiffView(flatDiffNode, (DiffNode) input);
+
+ return flatDiffNode;
+ }
+
+ private void flatDiffView(DiffNode rootNode, DiffNode currentNode) {
+ if(currentNode != null) {
+ IDiffElement[] dElems = currentNode.getChildren();
+ if(dElems != null) {
+ for(IDiffElement dElem : dElems) {
+ DiffNode dNode = (DiffNode) dElem;
+ if(dNode.getChildren() != null && dNode.getChildren().length > 0) {
+ flatDiffView(rootNode, dNode);
+ } else {
+ rootNode.add(dNode);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitResourceNode.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitResourceNode.java
new file mode 100644
index 000000000..d6830009d
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/GitResourceNode.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.eclipse.compare.BufferedContent;
+import org.eclipse.compare.CompareUI;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.compare.structuremergeviewer.IStructureComparator;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.jgit.lib.FileTreeEntry;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.lib.TreeEntry;
+
+/**
+ * A resource node is for letting Eclipse access data in the git repo in a hierarchical
+ * fashion, e.g. for the compare editor.
+ */
+public class GitResourceNode extends BufferedContent implements IStructureComparator, ITypedElement {
+ TreeEntry entry;
+ GitResourceNode[] children;
+ String contentIdentifier;
+
+ /**
+ * Construct a resource not for a {@link TreeEntry}
+ * @param e The {@link TreeEntry}
+ */
+ public GitResourceNode(TreeEntry e) {
+ entry = e;
+ }
+
+ public Object[] getChildren() {
+ if (children != null)
+ return children;
+ if (entry instanceof Tree) {
+ try {
+ Tree t = (Tree)entry;
+ children = new GitResourceNode[t.memberCount()];
+ for (int i=0; i<children.length; ++i) {
+ children[i] = new GitResourceNode(t.members()[i]);
+ }
+ } catch (IOException e) {
+ // TODO: eclipse error handling
+ e.printStackTrace();
+ children = new GitResourceNode[0];
+ }
+ }
+ return children;
+ }
+
+ public boolean equals(Object obj) {
+ return entry.getId().equals(((GitResourceNode)obj).entry.getId());
+ }
+
+ protected InputStream createStream() throws CoreException {
+ if (entry instanceof FileTreeEntry) {
+ try {
+ ObjectId id = entry.getId();
+ ObjectLoader reader = entry.getRepository().openBlob(id);
+ byte[] bytes = reader.getBytes();
+ return new ByteArrayInputStream(bytes);
+ } catch (IOException e) {
+ // TODO: eclipse error handling
+ e.printStackTrace();
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public String getName() {
+ if (entry != null)
+ return entry.getFullName();
+ else
+ return "<none>";
+ }
+
+ public Image getImage() {
+ return CompareUI.getImage(getType());
+ }
+
+ public String getType() {
+ if (entry instanceof Tree)
+ return ITypedElement.FOLDER_TYPE;
+ else {
+ if (entry != null) {
+ String name = entry.getName();
+ if (name != null) {
+ int index = name.lastIndexOf('.');
+ if (index == -1)
+ return ""; //$NON-NLS-1$
+ if (index == (name.length() - 1))
+ return ""; //$NON-NLS-1$
+ return name.substring(index + 1);
+ }
+ return "";
+ } else
+ return "";
+ }
+ }
+
+ /**
+ * @return a user friendly version identification of the resource
+ */
+ public String getContentIdentifier() {
+ return contentIdentifier;
+ }
+}
+
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/SWTUtils.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/SWTUtils.java
new file mode 100644
index 000000000..976bc0687
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/SWTUtils.java
@@ -0,0 +1,595 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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 org.eclipse.egit.ui.internal;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.dialogs.PreferenceLinkArea;
+import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer;
+
+/**
+ * A collection of factory methods for creating common SWT controls
+ */
+public class SWTUtils {
+
+ /** */
+ public static final int MARGINS_DEFAULT = -1;
+
+ /** */
+ public static final int MARGINS_NONE = 0;
+
+ /** */
+ public static final int MARGINS_DIALOG = 1;
+
+ /**
+ * Creates a preference link which will open in the specified container
+ *
+ * @param container
+ * @param parent
+ * @param pageId
+ * @param text
+ *
+ * @return the created link
+ */
+ public static PreferenceLinkArea createPreferenceLink(
+ IWorkbenchPreferenceContainer container, Composite parent,
+ String pageId, String text) {
+ final PreferenceLinkArea area = new PreferenceLinkArea(parent,
+ SWT.NONE, pageId, text, container, null);
+ return area;
+ }
+
+ /**
+ * Creates a grid data with the specified metrics
+ *
+ * @param width
+ * @param height
+ * @param hFill
+ * @param vFill
+ *
+ * @return the created grid data
+ */
+ public static GridData createGridData(int width, int height, boolean hFill,
+ boolean vFill) {
+ return createGridData(width, height, hFill ? SWT.FILL : SWT.BEGINNING,
+ vFill ? SWT.FILL : SWT.CENTER, hFill, vFill);
+ }
+
+ /**
+ * Creates a grid data with the specified metrics
+ *
+ * @param width
+ * @param height
+ * @param hAlign
+ * @param vAlign
+ * @param hGrab
+ * @param vGrab
+ *
+ * @return the created grid data
+ */
+ public static GridData createGridData(int width, int height, int hAlign,
+ int vAlign, boolean hGrab, boolean vGrab) {
+ final GridData gd = new GridData(hAlign, vAlign, hGrab, vGrab);
+ gd.widthHint = width;
+ gd.heightHint = height;
+ return gd;
+ }
+
+ /**
+ * Creates a horizontal grid data with the default metrics
+ *
+ * @return the created grid data
+ */
+ public static GridData createHFillGridData() {
+ return createHFillGridData(1);
+ }
+
+ /**
+ * Creates a horizontal grid data with the specified span
+ *
+ * @param span
+ *
+ * @return the created grid data
+ */
+ public static GridData createHFillGridData(int span) {
+ final GridData gd = createGridData(0, SWT.DEFAULT, SWT.FILL,
+ SWT.CENTER, true, false);
+ gd.horizontalSpan = span;
+ return gd;
+ }
+
+ /**
+ * Creates a horizontal fill composite with the specified margins
+ *
+ * @param parent
+ * @param margins
+ *
+ * @return the created composite
+ */
+ public static Composite createHFillComposite(Composite parent, int margins) {
+ return createHFillComposite(parent, margins, 1);
+ }
+
+ /**
+ * Creates a horizontal fill composite with the specified margins and
+ * columns
+ *
+ * @param parent
+ * @param margins
+ * @param columns
+ *
+ * @return the created composite
+ */
+ public static Composite createHFillComposite(Composite parent, int margins,
+ int columns) {
+ final Composite composite = new Composite(parent, SWT.NONE);
+ composite.setFont(parent.getFont());
+ composite.setLayoutData(createHFillGridData());
+ composite.setLayout(createGridLayout(columns,
+ new PixelConverter(parent), margins));
+ return composite;
+ }
+
+ /**
+ * Creates a horizontal/vertical fill composite with the specified margins
+ *
+ * @param parent
+ * @param margins
+ *
+ * @return the created composite
+ */
+ public static Composite createHVFillComposite(Composite parent, int margins) {
+ return createHVFillComposite(parent, margins, 1);
+ }
+
+ /**
+ * Creates a horizontal/vertical fill composite with the specified margins
+ * and columns
+ *
+ * @param parent
+ * @param margins
+ * @param columns
+ *
+ * @return the created composite
+ */
+ public static Composite createHVFillComposite(Composite parent,
+ int margins, int columns) {
+ final Composite composite = new Composite(parent, SWT.NONE);
+ composite.setFont(parent.getFont());
+ composite.setLayoutData(createHVFillGridData());
+ composite.setLayout(createGridLayout(columns,
+ new PixelConverter(parent), margins));
+ return composite;
+ }
+
+ /**
+ * Creates a horizontal fill group with the specified text and margins
+ *
+ * @param parent
+ * @param text
+ * @param margins
+ * @return the created group
+ */
+ public static Group createHFillGroup(Composite parent, String text,
+ int margins) {
+ return createHFillGroup(parent, text, margins, 1);
+ }
+
+ /**
+ * Creates a horizontal fill group with the specified text, margins and rows
+ *
+ * @param parent
+ * @param text
+ * @param margins
+ * @param rows
+ *
+ * @return the created group
+ */
+ public static Group createHFillGroup(Composite parent, String text,
+ int margins, int rows) {
+ final Group group = new Group(parent, SWT.NONE);
+ group.setFont(parent.getFont());
+ group.setLayoutData(createHFillGridData());
+ if (text != null)
+ group.setText(text);
+ group.setLayout(createGridLayout(rows, new PixelConverter(parent),
+ margins));
+ return group;
+ }
+
+ /**
+ * Creates a horizontal/vertical fill group with the specified text and
+ * margins
+ *
+ * @param parent
+ * @param text
+ * @param margins
+ *
+ * @return the created group
+ */
+ public static Group createHVFillGroup(Composite parent, String text,
+ int margins) {
+ return createHVFillGroup(parent, text, margins, 1);
+ }
+
+ /**
+ * Creates a horizontal/vertical fill group with the specified text, margins
+ * and rows
+ *
+ * @param parent
+ * @param text
+ * @param margins
+ * @param rows
+ *
+ * @return the created group
+ */
+ public static Group createHVFillGroup(Composite parent, String text,
+ int margins, int rows) {
+ final Group group = new Group(parent, SWT.NONE);
+ group.setFont(parent.getFont());
+ group.setLayoutData(createHVFillGridData());
+ if (text != null)
+ group.setText(text);
+ group.setLayout(createGridLayout(rows, new PixelConverter(parent),
+ margins));
+ return group;
+ }
+
+ /**
+ * Creates a horizontal/vertical fill grid data with the default metrics
+ *
+ * @return the created grid data
+ */
+ public static GridData createHVFillGridData() {
+ return createHVFillGridData(1);
+ }
+
+ /**
+ * Creates a horizontal/vertical fill grid data with the specified span
+ *
+ * @param span
+ *
+ * @return the created grid data
+ */
+ public static GridData createHVFillGridData(int span) {
+ final GridData gd = createGridData(0, 0, true, true);
+ gd.horizontalSpan = span;
+ return gd;
+ }
+
+ /**
+ * Creates a grid layout with the specified number of columns and the
+ * standard spacings.
+ *
+ * @param numColumns
+ * the number of columns
+ * @param converter
+ * the pixel converter
+ * @param margins
+ * one of <code>MARGINS_DEFAULT</code>, <code>MARGINS_NONE</code>
+ * or <code>MARGINS_DIALOG</code>.
+ *
+ * @return the created grid layout
+ */
+ public static GridLayout createGridLayout(int numColumns,
+ PixelConverter converter, int margins) {
+ Assert.isTrue(margins == MARGINS_DEFAULT || margins == MARGINS_NONE
+ || margins == MARGINS_DIALOG);
+
+ final GridLayout layout = new GridLayout(numColumns, false);
+ layout.horizontalSpacing = converter
+ .convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+ layout.verticalSpacing = converter
+ .convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+
+ switch (margins) {
+ case MARGINS_NONE:
+ layout.marginLeft = layout.marginRight = 0;
+ layout.marginTop = layout.marginBottom = 0;
+ break;
+ case MARGINS_DIALOG:
+ layout.marginLeft = layout.marginRight = converter
+ .convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ layout.marginTop = layout.marginBottom = converter
+ .convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ break;
+ case MARGINS_DEFAULT:
+ layout.marginLeft = layout.marginRight = layout.marginWidth;
+ layout.marginTop = layout.marginBottom = layout.marginHeight;
+ }
+ layout.marginWidth = layout.marginHeight = 0;
+ return layout;
+ }
+
+ /**
+ * Creates a label with the specified message
+ *
+ * @param parent
+ * @param message
+ *
+ * @return the created label
+ */
+ public static Label createLabel(Composite parent, String message) {
+ return createLabel(parent, message, 1);
+ }
+
+ /**
+ * Creates a label with the specified message and span
+ *
+ * @param parent
+ * @param message
+ * @param span
+ *
+ * @return the created label
+ */
+ public static Label createLabel(Composite parent, String message, int span) {
+ final Label label = new Label(parent, SWT.WRAP);
+ if (message != null)
+ label.setText(message);
+ label.setLayoutData(createHFillGridData(span));
+ return label;
+ }
+
+ /**
+ * Creates a check box with the specified message
+ *
+ * @param parent
+ * @param message
+ *
+ * @return the created check box
+ */
+ public static Button createCheckBox(Composite parent, String message) {
+ return createCheckBox(parent, message, 1);
+ }
+
+ /**
+ * Creates a check box with the specified message and span
+ *
+ * @param parent
+ * @param message
+ * @param span
+ *
+ * @return the created check box
+ */
+ public static Button createCheckBox(Composite parent, String message,
+ int span) {
+ final Button button = new Button(parent, SWT.CHECK);
+ button.setText(message);
+ button.setLayoutData(createHFillGridData(span));
+ return button;
+ }
+
+ /**
+ * Creates a radio button with the specified message
+ *
+ * @param parent
+ * @param message
+ *
+ * @return the created radio button
+ */
+ public static Button createRadioButton(Composite parent, String message) {
+ return createRadioButton(parent, message, 1);
+ }
+
+ /**
+ * Creates a radio button with the specified message and span
+ *
+ * @param parent
+ * @param message
+ * @param span
+ *
+ * @return the created radio button
+ */
+ public static Button createRadioButton(Composite parent, String message,
+ int span) {
+ final Button button = new Button(parent, SWT.RADIO);
+ button.setText(message);
+ button.setLayoutData(createHFillGridData(span));
+ return button;
+ }
+
+ /**
+ * Creates a text control
+ *
+ * @param parent
+ *
+ * @return the created text control
+ */
+ public static Text createText(Composite parent) {
+ return createText(parent, 1);
+ }
+
+ /**
+ * Creates a text control with the specified span
+ *
+ * @param parent
+ * @param span
+ *
+ * @return the created text control
+ */
+ public static Text createText(Composite parent, int span) {
+ final Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
+ text.setLayoutData(createHFillGridData(span));
+ return text;
+ }
+
+ /**
+ * Creates a place holder with the specified height and span
+ *
+ * @param parent
+ * @param heightInChars
+ * @param span
+ *
+ * @return the created place holder
+ */
+ public static Control createPlaceholder(Composite parent,
+ int heightInChars, int span) {
+ Assert.isTrue(heightInChars > 0);
+ final Control placeHolder = new Composite(parent, SWT.NONE);
+ final GridData gd = new GridData(SWT.BEGINNING, SWT.TOP, false, false);
+ gd.heightHint = new PixelConverter(parent)
+ .convertHeightInCharsToPixels(heightInChars);
+ gd.horizontalSpan = span;
+ placeHolder.setLayoutData(gd);
+ return placeHolder;
+ }
+
+ /**
+ * Creates a place holder with the specified height
+ *
+ * @param parent
+ * @param heightInChars
+ * @return the created place holder
+ */
+ public static Control createPlaceholder(Composite parent, int heightInChars) {
+ return createPlaceholder(parent, heightInChars, 1);
+ }
+
+ /**
+ * Creates a pixel converter
+ *
+ * @param control
+ *
+ * @return the created pixel converter
+ */
+ public static PixelConverter createDialogPixelConverter(Control control) {
+ Dialog.applyDialogFont(control);
+ return new PixelConverter(control);
+ }
+
+ /**
+ * Calculates the size of the specified controls, using the specified
+ * converter
+ *
+ * @param converter
+ * @param controls
+ *
+ * @return the size of the control(s)
+ */
+ public static int calculateControlSize(PixelConverter converter,
+ Control[] controls) {
+ return calculateControlSize(converter, controls, 0, controls.length - 1);
+ }
+
+ /**
+ * Calculates the size of the specified subset of controls, using the
+ * specified converter
+ *
+ * @param converter
+ * @param controls
+ * @param start
+ * @param end
+ *
+ * @return the created control
+ */
+ public static int calculateControlSize(PixelConverter converter,
+ Control[] controls, int start, int end) {
+ int minimum = converter
+ .convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
+ for (int i = start; i <= end; i++) {
+ final int length = controls[i]
+ .computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
+ if (minimum < length)
+ minimum = length;
+ }
+ return minimum;
+ }
+
+ /**
+ * Equalizes the specified controls using the specified converter
+ *
+ * @param converter
+ * @param controls
+ */
+ public static void equalizeControls(PixelConverter converter,
+ Control[] controls) {
+ equalizeControls(converter, controls, 0, controls.length - 1);
+ }
+
+ /**
+ * Equalizes the specified subset of controls using the specified converter
+ *
+ * @param converter
+ * @param controls
+ * @param start
+ * @param end
+ */
+ public static void equalizeControls(PixelConverter converter,
+ Control[] controls, int start, int end) {
+ final int size = calculateControlSize(converter, controls, start, end);
+ for (int i = start; i <= end; i++) {
+ final Control button = controls[i];
+ if (button.getLayoutData() instanceof GridData) {
+ ((GridData) button.getLayoutData()).widthHint = size;
+ }
+ }
+ }
+
+ /**
+ * Gets the width of the longest string in <code>strings</code>, using the
+ * specified pixel converter
+ *
+ * @param converter
+ * @param strings
+ *
+ * @return the width of the longest string
+ */
+ public static int getWidthInCharsForLongest(PixelConverter converter,
+ String[] strings) {
+ int minimum = 0;
+ for (int i = 0; i < strings.length; i++) {
+ final int length = converter.convertWidthInCharsToPixels(strings[i]
+ .length());
+ if (minimum < length)
+ minimum = length;
+ }
+ return minimum;
+ }
+
+ private static class PixelConverter {
+
+ private final FontMetrics fFontMetrics;
+
+ public PixelConverter(Control control) {
+ GC gc = new GC(control);
+ try {
+ gc.setFont(control.getFont());
+ fFontMetrics = gc.getFontMetrics();
+ } finally {
+ gc.dispose();
+ }
+ }
+
+ public int convertHeightInCharsToPixels(int chars) {
+ return Dialog.convertHeightInCharsToPixels(fFontMetrics, chars);
+ }
+
+ public int convertHorizontalDLUsToPixels(int dlus) {
+ return Dialog.convertHorizontalDLUsToPixels(fFontMetrics, dlus);
+ }
+
+ public int convertVerticalDLUsToPixels(int dlus) {
+ return Dialog.convertVerticalDLUsToPixels(fFontMetrics, dlus);
+ }
+
+ public int convertWidthInCharsToPixels(int chars) {
+ return Dialog.convertWidthInCharsToPixels(fFontMetrics, chars);
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractOperationAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractOperationAction.java
new file mode 100644
index 000000000..be0cf4dc9
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractOperationAction.java
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+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.egit.ui.Activator;
+import org.eclipse.egit.ui.UIText;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * Common functionality for EGit operations.
+ */
+public abstract class AbstractOperationAction implements IObjectActionDelegate {
+ /**
+ * The active workbench part
+ */
+ protected IWorkbenchPart wp;
+
+ private IWorkspaceRunnable op;
+
+ public void selectionChanged(final IAction act, final ISelection sel) {
+ // work performed in setActivePart
+ }
+
+ public void setActivePart(final IAction act, final IWorkbenchPart part) {
+ wp = part;
+ ISelection sel = part.getSite().getPage().getSelection();
+ final List selection;
+ if (sel instanceof IStructuredSelection && !sel.isEmpty()) {
+ selection = ((IStructuredSelection) sel).toList();
+ } else {
+ selection = Collections.EMPTY_LIST;
+ }
+ op = createOperation(act, selection);
+ act.setEnabled(op != null && wp != null);
+ }
+
+ /**
+ * Instantiate an operation on an action on provided objects.
+ *
+ * @param act
+ * @param selection
+ * @return a {@link IWorkspaceRunnable} for invoking this operation later on
+ */
+ protected abstract IWorkspaceRunnable createOperation(final IAction act,
+ final List selection);
+
+ /**
+ * A method to invoke when the operation is finished.
+ */
+ protected void postOperation() {
+ // Empty
+ }
+
+ public void run(final IAction act) {
+ if (op != null) {
+ try {
+ try {
+ wp.getSite().getWorkbenchWindow().run(true, false,
+ new IRunnableWithProgress() {
+ public void run(final IProgressMonitor monitor)
+ throws InvocationTargetException {
+ try {
+ op.run(monitor);
+ } catch (CoreException ce) {
+ throw new InvocationTargetException(ce);
+ }
+ }
+ });
+ } finally {
+ postOperation();
+ }
+ } catch (Throwable e) {
+ final String msg = NLS.bind(UIText.GenericOperationFailed, act
+ .getText());
+ final IStatus status;
+
+ if (e instanceof InvocationTargetException) {
+ e = e.getCause();
+ }
+
+ if (e instanceof CoreException) {
+ status = ((CoreException) e).getStatus();
+ e = status.getException();
+ } else {
+ status = new Status(IStatus.ERROR, Activator.getPluginId(),
+ 1, msg, e);
+ }
+
+ Activator.logError(msg, e);
+ ErrorDialog.openError(wp.getSite().getShell(), act.getText(),
+ msg, status, status.getSeverity());
+ }
+ }
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractRevObjectAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractRevObjectAction.java
new file mode 100644
index 000000000..6a4b756dc
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractRevObjectAction.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import org.eclipse.egit.ui.internal.history.RevObjectSelectionProvider;
+import org.eclipse.jgit.lib.Repository;
+
+abstract class AbstractRevObjectAction extends AbstractOperationAction {
+
+ /**
+ * Find out which repository is involved here
+ *
+ * @return the Git repository associated with the selected RevObject
+ */
+ protected Repository getActiveRepository() {
+ RevObjectSelectionProvider selectionProvider = (RevObjectSelectionProvider) wp
+ .getSite().getSelectionProvider();
+ return selectionProvider.getActiveRepository();
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractRevObjectOperation.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractRevObjectOperation.java
new file mode 100644
index 000000000..d493ed27b
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AbstractRevObjectOperation.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.jgit.lib.Repository;
+
+abstract class AbstractRevObjectOperation implements IWorkspaceRunnable {
+
+ Repository repository;
+
+ AbstractRevObjectOperation(final Repository repository) {
+ this.repository = repository;
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AssumeUnchanged.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AssumeUnchanged.java
new file mode 100644
index 000000000..bfbaf6cfc
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/AssumeUnchanged.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.egit.core.op.AssumeUnchangedOperation;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * This operation sets the assume-valid bit in the index for the
+ * selected resources.
+ *
+ * @see AssumeUnchangedOperation
+ */
+public class AssumeUnchanged extends AbstractOperationAction {
+ protected IWorkspaceRunnable createOperation(final IAction act,
+ final List sel) {
+ return sel.isEmpty() ? null : new AssumeUnchangedOperation(sel);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/BranchAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/BranchAction.java
new file mode 100644
index 000000000..e8e1b174a
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/BranchAction.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.BranchOperation;
+import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator;
+import org.eclipse.egit.ui.internal.dialogs.BranchSelectionDialog;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Action for selecting a branch and checking it out.
+ *
+ * @see BranchOperation
+ */
+public class BranchAction extends RepositoryAction {
+ @Override
+ public void run(IAction action) {
+ final Repository repository = getRepository(true);
+ if (repository == null)
+ return;
+
+ if (!repository.getRepositoryState().canCheckout()) {
+ MessageDialog.openError(getShell(), "Cannot checkout now",
+ "Repository state:"
+ + repository.getRepositoryState().getDescription());
+ return;
+ }
+
+ BranchSelectionDialog dialog = new BranchSelectionDialog(getShell(), repository);
+ dialog.setShowResetType(false);
+ if (dialog.open() != IDialogConstants.OK_ID) {
+ return;
+ }
+
+ final String refName = dialog.getRefName();
+ try {
+ getTargetPart().getSite().getWorkbenchWindow().run(true, false,
+ new IRunnableWithProgress() {
+ public void run(final IProgressMonitor monitor)
+ throws InvocationTargetException {
+ try {
+ new BranchOperation(repository, refName).run(monitor);
+ GitLightweightDecorator.refresh();
+ } catch (final CoreException ce) {
+ ce.printStackTrace();
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ handle(ce, "Error while switching branches", "Unable to switch branches");
+ }
+ });
+ }
+ }
+ });
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return getRepository(false) != null;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitAction.java
new file mode 100644
index 000000000..e4e75bf4c
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CommitAction.java
@@ -0,0 +1,413 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2007, Jing Xue <jingxue@digizenstudio.com>
+ * Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.TimeZone;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.egit.core.project.GitProjectData;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.egit.ui.internal.dialogs.CommitDialog;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.team.core.TeamException;
+import org.eclipse.team.internal.ui.Utils;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.IndexDiff;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryConfig;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.lib.TreeEntry;
+import org.eclipse.jgit.lib.GitIndex.Entry;
+
+/**
+ * Scan for modified resources in the same project as the selected resources.
+ */
+public class CommitAction extends RepositoryAction {
+
+ private ArrayList<IFile> notIndexed;
+ private ArrayList<IFile> indexChanges;
+ private ArrayList<IFile> files;
+
+ private Commit previousCommit;
+
+ private boolean amendAllowed;
+ private boolean amending;
+
+ @Override
+ public void run(IAction act) {
+ resetState();
+ try {
+ buildIndexHeadDiffList();
+ } catch (IOException e) {
+ Utils.handleError(getTargetPart().getSite().getShell(), e, "Error during commit", "Error occurred computing diffs");
+ return;
+ }
+
+ Repository[] repos = getRepositoriesFor(getProjectsForSelectedResources());
+ Repository repository = null;
+ amendAllowed = repos.length == 1;
+ for (Repository repo : repos) {
+ repository = repo;
+ if (!repo.getRepositoryState().canCommit()) {
+ MessageDialog.openError(getTargetPart().getSite().getShell(),
+ "Cannot commit now", "Repository state:"
+ + repo.getRepositoryState().getDescription());
+ return;
+ }
+ }
+
+ if (files.isEmpty()) {
+ if (amendAllowed) {
+ boolean result = MessageDialog
+ .openQuestion(getTargetPart().getSite().getShell(),
+ "No files to commit",
+ "No changed items were selected. Do you wish to amend the last commit?");
+ if (!result)
+ return;
+ amending = true;
+ } else {
+ MessageDialog.openWarning(getTargetPart().getSite().getShell(), "No files to commit", "No changed items were selected.\n\nAmend is not possible as you have selected multiple repositories.");
+ return;
+ }
+ }
+
+ String author = null;
+ String committer = null;
+ if (repository != null) {
+ final RepositoryConfig config = repository.getConfig();
+ author = config.getAuthorName();
+ final String authorEmail = config.getAuthorEmail();
+ author = author + " <" + authorEmail + ">";
+
+ committer = config.getCommitterName();
+ final String committerEmail = config.getCommitterEmail();
+ committer = committer + " <" + committerEmail + ">";
+ }
+
+ loadPreviousCommit();
+
+ CommitDialog commitDialog = new CommitDialog(getTargetPart().getSite().getShell());
+ commitDialog.setAmending(amending);
+ commitDialog.setAmendAllowed(amendAllowed);
+ commitDialog.setFileList(files);
+ commitDialog.setAuthor(author);
+ commitDialog.setCommitter(committer);
+
+ if (previousCommit != null) {
+ commitDialog.setPreviousCommitMessage(previousCommit.getMessage());
+ PersonIdent previousAuthor = previousCommit.getAuthor();
+ commitDialog.setPreviousAuthor(previousAuthor.getName() + " <" + previousAuthor.getEmailAddress() + ">");
+ }
+
+ if (commitDialog.open() != IDialogConstants.OK_ID)
+ return;
+
+ String commitMessage = commitDialog.getCommitMessage();
+ amending = commitDialog.isAmending();
+ try {
+ performCommit(commitDialog, commitMessage);
+ } catch (TeamException e) {
+ Utils.handleError(getTargetPart().getSite().getShell(), e, "Error during commit", "Error occurred while committing");
+ }
+ }
+
+ private void resetState() {
+ files = new ArrayList<IFile>();
+ notIndexed = new ArrayList<IFile>();
+ indexChanges = new ArrayList<IFile>();
+ amending = false;
+ previousCommit = null;
+ }
+
+ private void loadPreviousCommit() {
+ IProject project = getProjectsForSelectedResources()[0];
+
+ Repository repo = RepositoryMapping.getMapping(project).getRepository();
+ try {
+ ObjectId parentId = repo.resolve(Constants.HEAD);
+ if (parentId != null)
+ previousCommit = repo.mapCommit(parentId);
+ } catch (IOException e) {
+ Utils.handleError(getTargetPart().getSite().getShell(), e, "Error during commit", "Error occurred retrieving last commit");
+ }
+ }
+
+ private void performCommit(CommitDialog commitDialog, String commitMessage)
+ throws TeamException {
+ // System.out.println("Commit Message: " + commitMessage);
+ IFile[] selectedItems = commitDialog.getSelectedFiles();
+
+ HashMap<Repository, Tree> treeMap = new HashMap<Repository, Tree>();
+ try {
+ prepareTrees(selectedItems, treeMap);
+ } catch (IOException e) {
+ throw new TeamException("Preparing trees", e);
+ }
+
+ try {
+ doCommits(commitDialog, commitMessage, treeMap);
+ } catch (IOException e) {
+ throw new TeamException("Committing changes", e);
+ }
+ for (IProject proj : getProjectsForSelectedResources()) {
+ RepositoryMapping.getMapping(proj).fireRepositoryChanged();
+ }
+ }
+
+ private void doCommits(CommitDialog commitDialog, String commitMessage,
+ HashMap<Repository, Tree> treeMap) throws IOException, TeamException {
+
+ final String author = commitDialog.getAuthor();
+ final String committer = commitDialog.getCommitter();
+ final Date commitDate = new Date();
+ final TimeZone timeZone = TimeZone.getDefault();
+
+ final PersonIdent authorIdent = new PersonIdent(author);
+ final PersonIdent committerIdent = new PersonIdent(committer);
+
+ for (java.util.Map.Entry<Repository, Tree> entry : treeMap.entrySet()) {
+ Tree tree = entry.getValue();
+ Repository repo = tree.getRepository();
+ writeTreeWithSubTrees(tree);
+
+ ObjectId currentHeadId = repo.resolve(Constants.HEAD);
+ ObjectId[] parentIds;
+ if (amending) {
+ parentIds = previousCommit.getParentIds();
+ } else {
+ if (currentHeadId != null)
+ parentIds = new ObjectId[] { currentHeadId };
+ else
+ parentIds = new ObjectId[0];
+ }
+ Commit commit = new Commit(repo, parentIds);
+ commit.setTree(tree);
+ commit.setMessage(commitMessage);
+ commit.setAuthor(new PersonIdent(authorIdent, commitDate, timeZone));
+ commit.setCommitter(new PersonIdent(committerIdent, commitDate, timeZone));
+
+ ObjectWriter writer = new ObjectWriter(repo);
+ commit.setCommitId(writer.writeCommit(commit));
+
+ final RefUpdate ru = repo.updateRef(Constants.HEAD);
+ ru.setNewObjectId(commit.getCommitId());
+ ru.setRefLogMessage(buildReflogMessage(commitMessage), false);
+ if (ru.forceUpdate() == RefUpdate.Result.LOCK_FAILURE) {
+ throw new TeamException("Failed to update " + ru.getName()
+ + " to commit " + commit.getCommitId() + ".");
+ }
+ }
+ }
+
+ private void prepareTrees(IFile[] selectedItems,
+ HashMap<Repository, Tree> treeMap) throws IOException,
+ UnsupportedEncodingException {
+ if (selectedItems.length == 0) {
+ // amending commit - need to put something into the map
+ for (IProject proj : getProjectsForSelectedResources()) {
+ Repository repo = RepositoryMapping.getMapping(proj).getRepository();
+ if (!treeMap.containsKey(repo))
+ treeMap.put(repo, repo.mapTree(Constants.HEAD));
+ }
+ }
+
+ for (IFile file : selectedItems) {
+ // System.out.println("\t" + file);
+
+ IProject project = file.getProject();
+ RepositoryMapping repositoryMapping = RepositoryMapping.getMapping(project);
+ Repository repository = repositoryMapping.getRepository();
+ Tree projTree = treeMap.get(repository);
+ if (projTree == null) {
+ projTree = repository.mapTree(Constants.HEAD);
+ if (projTree == null)
+ projTree = new Tree(repository);
+ treeMap.put(repository, projTree);
+ System.out.println("Orig tree id: " + projTree.getId());
+ }
+ GitIndex index = repository.getIndex();
+ String repoRelativePath = repositoryMapping
+ .getRepoRelativePath(file);
+ String string = repoRelativePath;
+
+ TreeEntry treeMember = projTree.findBlobMember(repoRelativePath);
+ // we always want to delete it from the current tree, since if it's
+ // updated, we'll add it again
+ if (treeMember != null)
+ treeMember.delete();
+
+ Entry idxEntry = index.getEntry(string);
+ if (notIndexed.contains(file)) {
+ File thisfile = new File(repositoryMapping.getWorkDir(), idxEntry.getName());
+ if (!thisfile.isFile()) {
+ index.remove(repositoryMapping.getWorkDir(), thisfile);
+ index.write();
+ System.out.println("Phantom file, so removing from index");
+ continue;
+ } else {
+ if (idxEntry.update(thisfile))
+ index.write();
+ }
+ }
+
+
+ if (idxEntry != null) {
+ projTree.addFile(repoRelativePath);
+ TreeEntry newMember = projTree.findBlobMember(repoRelativePath);
+
+ newMember.setId(idxEntry.getObjectId());
+ System.out.println("New member id for " + repoRelativePath
+ + ": " + newMember.getId() + " idx id: "
+ + idxEntry.getObjectId());
+ }
+ }
+ }
+
+ private String buildReflogMessage(String commitMessage) {
+ String firstLine = commitMessage;
+ int newlineIndex = commitMessage.indexOf("\n");
+ if (newlineIndex > 0) {
+ firstLine = commitMessage.substring(0, newlineIndex);
+ }
+ String commitStr = amending ? "commit (amend):" : "commit: ";
+ String message = commitStr + firstLine;
+ return message;
+ }
+
+ private void writeTreeWithSubTrees(Tree tree) throws TeamException {
+ if (tree.getId() == null) {
+ System.out.println("writing tree for: " + tree.getFullName());
+ try {
+ for (TreeEntry entry : tree.members()) {
+ if (entry.isModified()) {
+ if (entry instanceof Tree) {
+ writeTreeWithSubTrees((Tree) entry);
+ } else {
+ // this shouldn't happen.... not quite sure what to
+ // do here :)
+ System.out.println("BAD JUJU: "
+ + entry.getFullName());
+ }
+ }
+ }
+ ObjectWriter writer = new ObjectWriter(tree.getRepository());
+ tree.setId(writer.writeTree(tree));
+ } catch (IOException e) {
+ throw new TeamException("Writing trees", e);
+ }
+ }
+ }
+
+ private void buildIndexHeadDiffList() throws IOException {
+ for (IProject project : getProjectsInRepositoryOfSelectedResources()) {
+ RepositoryMapping repositoryMapping = RepositoryMapping.getMapping(project);
+ assert repositoryMapping != null;
+ Repository repository = repositoryMapping.getRepository();
+ Tree head = repository.mapTree(Constants.HEAD);
+ GitIndex index = repository.getIndex();
+ IndexDiff indexDiff = new IndexDiff(head, index);
+ indexDiff.diff();
+
+ includeList(project, indexDiff.getAdded(), indexChanges);
+ includeList(project, indexDiff.getChanged(), indexChanges);
+ includeList(project, indexDiff.getRemoved(), indexChanges);
+ includeList(project, indexDiff.getMissing(), notIndexed);
+ includeList(project, indexDiff.getModified(), notIndexed);
+ }
+ }
+
+ private void includeList(IProject project, HashSet<String> added, ArrayList<IFile> category) {
+ String repoRelativePath = RepositoryMapping.getMapping(project).getRepoRelativePath(project);
+ if (repoRelativePath.length() > 0) {
+ repoRelativePath += "/";
+ }
+
+ for (String filename : added) {
+ try {
+ if (!filename.startsWith(repoRelativePath))
+ continue;
+ String projectRelativePath = filename.substring(repoRelativePath.length());
+ IResource member = project.getFile(projectRelativePath);
+ if (member != null && member instanceof IFile) {
+ if (!files.contains(member))
+ files.add((IFile) member);
+ category.add((IFile) member);
+ } else {
+ System.out.println("Couldn't find " + filename);
+ }
+ } catch (Exception t) {
+ t.printStackTrace();
+ continue;
+ } // if it's outside the workspace, bad things happen
+ }
+ }
+
+ boolean tryAddResource(IFile resource, GitProjectData projectData, ArrayList<IFile> category) {
+ if (files.contains(resource))
+ return false;
+
+ try {
+ RepositoryMapping repositoryMapping = projectData
+ .getRepositoryMapping(resource);
+
+ if (isChanged(repositoryMapping, resource)) {
+ files.add(resource);
+ category.add(resource);
+ return true;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ private boolean isChanged(RepositoryMapping map, IFile resource) {
+ try {
+ Repository repository = map.getRepository();
+ GitIndex index = repository.getIndex();
+ String repoRelativePath = map.getRepoRelativePath(resource);
+ Entry entry = index.getEntry(repoRelativePath);
+ if (entry != null)
+ return entry.isModified(map.getWorkDir());
+ return false;
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return getProjectsInRepositoryOfSelectedResources().length > 0;
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexAction.java
new file mode 100644
index 000000000..b7cecacfe
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithIndexAction.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (C) 2009, Yann Simon <yann.simon.fr@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.compare.CompareUI;
+import org.eclipse.compare.IContentChangeListener;
+import org.eclipse.compare.IContentChangeNotifier;
+import org.eclipse.compare.ITypedElement;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.egit.core.internal.storage.GitFileRevision;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.egit.ui.internal.EditableRevision;
+import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.team.core.history.IFileRevision;
+import org.eclipse.team.internal.ui.Utils;
+import org.eclipse.team.ui.synchronize.SaveableCompareEditorInput;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * The "compare with index" action. This action opens a diff editor comparing
+ * the file as found in the working directory and the version found in the index
+ * of the repository.
+ */
+@SuppressWarnings("restriction")
+public class CompareWithIndexAction extends RepositoryAction {
+
+ @Override
+ public void execute(IAction action) {
+ final IResource resource = getSelectedResources()[0];
+ final RepositoryMapping mapping = RepositoryMapping.getMapping(resource.getProject());
+ final Repository repository = mapping.getRepository();
+ final String gitPath = mapping.getRepoRelativePath(resource);
+
+ final IFileRevision nextFile = GitFileRevision.inIndex(repository, gitPath);
+
+ final IFile baseFile = (IFile) resource;
+ final ITypedElement base = SaveableCompareEditorInput.createFileElement(baseFile);
+
+ final EditableRevision next = new EditableRevision(nextFile);
+
+ IContentChangeListener listener = new IContentChangeListener() {
+ public void contentChanged(IContentChangeNotifier source) {
+ final byte[] newContent = next.getModifiedContent();
+ try {
+ final GitIndex index = repository.getIndex();
+ final File file = new File(baseFile.getLocation().toString());
+ index.add(mapping.getWorkDir(), file, newContent);
+ index.write();
+ } catch (IOException e) {
+ Utils.handleError(getTargetPart().getSite().getShell(), e,
+ "Error during adding to index",
+ "Error during adding to index");
+ return;
+ }
+ }
+ };
+
+ next.addContentChangeListener(listener);
+
+ final GitCompareFileRevisionEditorInput in = new GitCompareFileRevisionEditorInput(
+ base, next, null);
+ CompareUI.openCompareEditor(in);
+ }
+
+ @Override
+ public boolean isEnabled() {
+ final IResource[] selectedResources = getSelectedResources();
+ if (selectedResources.length != 1)
+ return false;
+
+ final IResource resource = selectedResources[0];
+ if (!(resource instanceof IFile)) {
+ return false;
+ }
+ final RepositoryMapping mapping = RepositoryMapping.getMapping(resource.getProject());
+ return mapping != null;
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithRevisionAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithRevisionAction.java
new file mode 100644
index 000000000..012ae9a5d
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/CompareWithRevisionAction.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (C) 2007, David Watson <dwatson@mimvista.com>
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.Arrays;
+import java.util.Hashtable;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.team.internal.ui.actions.TeamAction;
+import org.eclipse.team.ui.TeamUI;
+import org.eclipse.team.ui.history.HistoryPageSaveablePart;
+
+/**
+ * Compare the resources filtered in the history view with the current
+ * revision.
+ */
+public class CompareWithRevisionAction extends TeamAction {
+
+ // There are changes in Eclipse 3.3 requiring that execute be implemented
+ // for it to compile. while 3.2 requires that run is implemented instead.
+ /** See {@link #run}
+ * @param action
+ */
+ public void execute(IAction action) {
+ run(action);
+ }
+
+ @Override
+ public void run(IAction action) {
+ super.run(action);
+ System.out.println("Run:" + action);
+ System.out.println("Selection resources:"
+ + Arrays.asList(getSelectedResources()));
+ IResource[] r = getSelectedResources();
+ Hashtable providerMapping = this.getProviderMapping(r);
+ System.out.println("Mapping:" + providerMapping);
+ TeamUI.getHistoryView().showHistoryFor(getSelectedResources()[0]);
+
+ }
+
+ void showCompareInDialog(Shell shell, Object object) {
+ HistoryPageSaveablePart.showHistoryInDialog(shell, object);
+ }
+
+ public boolean isEnabled() {
+ return !getSelection().isEmpty();
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Disconnect.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Disconnect.java
new file mode 100644
index 000000000..a8ed9f9cd
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Disconnect.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.egit.core.op.DisconnectProviderOperation;
+import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Action to disassociate a project from its Git repository.
+ *
+ * @see DisconnectProviderOperation
+ */
+public class Disconnect extends AbstractOperationAction {
+ protected IWorkspaceRunnable createOperation(final IAction act,
+ final List sel) {
+ return sel.isEmpty() ? null : new DisconnectProviderOperation(sel);
+ }
+
+ protected void postOperation() {
+ GitLightweightDecorator.refresh();
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/FetchAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/FetchAction.java
new file mode 100644
index 000000000..f4bb26887
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/FetchAction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.net.URISyntaxException;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.UIText;
+import org.eclipse.egit.ui.internal.fetch.FetchWizard;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Action for displaying fetch wizard - allowing selection of specifications for
+ * fetch, and fetching objects/refs from another repository.
+ */
+public class FetchAction extends RepositoryAction {
+ @Override
+ public void run(IAction action) {
+ final Repository repository = getRepository(true);
+ if (repository == null)
+ return;
+
+ final FetchWizard fetchWizard;
+ try {
+ fetchWizard = new FetchWizard(repository);
+ } catch (URISyntaxException x) {
+ ErrorDialog.openError(getShell(), UIText.FetchAction_wrongURITitle,
+ UIText.FetchAction_wrongURIMessage, new Status(
+ IStatus.ERROR, Activator.getPluginId(), x
+ .getMessage(), x));
+ return;
+ }
+ final WizardDialog dialog = new WizardDialog(getShell(), fetchWizard);
+ dialog.open();
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return getRepository(false) != null;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/HardResetToRevisionAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/HardResetToRevisionAction.java
new file mode 100644
index 000000000..13dab0600
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/HardResetToRevisionAction.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.egit.core.op.ResetOperation;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jgit.lib.AnyObjectId;
+
+/**
+ * Hard reset to selected revision
+ */
+public class HardResetToRevisionAction extends AbstractRevObjectAction {
+
+ @Override
+ protected IWorkspaceRunnable createOperation(IAction act, List selection) {
+ return new ResetOperation(getActiveRepository(),
+ ((AnyObjectId) selection.get(0)).name(),
+ ResetOperation.ResetType.HARD);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/MixedResetToRevisionAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/MixedResetToRevisionAction.java
new file mode 100644
index 000000000..45ec53b7c
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/MixedResetToRevisionAction.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.egit.core.op.ResetOperation;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jgit.lib.AnyObjectId;
+
+/**
+ * Mixed reset to selected revision
+ */
+public class MixedResetToRevisionAction extends AbstractRevObjectAction {
+
+ @Override
+ protected IWorkspaceRunnable createOperation(IAction act, List selection) {
+ return new ResetOperation(getActiveRepository(),
+ ((AnyObjectId) selection.get(0)).name(),
+ ResetOperation.ResetType.MIXED);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PushAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PushAction.java
new file mode 100644
index 000000000..f24ccd4c3
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/PushAction.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.net.URISyntaxException;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.UIText;
+import org.eclipse.egit.ui.internal.push.PushWizard;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * Action for choosing specifications for push, and pushing out to another
+ * repository.
+ */
+public class PushAction extends RepositoryAction {
+
+ @Override
+ public void run(IAction action) {
+ final Repository repository = getRepository(true);
+ if (repository == null)
+ return;
+
+ final PushWizard pushWizard;
+ try {
+ pushWizard = new PushWizard(repository);
+ } catch (URISyntaxException x) {
+ ErrorDialog.openError(getShell(), UIText.PushAction_wrongURITitle,
+ UIText.PushAction_wrongURIDescription, new Status(
+ IStatus.ERROR, Activator.getPluginId(), x
+ .getMessage(), x));
+ return;
+ }
+ final WizardDialog dialog = new WizardDialog(getShell(), pushWizard);
+ dialog.open();
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return getRepository(false) != null;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/QuickdiffBaselineOperation.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/QuickdiffBaselineOperation.java
new file mode 100644
index 000000000..0364bbfa7
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/QuickdiffBaselineOperation.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.ui.Activator;
+import org.eclipse.egit.ui.internal.decorators.GitQuickDiffProvider;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * UI operation to change the git quickdiff baseline
+ */
+public class QuickdiffBaselineOperation extends AbstractRevObjectOperation {
+
+ private final String baseline;
+
+ /**
+ * Construct a QuickdiffBaselineOperation for changing quickdiff baseline
+ * @param repository
+ *
+ * @param baseline
+ */
+ QuickdiffBaselineOperation(final Repository repository, final String baseline) {
+ super(repository);
+ this.baseline = baseline;
+ }
+
+ public void run(IProgressMonitor monitor) throws CoreException {
+ try {
+ GitQuickDiffProvider.setBaselineReference(repository, baseline);
+ } catch (IOException e) {
+ Activator.logError("Cannot set quickdiff baseline", e);
+ }
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryAction.java
new file mode 100644
index 000000000..e35e9862c
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/RepositoryAction.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.egit.core.project.RepositoryMapping;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.team.internal.ui.actions.TeamAction;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * A helper class for Team Actions on Git controlled projects
+ */
+public abstract class RepositoryAction extends TeamAction {
+
+ // There are changes in Eclipse 3.3 requiring that execute be implemented
+ // for it to compile. while 3.2 requires that run is implemented instead.
+ /*
+ * See {@link #run(IAction)}
+ *
+ * @param action
+ */
+ public void execute(IAction action) {
+ run(action);
+ }
+
+ /**
+ * @return the projects hosting the selected resources
+ */
+ protected IProject[] getProjectsForSelectedResources() {
+ Set<IProject> ret = new HashSet<IProject>();
+ for (IResource resource : (IResource[])getSelectedAdaptables(getSelection(), IResource.class))
+ ret.add(resource.getProject());
+ return ret.toArray(new IProject[ret.size()]);
+ }
+
+ /**
+ * @param projects
+ * a list of projects
+ * @return the repositories that projects map to iff all projects are mapped
+ */
+ protected Repository[] getRepositoriesFor(final IProject[] projects) {
+ Set<Repository> ret = new HashSet<Repository>();
+ for (IProject project : projects) {
+ RepositoryMapping repositoryMapping = RepositoryMapping.getMapping(project);
+ if (repositoryMapping == null)
+ return new Repository[0];
+ ret.add(repositoryMapping.getRepository());
+ }
+ return ret.toArray(new Repository[ret.size()]);
+ }
+
+ /**
+ * List the projects with selected resources, if all projects are connected
+ * to a Git repository.
+ *
+ * @return the tracked projects affected by the current resource selection
+ */
+ public IProject[] getProjectsInRepositoryOfSelectedResources() {
+ Set<IProject> ret = new HashSet<IProject>();
+ Repository[] repositories = getRepositoriesFor(getProjectsForSelectedResources());
+ final IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ for (IProject project : projects) {
+ RepositoryMapping mapping = RepositoryMapping.getMapping(project);
+ for (Repository repository : repositories) {
+ if (mapping != null && mapping.getRepository() == repository) {
+ ret.add(project);
+ break;
+ }
+ }
+ }
+ return ret.toArray(new IProject[ret.size()]);
+ }
+
+ /**
+ * Figure out which repository to use. All selected
+ * resources must map to the same Git repository.
+ *
+ * @param warn Put up a message dialog to warn why a resource was not selected
+ * @return repository for current project, or null
+ */
+ protected Repository getRepository(boolean warn) {
+ RepositoryMapping mapping = null;
+ for (IProject project : getSelectedProjects()) {
+ RepositoryMapping repositoryMapping = RepositoryMapping.getMapping(project);
+ if (mapping == null)
+ mapping = repositoryMapping;
+ if (repositoryMapping == null)
+ return null;
+ if (mapping.getRepository() != repositoryMapping.getRepository()) {
+ if (warn)
+ MessageDialog.openError(getShell(), "Multiple Repositories Selection", "Cannot perform reset on multiple repositories simultaneously.\n\nPlease select items from only one repository.");
+ return null;
+ }
+ }
+ if (mapping == null) {
+ if (warn)
+ MessageDialog.openError(getShell(), "Cannot Find Repository", "Could not find a repository associated with this project");
+ return null;
+ }
+
+ final Repository repository = mapping.getRepository();
+ return repository;
+ }
+
+ /**
+ * Figure out which repositories to use. All selected
+ * resources must map to a Git repository.
+ *
+ * @return repository for current project, or null
+ */
+ protected Repository[] getRepositories() {
+ IProject[] selectedProjects = getSelectedProjects();
+ Set<Repository> repos = new HashSet<Repository>(selectedProjects.length);
+ for (IProject project : selectedProjects) {
+ RepositoryMapping repositoryMapping = RepositoryMapping.getMapping(project);
+ if (repositoryMapping == null)
+ return new Repository[0];
+ repos.add(repositoryMapping.getRepository());
+ }
+ return repos.toArray(new Repository[repos.size()]);
+ }
+
+ // Re-make isEnabled abstract
+ @Override
+ abstract public boolean isEnabled();
+} \ No newline at end of file
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetAction.java
new file mode 100644
index 000000000..a6ef755c9
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetAction.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.ResetOperation;
+import org.eclipse.egit.core.op.ResetOperation.ResetType;
+import org.eclipse.egit.ui.internal.decorators.GitLightweightDecorator;
+import org.eclipse.egit.ui.internal.dialogs.BranchSelectionDialog;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jgit.lib.Repository;
+
+/**
+ * An action to reset the current branch to a specific revision.
+ *
+ * @see ResetOperation
+ */
+public class ResetAction extends RepositoryAction {
+
+ @Override
+ public void run(IAction action) {
+ final Repository repository = getRepository(true);
+ if (repository == null)
+ return;
+
+ if (!repository.getRepositoryState().canResetHead()) {
+ MessageDialog.openError(getShell(), "Cannot reset HEAD now",
+ "Repository state:"
+ + repository.getRepositoryState().getDescription());
+ return;
+ }
+
+ BranchSelectionDialog branchSelectionDialog = new BranchSelectionDialog(getShell(), repository);
+ if (branchSelectionDialog.open() == IDialogConstants.OK_ID) {
+ final String refName = branchSelectionDialog.getRefName();
+ final ResetType type = branchSelectionDialog.getResetType();
+
+ try {
+ getTargetPart().getSite().getWorkbenchWindow().run(true, false,
+ new IRunnableWithProgress() {
+ public void run(final IProgressMonitor monitor)
+ throws InvocationTargetException {
+ try {
+ new ResetOperation(repository, refName, type).run(monitor);
+ GitLightweightDecorator.refresh();
+ } catch (CoreException ce) {
+ ce.printStackTrace();
+ throw new InvocationTargetException(ce);
+ }
+ }
+ });
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(getShell(),"Reset failed", e.getMessage());
+ } catch (InterruptedException e) {
+ MessageDialog.openError(getShell(),"Reset failed", e.getMessage());
+ }
+ }
+
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return getRepository(false) != null;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetQuickdiffBaselineAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetQuickdiffBaselineAction.java
new file mode 100644
index 000000000..3b42ddbce
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetQuickdiffBaselineAction.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jgit.lib.Constants;
+
+/**
+ * Changes the reference for the quickdiff to HEAD
+ */
+public class ResetQuickdiffBaselineAction extends AbstractRevObjectAction {
+
+ @Override
+ protected IWorkspaceRunnable createOperation(IAction act, List selection) {
+ return new QuickdiffBaselineOperation(getActiveRepository(), Constants.HEAD);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetQuickdiffBaselineHeadParentAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetQuickdiffBaselineHeadParentAction.java
new file mode 100644
index 000000000..0cc4a4525
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ResetQuickdiffBaselineHeadParentAction.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Changes the reference for the quickdiff to the (first) parent of HEAD
+ */
+public class ResetQuickdiffBaselineHeadParentAction extends AbstractRevObjectAction {
+
+ @Override
+ protected IWorkspaceRunnable createOperation(IAction act, List selection) {
+ return new QuickdiffBaselineOperation(getActiveRepository(), "HEAD^1");
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SetQuickdiffBaselineAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SetQuickdiffBaselineAction.java
new file mode 100644
index 000000000..907803c71
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SetQuickdiffBaselineAction.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jgit.revwalk.RevObject;
+
+/**
+ * Changes the reference for the quickdiff
+ */
+public class SetQuickdiffBaselineAction extends AbstractRevObjectAction {
+
+ @Override
+ protected IWorkspaceRunnable createOperation(IAction act, List selection) {
+ return new QuickdiffBaselineOperation(getActiveRepository(), ((RevObject)selection.get(0)).getId().name());
+ }
+
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowResourceInHistoryAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowResourceInHistoryAction.java
new file mode 100644
index 000000000..c3d39676f
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/ShowResourceInHistoryAction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (C) 2007, David Watson <dwatson@mimvista.com>
+ * Copyright (C) 2007, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import org.eclipse.egit.core.ResourceList;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.team.internal.ui.actions.TeamAction;
+import org.eclipse.team.ui.TeamUI;
+import org.eclipse.team.ui.history.HistoryPageSaveablePart;
+
+/**
+ * An action to update the history view for the selected
+ * resource. If the history view is not visible it will be
+ * shown.
+ */
+public class ShowResourceInHistoryAction extends TeamAction {
+
+ // There are changes in Eclipse 3.3 requiring that execute be implemented
+ // for it to compile. while 3.2 requires that run is implemented instead.
+ /**
+ * See {@link #run}
+ *
+ * @param action
+ */
+ public void execute(IAction action) {
+ run(action);
+ }
+
+ @Override
+ public void run(IAction action) {
+ TeamUI.getHistoryView().showHistoryFor(
+ new ResourceList(getSelectedResources()));
+ }
+
+ void showCompareInDialog(Shell shell, Object object) {
+ HistoryPageSaveablePart.showHistoryInDialog(shell, object);
+ }
+
+ public boolean isEnabled() {
+ return !getSelection().isEmpty();
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SoftResetToRevisionAction.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SoftResetToRevisionAction.java
new file mode 100644
index 000000000..220807b81
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/SoftResetToRevisionAction.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.egit.core.op.ResetOperation;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jgit.lib.AnyObjectId;
+
+/**
+ * Soft reset to selected revision
+ */
+public class SoftResetToRevisionAction extends AbstractRevObjectAction {
+
+ @Override
+ protected IWorkspaceRunnable createOperation(IAction act, List selection) {
+ return new ResetOperation(getActiveRepository(),
+ ((AnyObjectId) selection.get(0)).name(),
+ ResetOperation.ResetType.SOFT);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Track.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Track.java
new file mode 100644
index 000000000..fe5f14b18
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Track.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.egit.core.op.TrackOperation;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+
+/**
+ * An action to add resources to the Git repository.
+ *
+ * @see TrackOperation
+ */
+public class Track extends RepositoryAction {
+
+ @Override
+ public void run(IAction action) {
+ try {
+ final TrackOperation op = new TrackOperation(Arrays
+ .asList(getSelectedResources()));
+ getTargetPart().getSite().getWorkbenchWindow().run(true, false,
+ new IRunnableWithProgress() {
+ public void run(IProgressMonitor arg0)
+ throws InvocationTargetException,
+ InterruptedException {
+ try {
+ op.run(arg0);
+ } catch (CoreException e) {
+ MessageDialog.openError(getShell(),
+ "Track failed", e.getMessage());
+ }
+ }
+ });
+ } catch (InvocationTargetException e) {
+ MessageDialog.openError(getShell(), "Track failed", e.getMessage());
+ } catch (InterruptedException e) {
+ MessageDialog.openError(getShell(), "Track failed", e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return getSelectedAdaptables(getSelection(), IResource.class).length > 0;
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Untrack.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Untrack.java
new file mode 100644
index 000000000..19805c308
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Untrack.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.egit.core.op.UntrackOperation;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * An action to remove files from a Git repository. The removal does not alter
+ * history, only future commits on the same branch will be affected.
+ *
+ * @see UntrackOperation
+ */
+public class Untrack extends AbstractOperationAction {
+ protected IWorkspaceRunnable createOperation(final IAction act,
+ final List sel) {
+ return sel.isEmpty() ? null : new UntrackOperation(sel);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Update.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Update.java
new file mode 100644
index 000000000..403063615
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/Update.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.actions;
+
+import java.util.List;
+
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.egit.core.op.UpdateOperation;
+import org.eclipse.jface.action.IAction;
+
+/**
+ * Action to update index for selected resources with content from workdir.
+ *
+ * @see UpdateOperation
+ */
+public class Update extends AbstractOperationAction {
+ protected IWorkspaceRunnable createOperation(final IAction act,
+ final List sel) {
+ return sel.isEmpty() ? null : new UpdateOperation(sel);
+ }
+}
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/CloneDestinationPage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/CloneDestinationPage.java
new file mode 100644
index 000000000..f2419dd61
--- /dev/null
+++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/CloneDestinationPage.java
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the 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 org.eclipse.egit.ui.internal.clone;
+
+import java.io.File;
+import java.util.List;
+
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.egit.ui.UIText;
+import org.eclipse.egit.ui.internal.components.RepositorySelection;
+import org.eclipse.egit.ui.internal.components.RepositorySelectionPage;
+import org.eclipse.egit.ui.internal.components.SelectionChangeListener;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.osgi.util.NLS;
+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.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.FileDialog;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+
+/**
+ * Wizard page that allows the user entering the location of a repository to be
+ * cloned.
+ */
+class CloneDestinationPage extends WizardPage {
+ private final RepositorySelectionPage sourcePage;
+
+ private final SourceBranchPage branchPage;
+
+ private RepositorySelection validatedRepoSelection;
+
+ private List<Ref> validatedSelectedBranches;
+
+ private Ref validatedHEAD;
+
+ private Combo initialBranch;
+
+ private Text directoryText;
+
+ private Text remoteText;
+
+ Button showImportWizard;
+
+ String alreadyClonedInto;
+
+ CloneDestinationPage(final RepositorySelectionPage sp,
+ final SourceBranchPage bp) {
+ super(CloneDestinationPage.class.getName());
+ sourcePage = sp;
+ branchPage = bp;
+ setTitle(UIText.CloneDestinationPage_title);
+
+ final SelectionChangeListener listener = new SelectionChangeListener() {
+ public void selectionChanged() {
+ checkPreviousPagesSelections();
+ }
+ };
+ sourcePage.addSelectionListener(listener);
+ branchPage.addSelectionListener(listener);
+ }
+
+ public void createControl(final Composite parent) {
+ final Composite panel = new Composite(parent, SWT.NULL);
+ final GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ panel.setLayout(layout);
+
+ createDestinationGroup(panel);
+ createConfigGroup(panel);
+ createWorkbenchGroup(panel);
+ setControl(panel);
+ checkPage();
+ }
+
+ @Override
+ public void setVisible(final boolean visible) {
+ if (visible)
+ revalidate();
+ super.setVisible(visible);
+ if (visible)
+ directoryText.setFocus();
+ }
+
+ private void checkPreviousPagesSelections() {
+ if (!sourcePage.selectionEquals(validatedRepoSelection)
+ || !branchPage.selectionEquals(validatedSelectedBranches,
+ validatedHEAD))
+ setPageComplete(false);
+ else
+ checkPage();
+ }
+
+ private void createDestinationGroup(final Composite parent) {
+ final Group g = createGroup(parent,
+ UIText.CloneDestinationPage_groupDestination);
+
+ newLabel(g, UIText.CloneDestinationPage_promptDirectory + ":");
+ final Composite p = new Composite(g, SWT.NONE);
+ final GridLayout grid = new GridLayout();
+ grid.numColumns = 2;
+ p.setLayout(grid);
+ p.setLayoutData(createFieldGridData());
+ directoryText = new Text(p, SWT.BORDER);
+ directoryText.setLayoutData(createFieldGridData());
+ directoryText.addModifyListener(new ModifyListener() {
+ public void modifyText(final ModifyEvent e) {
+ checkPage();
+ }
+ });
+ final Button b = new Button(p, SWT.PUSH);
+ b.setText(UIText.CloneDestinationPage_browseButton);
+ b.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(final SelectionEvent e) {
+ final FileDialog d;
+
+ d = new FileDialog(getShell(), SWT.APPLICATION_MODAL | SWT.SAVE);
+ if (directoryText.getText().length() > 0) {
+ final File file = new File(directoryText.getText())
+ .getAbsoluteFile();
+ d.setFilterPath(file.getParent());
+ d.setFileName(file.getName());
+ }
+ final String r = d.open();
+ if (r != null)
+ directoryText.setText(r);
+ }
+ });
+
+ newLabel(g, UIText.CloneDestinationPage_promptInitialBranch + ":");
+ initialBranch = new Combo(g, SWT.DROP_DOWN | SWT.READ_ONLY);
+ initialBranch.setLayoutData(createFieldGridData());
+ initialBranch.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(final SelectionEvent e) {
+ checkPage();
+ }
+ });
+ }
+
+ private void createConfigGroup(final Composite parent) {
+ final Group g = createGroup(parent,
+ UIText.CloneDestinationPage_groupConfiguration);
+
+ newLabel(g, UIText.CloneDestinationPage_promptRemoteName + ":");
+ remoteText = new Text(g, SWT.BORDER);
+ remoteText.setText("origin");
+ remoteText.setLayoutData(createFieldGridData());
+ remoteText.addModifyListener(new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ checkPage();
+ }
+ });
+ }
+
+ private void createWorkbenchGroup(Composite parent) {
+ final Group g = createGroup(parent, UIText.CloneDestinationPage_workspaceImport);
+ showImportWizard = new Button(g, SWT.CHECK);
+ showImportWizard.setSelection(true);
+ showImportWizard.setText(UIText.CloneDestinationPage_importProjectsAfterClone);
+ showImportWizard.setLayoutData(createFieldGridData());
+ showImportWizard.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ checkPage();
+ }
+ });
+ }
+
+ private static Group createGroup(final Composite parent, final String text) {
+ final Group g = new Group(parent, SWT.NONE);
+ final GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ g.setLayout(layout);
+ g.setText(text);
+ final GridData gd = new GridData();
+ gd.grabExcessHorizontalSpace = true;
+ gd.horizontalAlignment = SWT.FILL;
+ g.setLayoutData(gd);
+ return g;
+ }
+
+ private static void newLabel(final Group g, final String text) {
+ new Label(g, SWT.NULL).setText(text);
+ }
+
+ private static GridData createFieldGridData() {
+ return new GridData(SWT.FILL, SWT.DEFAULT, true, false);
+ }
+
+ /**
+ * @return location the user wants to store this repository.
+ */
+ public File getDestinationFile() {
+ return new File(directoryText.getText());
+ }
+
+ /**
+ * @return initial branch selected (includes refs/heads prefix).
+ */
+ public String getInitialBranch() {
+ final int ix = initialBranch.getSelectionIndex();
+ if (ix < 0)
+ return Constants.R_HEADS + Constants.MASTER;
+ return Constants.R_HEADS + initialBranch.getItem(ix);
+ }
+
+ /**
+ * @return remote name
+ */
+ public String getRemote() {
+ return remoteText.getText();
+ }
+
+ /**
+ * Check internal state for page completion status.
+ */
+ private void checkPage() {
+ final String dstpath = directoryText.getText();
+ if (dstpath.length() == 0) {
+ setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
+ UIText.CloneDestinationPage_promptDirectory));
+ setPageComplete(false);
+ return;
+ }
+ final File absoluteFile = new File(dstpath).getAbsoluteFile();
+ if (!absoluteFile.getAbsolutePath().equals(alreadyClonedInto)
+ && !isEmptyDir(absoluteFile)) {
+ setErrorMessage(NLS.bind(
+ UIText.CloneDestinationPage_errorNotEmptyDir, absoluteFile
+ .getPath()));
+ setPageComplete(false);
+ return;
+ }
+
+ if (!canCreateSubdir(absoluteFile.getParentFile())) {
+ setErrorMessage(NLS.bind(UIText.GitCloneWizard_errorCannotCreate,
+ absoluteFile.getPath()));
+ setPageComplete(false);
+ return;
+ }
+ if (initialBranch.getSelectionIndex() < 0) {
+ setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
+ UIText.CloneDestinationPage_promptInitialBranch));
+ setPageComplete(false);
+ return;
+ }
+ if (remoteText.getText().length() == 0) {
+ setErrorMessage(NLS.bind(UIText.CloneDestinationPage_fieldRequired,
+ UIText.CloneDestinationPage_promptRemoteName));
+ setPageComplete(false);
+ return;
+ }
+
+ setErrorMessage(null);
+ setPageComplete(true);
+ }
+
+ private static boolean isEmptyDir(final File dir) {
+ if (!dir.exists())
+ return true;
+ if (!dir.isDirectory())
+ return false;
+ return dir.listFiles().length == 0;
+ }
+
+ // this is actually just an optimistic heuristic - should be named
+ // isThereHopeThatCanCreateSubdir() as probably there is no 100% reliable
+ // way to check that in Java for Windows
+ private static boolean canCreateSubdir(final File parent) {
+ if (parent == null)
+ return true;
+ if (parent.exists())
+ return parent.isDirectory() && parent.canWrite();
+ return canCreateSubdir(parent.getParentFile());
+ }
+
+ private void revalidate() {
+ if (sourcePage.selectionEquals(validatedRepoSelection)
+ && branchPage.selectionEquals(validatedSelectedBranches,
+ validatedHEAD)) {
+ checkPage();
+ return;
+ }
+
+ if (!sourcePage.selectionEquals(validatedRepoSelection)) {
+ validatedRepoSelection = sourcePage.getSelection();
+ // update repo-related selection only if it changed
+ final String n = getSuggestedName();
+ setDescription(NLS.bind(UIText.CloneDestinationPage_description, n));
+ directoryText.setText(new File(ResourcesPlugin.getWorkspace()
+ .getRoot().getRawLocation().toFile(), n).getAbsolutePath());
+ }
+
+ validatedSelectedBranches = branchPage.getSelectedBranches();
+ validatedHEAD = branchPage.getHEAD();
+
+ initialBranch.removeAll();
+ final Ref head = branchPage.getHEAD();
+ int newix = 0;
+ for (final Ref r : branchPage.getSelectedBranches()) {
+ String name = r.getName();
+ if (name.startsWith(Constants.R_HEADS))
+ name = name.substring((Constants.R_HEADS).length());
+ if (head != null && head.getName().equals(r.getName()))
+ newix = initialBranch.getItemCount();
+ initialBranch.add(name);
+ }
+ initialBranch.select(newix);
+ checkPage();
+ }
+
+ private String getSuggestedName() {
+ String path = validatedRepoSelection.getURI().getPath();
+ int s = path.lastIndexOf('/');
+ if (s != -1)
+ path = path.substring(s + 1);
+ if (path.endsWith(".git"))
+ path = path.substring(0, path.length() - 4);
+ return path;
+ }
+
+ @Override
+ public boolean canFlipToNextPage() {
+ return super.canFlipToNextPage() && showImportWizard.getSelection();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCloneWizard.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/clone/GitCloneWizard.java
new file mode 100644
index 000000000..e840e8d8e
--- /dev/null
+++ b/org.eclipse