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
;
60 * Handles the Git configuration files:
62 * <li><code>$GIT_DIR/config</code> for repository-specific configuration.</li>
63 * <li><code>~/.gitconfig</code> for user configuration.</li>
64 * <li><code>$(prefix)/etc/gitconfig</code> for system-wide configuration.</li>
67 * @author Padraig O'Briain
70 public class GitConfigFiles
{
72 public static final String GIT_EXTENSIONS
= "extensions"; // NOI18N
73 public static final String GIT_EXTENSIONS_GITK
= "gitk"; // NOI18N
74 public static final String GIT_EXTENSIONS_FETCH
= "fetch"; // NOI18N
76 public static final String GIT_USER_SECTION
= "user"; // NOI18N
77 public static final String GIT_USER_NAME
= "name"; // NOI18N
78 public static final String GIT_EMAIL
= "email"; // NOI18N
80 public static final String GIT_PATHS_SECTION
= "[remote \"origin\"]"; // NOI18N
81 //public static final String GIT_DEFAULT_PUSH = "url"; // NOI18N
82 //public static final String GIT_DEFAULT_PUSH_VALUE = "url"; // NOI18N
83 public static final String GIT_DEFAULT_PULL
= "url"; // NOI18N
84 public static final String GIT_DEFAULT_PULL_VALUE
= "url"; // NOI18N
86 /** The GitConfigFiles instance for user and system defaults */
87 private static GitConfigFiles instance
;
89 /** the Ini instance holding the configuration values stored in the <b>gitconfig</b>
90 * file used by the Git module */
91 private Ini gitConfig
= null;
93 /** The repository directory if this instance is for a repository */
96 private static final String WINDOWS_USER_APPDATA
= getAPPDATA();
97 private static final String WINDOWS_CONFIG_DIR
= WINDOWS_USER_APPDATA
+ "\\Git"; // NOI18N
98 private static final String WINDOWS_GLOBAL_CONFIG_DIR
= getGlobalAPPDATA() + "\\Git"; // NOI18N
100 public static final String GITCONFIG_FILE
= "gitconfig"; // NOI18N
102 public static final String GIT_REPO_DIR
= ".git"; // NOI18N
103 public static final String GIT_REPO_CONFIG_FILE
= "config";
106 * Creates a new instance
108 private GitConfigFiles() {
109 // get the system .gitconfig file
110 gitConfig
= loadFile(GITCONFIG_FILE
);
114 * Returns a singleton instance
116 * @return the GitConfigFiles instance
118 public static GitConfigFiles
getInstance() {
119 if (instance
== null) {
120 instance
= new GitConfigFiles();
125 public GitConfigFiles(File file
) {
127 gitConfig
= loadFile(file
, GIT_REPO_CONFIG_FILE
);
130 public void setProperty(String name
, String value
) {
131 if (name
.equals(GIT_USER_NAME
)) {
132 setProperty(GIT_USER_SECTION
, GIT_USER_NAME
, value
);
133 } else if (name
.equals(GIT_EMAIL
)) {
134 setProperty(GIT_USER_SECTION
, GIT_EMAIL
, value
);
135 } else if (name
.equals(GIT_DEFAULT_PULL
)) {
136 setProperty(GIT_PATHS_SECTION
, GIT_DEFAULT_PULL
, value
);
138 } else if (name
.equals(GIT_EXTENSIONS_GITK
)) {
140 if(getProperty(GIT_EXTENSIONS
, GIT_EXTENSIONS_GITK
).equals("")){
141 setProperty(GIT_EXTENSIONS
, GIT_EXTENSIONS_GITK
, value
, true);
143 } else if (name
.equals(GIT_EXTENSIONS_FETCH
)) {
144 // Allow fetch to be set to some other user defined value if required
145 if(getProperty(GIT_EXTENSIONS
, GIT_EXTENSIONS_FETCH
).equals("")){
146 setProperty(GIT_EXTENSIONS
, GIT_EXTENSIONS_FETCH
, value
, true);
152 public void setProperty(String section
, String name
, String value
, boolean allowEmpty
) {
154 if (value
.length() == 0) {
155 removeProperty(section
, name
);
157 Ini
.Section inisection
= getSection(gitConfig
, section
, true);
158 inisection
.put(name
, value
);
161 Ini
.Section inisection
= getSection(gitConfig
, section
, true);
162 inisection
.put(name
, value
);
167 public void setProperty(String section
, String name
, String value
) {
168 setProperty(section
, name
,value
, false);
171 public void setEmail(String value
) {
172 setProperty(GIT_USER_SECTION
, GIT_EMAIL
, value
);
175 public void setUserName(String value
) {
176 setProperty(GIT_USER_SECTION
, GIT_USER_NAME
, value
);
179 public String
getUserName() {
180 return getUserName(true);
183 public String
getEmail() {
184 return getEmail(true);
187 public Properties
getProperties(String section
) {
188 Ini
.Section inisection
= getSection(gitConfig
, section
, false);
189 Properties props
= new Properties();
190 if (inisection
!= null) {
191 Set
<String
> keys
= inisection
.keySet();
192 for (String key
: keys
) {
193 props
.setProperty(key
, inisection
.get(key
));
199 public void clearProperties(String section
) {
200 Ini
.Section inisection
= getSection(gitConfig
, section
, false);
201 if (inisection
!= null) {
207 public void removeProperty(String section
, String name
) {
208 Ini
.Section inisection
= getSection(gitConfig
, section
, false);
209 if (inisection
!= null) {
210 inisection
.remove(name
);
215 public String
getDefaultPull(Boolean reload
) {
219 return getProperty(GIT_PATHS_SECTION
, GIT_DEFAULT_PULL_VALUE
);
222 public String
getDefaultPush(Boolean reload
) {
227 //String value = getProperty(GIT_PATHS_SECTION, "");
228 //if (value.length() == 0) {
229 value
= getProperty(GIT_PATHS_SECTION
, GIT_DEFAULT_PULL_VALUE
);
234 public String
getUserName(Boolean reload
) {
238 return getProperty(GIT_USER_SECTION
, GIT_USER_NAME
);
241 public String
getEmail(Boolean reload
) {
245 return getProperty(GIT_USER_SECTION
, GIT_EMAIL
);
248 public String
getProperty(String section
, String name
) {
249 Ini
.Section inisection
= getSection(gitConfig
, section
, true);
250 String value
= inisection
.get(name
);
251 return value
!= null ? value
: ""; // NOI18N
254 public boolean containsProperty(String section
, String name
) {
255 Ini
.Section inisection
= getSection(gitConfig
, section
, true);
256 return inisection
.containsKey(name
);
259 private void doReload () {
261 gitConfig
= loadFile(GITCONFIG_FILE
);
263 gitConfig
= loadFile(dir
, GIT_REPO_CONFIG_FILE
);
267 private Ini
.Section
getSection(Ini ini
, String key
, boolean create
) {
268 Ini
.Section section
= ini
.get(key
);
269 if(section
== null && create
) {
275 private void storeIni(Ini ini
) {
279 filePath
= dir
.getAbsolutePath() + File
.separator
+ GIT_REPO_DIR
+ File
.separator
+ GIT_REPO_CONFIG_FILE
; // NOI18N
281 filePath
= getUserConfigPath() + GITCONFIG_FILE
;
283 File file
= FileUtil
.normalizeFile(new File(filePath
));
284 file
.getParentFile().mkdirs();
285 ini
.store(new BufferedOutputStream(new FileOutputStream(file
)));
286 } catch (IOException ex
) {
287 Git
.LOG
.log(Level
.INFO
, null, ex
);
292 * Returns the path for the user-specific git configuration.
296 public static String
getUserConfigPath() {
297 if(Utilities
.isUnix()) {
298 String path
= System
.getProperty("user.home") ; // NOI18N
299 return path
+ "/."; // NOI18N
300 } else if (Utilities
.isWindows()){
301 return WINDOWS_CONFIG_DIR
+ "/"; // NOI18N
306 private Ini
loadFile(File dir
, String fileName
) {
307 String filePath
= dir
.getAbsolutePath() + File
.separator
+ GIT_REPO_DIR
+ File
.separator
+ fileName
; // NOI18N
308 File file
= FileUtil
.normalizeFile(new File(filePath
));
311 system
= new Ini(new FileReader(file
));
312 } catch (FileNotFoundException ex
) {
314 } catch (IOException ex
) {
315 Git
.LOG
.log(Level
.INFO
, null, ex
);
320 Git
.LOG
.log(Level
.WARNING
, "Could not load the file " + filePath
+ ". Falling back on git defaults."); // NOI18N
325 * Loads the configuration file
326 * The settings are loaded and merged together in the folowing order:
328 * <li> The per-user configuration file, i.e ~/.gitconfig
331 * @param fileName the file name
332 * @return an Ini instance holding the configuration file.
334 private Ini
loadFile(String fileName
) {
335 // config files from userdir
336 String filePath
= getUserConfigPath() + fileName
;
337 File file
= FileUtil
.normalizeFile(new File(filePath
));
340 system
= new Ini(new FileReader(file
));
341 } catch (FileNotFoundException ex
) {
343 } catch (IOException ex
) {
344 Git
.LOG
.log(Level
.INFO
, null, ex
);
349 Git
.LOG
.log(Level
.WARNING
, "Could not load the file " + filePath
+ ". Falling back on git defaults."); // NOI18N
354 global
= new Ini(new FileReader(getGlobalConfigPath() + File
.separator
+ fileName
)); // NOI18N
355 } catch (FileNotFoundException ex
) {
356 // just doesn't exist - ignore
357 } catch (IOException ex
) {
358 Git
.LOG
.log(Level
.INFO
, null, ex
);
362 merge(global
, system
);
368 * Merges only sections/keys/values into target which are not already present in source
370 * @param source the source ini file
371 * @param target the target ini file in which the values from the source file are going to be merged
373 private void merge(Ini source
, Ini target
) {
374 for (Iterator
<String
> itSections
= source
.keySet().iterator(); itSections
.hasNext();) {
375 String sectionName
= itSections
.next();
376 Ini
.Section sourceSection
= source
.get( sectionName
);
377 Ini
.Section targetSection
= target
.get( sectionName
);
379 if(targetSection
== null) {
380 targetSection
= target
.add(sectionName
);
383 for (Iterator
<String
> itVariables
= sourceSection
.keySet().iterator(); itVariables
.hasNext();) {
384 String key
= itVariables
.next();
386 if(!targetSection
.containsKey(key
)) {
387 targetSection
.put(key
, sourceSection
.get(key
));
394 * Return the path for the systemwide command lines configuration directory
396 private static String
getGlobalConfigPath () {
397 if(Utilities
.isUnix()) {
398 return "/etc/gitconfig"; // NOI18N
399 } else if (Utilities
.isWindows()){
400 return WINDOWS_GLOBAL_CONFIG_DIR
;
406 * Returns the value for the %APPDATA% env variable on Windows
408 private static String
getAPPDATA() {
409 String appdata
= ""; // NOI18N
410 if(Utilities
.isWindows()) {
411 appdata
= System
.getenv("APPDATA");// NOI18N
413 return appdata
!= null? appdata
: ""; // NOI18N
417 * Returns the value for the %ALLUSERSPROFILE% + the last folder segment
418 * from %APPDATA% env variables on Windows
420 private static String
getGlobalAPPDATA() {
421 if(Utilities
.isWindows()) {
422 String globalProfile
= System
.getenv("ALLUSERSPROFILE"); // NOI18N
423 if(globalProfile
== null || globalProfile
.trim().equals("")) { // NOI18N
424 globalProfile
= ""; // NOI18N
426 String appdataPath
= WINDOWS_USER_APPDATA
;
427 if(appdataPath
== null || appdataPath
.equals("")) { // NOI18N
430 String appdata
= ""; // NOI18N
431 int idx
= appdataPath
.lastIndexOf("\\"); // NOI18N
433 appdata
= appdataPath
.substring(idx
+ 1);
434 if(appdata
.trim().equals("")) { // NOI18N
435 int previdx
= appdataPath
.lastIndexOf("\\", idx
); // NOI18N
437 appdata
= appdataPath
.substring(previdx
+ 1, idx
);
443 return globalProfile
+ "/" + appdata
; // NOI18N