3 * ====================================================================
4 * Copyright (c) 2003-2004 QintSoft. All rights reserved.
6 * This software is licensed as described in the file COPYING, which
7 * you should have received as part of this distribution. The terms
8 * are also available at http://subversion.tigris.org/license-1.html.
9 * If newer versions of this license are posted there, you may use a
10 * newer version instead, at your option.
12 * This software consists of voluntary contributions made by many
13 * individuals. For exact contribution history, see the revision
14 * history and logs, available at http://svnup.tigris.org/.
15 * ====================================================================
19 * Copyright 2000-2005 JetBrains s.r.o.
21 * Licensed under the Apache License, Version 2.0 (the "License");
22 * you may not use this file except in compliance with the License.
23 * You may obtain a copy of the License at
25 * http://www.apache.org/licenses/LICENSE-2.0
27 * Unless required by applicable law or agreed to in writing, software
28 * distributed under the License is distributed on an "AS IS" BASIS,
29 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30 * See the License for the specific language governing permissions and
31 * limitations under the License.
33 package org
.jetbrains
.idea
.svn
;
35 import com
.intellij
.openapi
.application
.ApplicationManager
;
36 import com
.intellij
.openapi
.components
.ProjectComponent
;
37 import com
.intellij
.openapi
.diagnostic
.Logger
;
38 import com
.intellij
.openapi
.progress
.ProcessCanceledException
;
39 import com
.intellij
.openapi
.progress
.ProgressIndicator
;
40 import com
.intellij
.openapi
.progress
.ProgressManager
;
41 import com
.intellij
.openapi
.project
.Project
;
42 import com
.intellij
.openapi
.util
.*;
43 import com
.intellij
.openapi
.util
.io
.FileUtil
;
44 import org
.jdom
.Attribute
;
45 import org
.jdom
.DataConversionException
;
46 import org
.jdom
.Element
;
47 import org
.jetbrains
.idea
.svn
.dialogs
.SvnAuthenticationProvider
;
48 import org
.jetbrains
.idea
.svn
.update
.MergeRootInfo
;
49 import org
.jetbrains
.idea
.svn
.update
.UpdateRootInfo
;
50 import org
.tmatesoft
.svn
.core
.SVNDepth
;
51 import org
.tmatesoft
.svn
.core
.auth
.ISVNAuthenticationManager
;
52 import org
.tmatesoft
.svn
.core
.internal
.wc
.ISVNAuthenticationStorage
;
53 import org
.tmatesoft
.svn
.core
.internal
.wc
.SVNConfigFile
;
54 import org
.tmatesoft
.svn
.core
.internal
.wc
.SVNFileUtil
;
55 import org
.tmatesoft
.svn
.core
.wc
.ISVNOptions
;
56 import org
.tmatesoft
.svn
.core
.wc
.SVNWCUtil
;
61 public class SvnConfiguration
implements ProjectComponent
, JDOMExternalizable
{
62 private static final Logger LOG
= Logger
.getInstance("org.jetbrains.idea.svn.SvnConfiguration");
64 private final static String SERVERS_FILE_NAME
= "servers";
66 public static final String UPGRADE_AUTO
= "auto";
67 public static final String UPGRADE_AUTO_15
= "auto1.5";
68 public static final String UPGRADE_AUTO_16
= "auto1.6";
69 public static final String UPGRADE_NONE
= "none";
71 public String USER
= "";
72 public String PASSWORD
= "";
73 public String
[] ADD_PATHS
= null;
75 private String myConfigurationDirectory
;
76 private boolean myIsUseDefaultConfiguration
;
77 private boolean myIsUseDefaultProxy
;
78 private ISVNOptions myOptions
;
79 private boolean myIsKeepLocks
;
80 private boolean myRemoteStatus
;
81 private final Project myProject
;
82 private SvnAuthenticationManager myAuthManager
;
83 private String myUpgradeMode
;
84 private SvnSupportOptions mySupportOptions
;
86 public static final AuthStorage RUNTIME_AUTH_CACHE
= new AuthStorage();
87 public String LAST_MERGED_REVISION
= null;
88 public boolean UPDATE_RUN_STATUS
= false;
89 public SVNDepth UPDATE_DEPTH
= SVNDepth
.INFINITY
;
91 public boolean MERGE_DRY_RUN
= false;
92 public boolean MERGE_DIFF_USE_ANCESTRY
= true;
93 public boolean UPDATE_LOCK_ON_DEMAND
= false;
94 public boolean IGNORE_SPACES_IN_MERGE
= false;
95 public boolean DETECT_NESTED_COPIES
= true;
97 private final Map
<File
, MergeRootInfo
> myMergeRootInfos
= new HashMap
<File
, MergeRootInfo
>();
98 private final Map
<File
, UpdateRootInfo
> myUpdateRootInfos
= new HashMap
<File
, UpdateRootInfo
>();
101 public static SvnConfiguration
getInstance(Project project
) {
102 return project
.getComponent(SvnConfiguration
.class);
105 public static SvnConfiguration
getInstanceChecked(final Project project
) {
106 return ApplicationManager
.getApplication().runReadAction(new Computable
<SvnConfiguration
>() {
107 public SvnConfiguration
compute() {
108 if (project
.isDisposed()) throw new ProcessCanceledException();
109 return project
.getComponent(SvnConfiguration
.class);
114 public SvnConfiguration(final Project project
) {
118 public class SvnSupportOptions
{
120 * version of "support SVN in IDEA". for features tracking. should grow
122 private Long myVersion
;
124 public SvnSupportOptions(final Long version
) {
126 // will be set to SvnSupportOptions.CHANGELIST_SUPPORT after sync
127 if (myVersion
== null || myVersion
.longValue() < SvnSupportOptions
.CHANGELIST_SUPPORT
) {
128 myVersion
= SvnSupportOptions
.UPGRADE_TO_15_VERSION_ASKED
;
132 private final static long UPGRADE_TO_15_VERSION_ASKED
= 123;
133 private final static long CHANGELIST_SUPPORT
= 124;
134 private final static long UPGRADE_TO_16_VERSION_ASKED
= 125;
136 public boolean upgradeTo16Asked() {
137 return (myVersion
!= null) && (UPGRADE_TO_16_VERSION_ASKED
<= myVersion
);
140 public boolean changeListsSynchronized() {
141 return (myVersion
!= null) && (CHANGELIST_SUPPORT
<= myVersion
);
144 public void upgrade() {
145 myVersion
= UPGRADE_TO_16_VERSION_ASKED
;
149 public SvnSupportOptions
getSupportOptions() {
150 if (mySupportOptions
== null) {
151 // used to be kept in SvnBranchConfigurationManager
152 mySupportOptions
= new SvnSupportOptions(SvnBranchConfigurationManager
.getInstance(myProject
).getSupportValue());
154 return mySupportOptions
;
157 public String
getConfigurationDirectory() {
158 if (myConfigurationDirectory
== null || isUseDefaultConfiguation()) {
159 myConfigurationDirectory
= SVNWCUtil
.getDefaultConfigurationDirectory().getAbsolutePath();
161 return myConfigurationDirectory
;
164 public boolean isUseDefaultConfiguation() {
165 return myIsUseDefaultConfiguration
;
168 public void setConfigurationDirectory(String path
) {
169 myConfigurationDirectory
= path
;
170 File dir
= path
== null ? SVNWCUtil
.getDefaultConfigurationDirectory() : new File(path
);
171 SVNConfigFile
.createDefaultConfiguration(dir
);
174 myAuthManager
= null;
175 RUNTIME_AUTH_CACHE
.clear();
178 public void setUseDefaultConfiguation(boolean useDefault
) {
179 myIsUseDefaultConfiguration
= useDefault
;
181 myAuthManager
= null;
182 RUNTIME_AUTH_CACHE
.clear();
185 public ISVNOptions
getOptions(Project project
) {
186 if (myOptions
== null) {
187 File path
= new File(getConfigurationDirectory());
188 myOptions
= SVNWCUtil
.createDefaultOptions(path
.getAbsoluteFile(), true);
193 public ISVNAuthenticationManager
getAuthenticationManager(Project project
) {
194 if (myAuthManager
== null) {
195 // reloaded when configuration directory changes
196 myAuthManager
= new SvnAuthenticationManager(myProject
, new File(getConfigurationDirectory()));
197 myAuthManager
.setAuthenticationProvider(new SvnAuthenticationProvider(project
));
198 myAuthManager
.setRuntimeStorage(RUNTIME_AUTH_CACHE
);
200 return myAuthManager
;
203 public void getServerFilesManagers(final Ref
<SvnServerFileManager
> systemManager
, final Ref
<SvnServerFileManager
> userManager
) {
204 // created only if does not exist
205 SVNConfigFile
.createDefaultConfiguration(new File(getConfigurationDirectory()));
207 systemManager
.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(SVNFileUtil
.getSystemConfigurationDirectory(), SERVERS_FILE_NAME
))));
208 userManager
.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(getConfigurationDirectory(), SERVERS_FILE_NAME
))));
211 public String
getUpgradeMode() {
212 return myUpgradeMode
;
215 public void setUpgradeMode(String upgradeMode
) {
216 myUpgradeMode
= upgradeMode
;
219 @SuppressWarnings({"HardCodedStringLiteral"})
220 public void readExternal(Element element
) throws InvalidDataException
{
221 DefaultJDOMExternalizer
.readExternal(this, element
);
222 List elems
= element
.getChildren("addpath");
223 LOG
.debug(elems
.toString());
224 ADD_PATHS
= new String
[elems
.size()];
225 for (int i
= 0; i
< elems
.size(); i
++) {
226 Element elem
= (Element
)elems
.get(i
);
227 ADD_PATHS
[i
] = elem
.getAttributeValue("path");
229 Element configurationDirectory
= element
.getChild("configuration");
230 if (configurationDirectory
!= null) {
231 myConfigurationDirectory
= configurationDirectory
.getText();
232 Attribute defaultAttr
= configurationDirectory
.getAttribute("useDefault");
234 myIsUseDefaultConfiguration
= defaultAttr
!= null && defaultAttr
.getBooleanValue();
236 catch (DataConversionException e
) {
237 myIsUseDefaultConfiguration
= false;
241 myIsUseDefaultConfiguration
= true;
243 // compatibility: this setting was moved from .iws to global settings
244 List urls
= element
.getChildren("checkoutURL");
245 for (Object url1
: urls
) {
246 Element child
= (Element
)url1
;
247 String url
= child
.getText();
249 SvnApplicationSettings
.getInstance().addCheckoutURL(url
);
252 myIsKeepLocks
= element
.getChild("keepLocks") != null;
253 myRemoteStatus
= element
.getChild("remoteStatus") != null;
254 myUpgradeMode
= element
.getChild("upgradeMode") != null ? element
.getChild("upgradeMode").getText() : null;
255 final Element useProxy
= element
.getChild("myIsUseDefaultProxy");
256 if (useProxy
== null) {
257 myIsUseDefaultProxy
= false;
259 myIsUseDefaultProxy
= Boolean
.parseBoolean(useProxy
.getText());
261 final Element supportedVersion
= element
.getChild("supportedVersion");
262 if (supportedVersion
!= null) {
263 mySupportOptions
= new SvnSupportOptions(Long
.parseLong(supportedVersion
.getText()));
267 @SuppressWarnings({"HardCodedStringLiteral"})
268 public void writeExternal(Element element
) throws WriteExternalException
{
269 DefaultJDOMExternalizer
.writeExternal(this, element
);
270 if (ADD_PATHS
!= null) {
271 for (String aADD_PATHS
: ADD_PATHS
) {
272 Element elem
= new Element("addpath");
273 elem
.setAttribute("path", aADD_PATHS
);
274 element
.addContent(elem
);
277 if (myConfigurationDirectory
!= null) {
278 Element configurationDirectory
= new Element("configuration");
279 configurationDirectory
.setText(myConfigurationDirectory
);
280 configurationDirectory
.setAttribute("useDefault", myIsUseDefaultConfiguration ?
"true" : "false");
281 element
.addContent(configurationDirectory
);
284 element
.addContent(new Element("keepLocks"));
286 if (myRemoteStatus
) {
287 element
.addContent(new Element("remoteStatus"));
289 if (myUpgradeMode
!= null) {
290 element
.addContent(new Element("upgradeMode").setText(myUpgradeMode
));
292 element
.addContent(new Element("myIsUseDefaultProxy").setText(myIsUseDefaultProxy ?
"true" : "false"));
293 if (mySupportOptions
!= null) {
294 element
.addContent(new Element("supportedVersion").setText("" + mySupportOptions
.myVersion
));
298 public void projectOpened() {
301 public void projectClosed() {
304 public String
getComponentName() {
305 return "SvnConfiguration";
308 public void initComponent() {
311 public void disposeComponent() {
314 public boolean isKeepLocks() {
315 return myIsKeepLocks
;
318 public void setKeepLocks(boolean keepLocks
) {
319 myIsKeepLocks
= keepLocks
;
322 public boolean isRemoteStatus() {
323 return myRemoteStatus
;
326 public void setRemoteStatus(boolean remote
) {
327 myRemoteStatus
= remote
;
330 public boolean isIsUseDefaultProxy() {
331 return myIsUseDefaultProxy
;
334 public void setIsUseDefaultProxy(final boolean isUseDefaultProxy
) {
335 myIsUseDefaultProxy
= isUseDefaultProxy
;
338 public static class AuthStorage
implements ISVNAuthenticationStorage
{
340 private final Map
<String
, Object
> myStorage
= new Hashtable
<String
, Object
>();
342 public void clear() {
346 public void putData(String kind
, String realm
, Object data
) {
348 myStorage
.remove(kind
+ "$" + realm
);
350 myStorage
.put(kind
+ "$" + realm
, data
);
354 public Object
getData(String kind
, String realm
) {
355 return myStorage
.get(kind
+ "$" + realm
);
359 public MergeRootInfo
getMergeRootInfo(final File file
, final SvnVcs svnVcs
) {
360 if (!myMergeRootInfos
.containsKey(file
)) {
361 myMergeRootInfos
.put(file
, new MergeRootInfo(file
, svnVcs
));
363 return myMergeRootInfos
.get(file
);
366 public UpdateRootInfo
getUpdateRootInfo(File file
, final SvnVcs svnVcs
) {
367 if (!myUpdateRootInfos
.containsKey(file
)) {
368 myUpdateRootInfos
.put(file
, new UpdateRootInfo(file
, svnVcs
));
370 return myUpdateRootInfos
.get(file
);
373 public Map
<File
, UpdateRootInfo
> getUpdateInfosMap() {
374 return Collections
.unmodifiableMap(myUpdateRootInfos
);
377 public void clearAuthenticationDirectory() {
378 final File authDir
= new File(getConfigurationDirectory(), "auth");
379 if (authDir
.exists()) {
380 ProgressManager
.getInstance().runProcessWithProgressSynchronously(new Runnable() {
382 final ProgressIndicator ind
= ProgressManager
.getInstance().getProgressIndicator();
384 ind
.setIndeterminate(true);
385 ind
.setText("Deleting " + authDir
.getAbsolutePath());
386 FileUtil
.delete(authDir
);
389 }, "button.text.clear.authentication.cache", false, myProject
);