2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
26 * The Original Software is NetBeans. The Initial Developer of the Original
27 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28 * Microsystems, Inc. All Rights Reserved.
29 * Portions Copyright 2008 Alexander Coles (Ikonoklastik Productions).
31 * If you wish your version of this file to be governed by only the CDDL
32 * or only the GPL Version 2, indicate your decision by adding
33 * "[Contributor] elects to include this software in this distribution
34 * under the [CDDL or GPL Version 2] license." If you do not indicate a
35 * single choice of license, a recipient has the option to distribute
36 * your version of this file under either the CDDL, the GPL Version 2 or
37 * to extend the choice of license to its licensees as provided above.
38 * However, if you add GPL Version 2 code and therefore, elected the GPL
39 * Version 2 license, then the option applies only if the new code is
40 * made subject to such option by the copyright holder.
42 package org
.netbeans
.modules
.git
.config
;
44 import java
.io
.BufferedOutputStream
;
46 import java
.io
.FileNotFoundException
;
47 import java
.io
.FileOutputStream
;
48 import java
.io
.FileReader
;
49 import java
.io
.IOException
;
50 import java
.util
.Iterator
;
51 import java
.util
.Properties
;
53 import java
.util
.logging
.Level
;
55 import org
.netbeans
.modules
.git
.Git
;
56 import org
.openide
.filesystems
.FileUtil
;
57 import org
.openide
.util
.Utilities
;
61 * Handles the <b>.gitconfig</b> configuration file.</br>
63 * @author Padraig O'Briain
65 public class GitConfigFiles
{
67 public static final String GIT_EXTENSIONS
= "extensions"; // NOI18N
68 public static final String GIT_EXTENSIONS_GITK
= "gitk"; // NOI18N
69 public static final String GIT_EXTENSIONS_FETCH
= "fetch"; // NOI18N
70 public static final String GIT_UI_SECTION
= "ui"; // NOI18N
71 public static final String GIT_USERNAME
= "username"; // NOI18N
72 public static final String GIT_PATHS_SECTION
= "paths"; // NOI18N
73 public static final String GIT_DEFAULT_PUSH
= "default-push"; // NOI18N
74 public static final String GIT_DEFAULT_PUSH_VALUE
= "default-push"; // NOI18N
75 public static final String GIT_DEFAULT_PULL
= "default-pull"; // NOI18N
76 public static final String GIT_DEFAULT_PULL_VALUE
= "default"; // NOI18N
78 /** The GitConfigFiles instance for user and system defaults */
79 private static GitConfigFiles instance
;
81 /** the Ini instance holding the configuration values stored in the <b>gitconfig</b>
82 * file used by the Git module */
83 private Ini gitConfig
= null;
85 /** The repository directory if this instance is for a repository */
87 private static final String WINDOWS_USER_APPDATA
= getAPPDATA();
88 private static final String WINDOWS_CONFIG_DIR
= WINDOWS_USER_APPDATA
+ "\\Git"; // NOI18N
89 private static final String WINDOWS_GLOBAL_CONFIG_DIR
= getGlobalAPPDATA() + "\\Git"; // NOI18N
90 public static final String GITCONFIG_FILE
= "gitconfig"; // NOI18N
91 public static final String GIT_REPO_DIR
= ".git"; // NOI18N
94 * Creates a new instance
96 private GitConfigFiles() {
97 // get the system gitconfig file
98 gitConfig
= loadFile(GITCONFIG_FILE
);
102 * Returns a singleton instance
104 * @return the GitConfigFiles instance
106 public static GitConfigFiles
getInstance() {
107 if (instance
== null) {
108 instance
= new GitConfigFiles();
113 public GitConfigFiles(File file
) {
115 gitConfig
= loadFile(file
, GITCONFIG_FILE
);
118 public void setProperty(String name
, String value
) {
119 if (name
.equals(GIT_USERNAME
)) {
120 setProperty(GIT_UI_SECTION
, GIT_USERNAME
, value
);
121 } else if (name
.equals(GIT_DEFAULT_PUSH
)) {
122 setProperty(GIT_PATHS_SECTION
, GIT_DEFAULT_PUSH_VALUE
, value
);
123 } else if (name
.equals(GIT_DEFAULT_PULL
)) {
124 setProperty(GIT_PATHS_SECTION
, GIT_DEFAULT_PULL_VALUE
, value
);
125 } else if (name
.equals(GIT_EXTENSIONS_GITK
)) {
127 if(getProperty(GIT_EXTENSIONS
, GIT_EXTENSIONS_GITK
).equals("")){
128 setProperty(GIT_EXTENSIONS
, GIT_EXTENSIONS_GITK
, value
, true);
130 } else if (name
.equals(GIT_EXTENSIONS_FETCH
)) {
131 // Allow fetch to be set to some other user defined value if required
132 if(getProperty(GIT_EXTENSIONS
, GIT_EXTENSIONS_FETCH
).equals("")){
133 setProperty(GIT_EXTENSIONS
, GIT_EXTENSIONS_FETCH
, value
, true);
139 public void setProperty(String section
, String name
, String value
, boolean allowEmpty
) {
141 if (value
.length() == 0) {
142 removeProperty(section
, name
);
144 Ini
.Section inisection
= getSection(gitConfig
, section
, true);
145 inisection
.put(name
, value
);
148 Ini
.Section inisection
= getSection(gitConfig
, section
, true);
149 inisection
.put(name
, value
);
151 storeIni(gitConfig
, GITCONFIG_FILE
);
154 public void setProperty(String section
, String name
, String value
) {
155 setProperty(section
, name
,value
, false);
158 public void setUserName(String value
) {
159 setProperty(GIT_UI_SECTION
, GIT_USERNAME
, value
);
162 public String
getUserName() {
163 return getUserName(true);
166 public Properties
getProperties(String section
) {
167 Ini
.Section inisection
= getSection(gitConfig
, section
, false);
168 Properties props
= new Properties();
169 if (inisection
!= null) {
170 Set
<String
> keys
= inisection
.keySet();
171 for (String key
: keys
) {
172 props
.setProperty(key
, inisection
.get(key
));
178 public void clearProperties(String section
) {
179 Ini
.Section inisection
= getSection(gitConfig
, section
, false);
180 if (inisection
!= null) {
182 storeIni(gitConfig
, GITCONFIG_FILE
);
186 public void removeProperty(String section
, String name
) {
187 Ini
.Section inisection
= getSection(gitConfig
, section
, false);
188 if (inisection
!= null) {
189 inisection
.remove(name
);
190 storeIni(gitConfig
, GITCONFIG_FILE
);
194 public String
getDefaultPull(Boolean reload
) {
198 return getProperty(GIT_PATHS_SECTION
, GIT_DEFAULT_PULL_VALUE
);
201 public String
getDefaultPush(Boolean reload
) {
205 String value
= getProperty(GIT_PATHS_SECTION
, GIT_DEFAULT_PUSH
);
206 if (value
.length() == 0) {
207 value
= getProperty(GIT_PATHS_SECTION
, GIT_DEFAULT_PULL_VALUE
);
212 public String
getUserName(Boolean reload
) {
216 return getProperty(GIT_UI_SECTION
, GIT_USERNAME
);
219 public String
getProperty(String section
, String name
) {
220 Ini
.Section inisection
= getSection(gitConfig
, section
, true);
221 String value
= inisection
.get(name
);
222 return value
!= null ? value
: ""; // NOI18N
225 public boolean containsProperty(String section
, String name
) {
226 Ini
.Section inisection
= getSection(gitConfig
, section
, true);
227 return inisection
.containsKey(name
);
230 private void doReload () {
232 gitConfig
= loadFile(GITCONFIG_FILE
);
234 gitConfig
= loadFile(dir
, GITCONFIG_FILE
);
238 private Ini
.Section
getSection(Ini ini
, String key
, boolean create
) {
239 Ini
.Section section
= ini
.get(key
);
240 if(section
== null && create
) {
246 private void storeIni(Ini ini
, String iniFile
) {
250 filePath
= dir
.getAbsolutePath() + File
.separator
+ GIT_REPO_DIR
+ File
.separator
+ iniFile
; // NOI18N
252 filePath
= getUserConfigPath() + iniFile
;
254 File file
= FileUtil
.normalizeFile(new File(filePath
));
255 file
.getParentFile().mkdirs();
256 ini
.store(new BufferedOutputStream(new FileOutputStream(file
)));
257 } catch (IOException ex
) {
258 Git
.LOG
.log(Level
.INFO
, null, ex
);
263 * Returns the path for the Git configuration directory
268 public static String
getUserConfigPath() {
269 if(Utilities
.isUnix()) {
270 String path
= System
.getProperty("user.home") ; // NOI18N
271 return path
+ "/."; // NOI18N
272 } else if (Utilities
.isWindows()){
273 return WINDOWS_CONFIG_DIR
+ "/"; // NOI18N
278 private Ini
loadFile(File dir
, String fileName
) {
279 String filePath
= dir
.getAbsolutePath() + File
.separator
+ GIT_REPO_DIR
+ File
.separator
+ fileName
; // NOI18N
280 File file
= FileUtil
.normalizeFile(new File(filePath
));
283 system
= new Ini(new FileReader(file
));
284 } catch (FileNotFoundException ex
) {
286 } catch (IOException ex
) {
287 Git
.LOG
.log(Level
.INFO
, null, ex
);
292 Git
.LOG
.log(Level
.WARNING
, "Could not load the file " + filePath
+ ". Falling back on git defaults."); // NOI18N
297 * Loads the configuration file
298 * The settings are loaded and merged together in the folowing order:
300 * <li> The per-user configuration file, i.e ~/.gitconfig
303 * @param fileName the file name
304 * @return an Ini instance holding the configuration file.
306 private Ini
loadFile(String fileName
) {
307 // config files from userdir
308 String filePath
= getUserConfigPath() + fileName
;
309 File file
= FileUtil
.normalizeFile(new File(filePath
));
312 system
= new Ini(new FileReader(file
));
313 } catch (FileNotFoundException ex
) {
315 } catch (IOException ex
) {
316 Git
.LOG
.log(Level
.INFO
, null, ex
);
321 Git
.LOG
.log(Level
.WARNING
, "Could not load the file " + filePath
+ ". Falling back on git defaults."); // NOI18N
326 global
= new Ini(new FileReader(getGlobalConfigPath() + File
.separator
+ fileName
)); // NOI18N
327 } catch (FileNotFoundException ex
) {
328 // just doesn't exist - ignore
329 } catch (IOException ex
) {
330 Git
.LOG
.log(Level
.INFO
, null, ex
);
334 merge(global
, system
);
340 * Merges only sections/keys/values into target which are not already present in source
342 * @param source the source ini file
343 * @param target the target ini file in which the values from the source file are going to be merged
345 private void merge(Ini source
, Ini target
) {
346 for (Iterator
<String
> itSections
= source
.keySet().iterator(); itSections
.hasNext();) {
347 String sectionName
= itSections
.next();
348 Ini
.Section sourceSection
= source
.get( sectionName
);
349 Ini
.Section targetSection
= target
.get( sectionName
);
351 if(targetSection
== null) {
352 targetSection
= target
.add(sectionName
);
355 for (Iterator
<String
> itVariables
= sourceSection
.keySet().iterator(); itVariables
.hasNext();) {
356 String key
= itVariables
.next();
358 if(!targetSection
.containsKey(key
)) {
359 targetSection
.put(key
, sourceSection
.get(key
));
366 * Return the path for the systemwide command lines configuration directory
368 private static String
getGlobalConfigPath () {
369 if(Utilities
.isUnix()) {
370 return "/etc/gitconfig"; // NOI18N
371 } else if (Utilities
.isWindows()){
372 return WINDOWS_GLOBAL_CONFIG_DIR
;
378 * Returns the value for the %APPDATA% env variable on windows
381 private static String
getAPPDATA() {
382 String appdata
= ""; // NOI18N
383 if(Utilities
.isWindows()) {
384 appdata
= System
.getenv("APPDATA");// NOI18N
386 return appdata
!= null? appdata
: ""; // NOI18N
390 * Returns the value for the %ALLUSERSPROFILE% + the last foder segment from %APPDATA% env variables on windows
393 private static String
getGlobalAPPDATA() {
394 if(Utilities
.isWindows()) {
395 String globalProfile
= System
.getenv("ALLUSERSPROFILE"); // NOI18N
396 if(globalProfile
== null || globalProfile
.trim().equals("")) { // NOI18N
397 globalProfile
= ""; // NOI18N
399 String appdataPath
= WINDOWS_USER_APPDATA
;
400 if(appdataPath
== null || appdataPath
.equals("")) { // NOI18N
403 String appdata
= ""; // NOI18N
404 int idx
= appdataPath
.lastIndexOf("\\"); // NOI18N
406 appdata
= appdataPath
.substring(idx
+ 1);
407 if(appdata
.trim().equals("")) { // NOI18N
408 int previdx
= appdataPath
.lastIndexOf("\\", idx
); // NOI18N
410 appdata
= appdataPath
.substring(previdx
+ 1, idx
);
416 return globalProfile
+ "/" + appdata
; // NOI18N