You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ConfigTest.java 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  1. /*
  2. * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
  3. * Copyright (C) 2009-2010, Google Inc.
  4. * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  5. * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
  6. * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  7. * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@sap.com>
  8. * and other copyright owners as documented in the project's IP log.
  9. *
  10. * This program and the accompanying materials are made available
  11. * under the terms of the Eclipse Distribution License v1.0 which
  12. * accompanies this distribution, is reproduced below, and is
  13. * available at http://www.eclipse.org/org/documents/edl-v10.php
  14. *
  15. * All rights reserved.
  16. *
  17. * Redistribution and use in source and binary forms, with or
  18. * without modification, are permitted provided that the following
  19. * conditions are met:
  20. *
  21. * - Redistributions of source code must retain the above copyright
  22. * notice, this list of conditions and the following disclaimer.
  23. *
  24. * - Redistributions in binary form must reproduce the above
  25. * copyright notice, this list of conditions and the following
  26. * disclaimer in the documentation and/or other materials provided
  27. * with the distribution.
  28. *
  29. * - Neither the name of the Eclipse Foundation, Inc. nor the
  30. * names of its contributors may be used to endorse or promote
  31. * products derived from this software without specific prior
  32. * written permission.
  33. *
  34. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  35. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  36. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  38. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  39. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  43. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  46. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  47. */
  48. package org.eclipse.jgit.lib;
  49. import static java.util.concurrent.TimeUnit.DAYS;
  50. import static java.util.concurrent.TimeUnit.HOURS;
  51. import static java.util.concurrent.TimeUnit.MILLISECONDS;
  52. import static java.util.concurrent.TimeUnit.MINUTES;
  53. import static java.util.concurrent.TimeUnit.SECONDS;
  54. import static org.junit.Assert.assertArrayEquals;
  55. import static org.junit.Assert.assertEquals;
  56. import static org.junit.Assert.assertFalse;
  57. import static org.junit.Assert.assertNull;
  58. import static org.junit.Assert.assertSame;
  59. import static org.junit.Assert.assertTrue;
  60. import static org.junit.Assert.fail;
  61. import java.io.File;
  62. import java.io.IOException;
  63. import java.nio.file.Files;
  64. import java.text.MessageFormat;
  65. import java.util.Arrays;
  66. import java.util.Iterator;
  67. import java.util.LinkedList;
  68. import java.util.Set;
  69. import java.util.concurrent.TimeUnit;
  70. import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
  71. import org.eclipse.jgit.errors.ConfigInvalidException;
  72. import org.eclipse.jgit.internal.JGitText;
  73. import org.eclipse.jgit.junit.MockSystemReader;
  74. import org.eclipse.jgit.merge.MergeConfig;
  75. import org.eclipse.jgit.storage.file.FileBasedConfig;
  76. import org.eclipse.jgit.util.FS;
  77. import org.eclipse.jgit.util.SystemReader;
  78. import org.junit.After;
  79. import org.junit.Rule;
  80. import org.junit.Test;
  81. import org.junit.rules.ExpectedException;
  82. import org.junit.rules.TemporaryFolder;
  83. /**
  84. * Test reading of git config
  85. */
  86. public class ConfigTest {
  87. @Rule
  88. public ExpectedException expectedEx = ExpectedException.none();
  89. @Rule
  90. public TemporaryFolder tmp = new TemporaryFolder();
  91. @After
  92. public void tearDown() {
  93. SystemReader.setInstance(null);
  94. }
  95. @Test
  96. public void test001_ReadBareKey() throws ConfigInvalidException {
  97. final Config c = parse("[foo]\nbar\n");
  98. assertTrue(c.getBoolean("foo", null, "bar", false));
  99. assertEquals("", c.getString("foo", null, "bar"));
  100. }
  101. @Test
  102. public void test002_ReadWithSubsection() throws ConfigInvalidException {
  103. final Config c = parse("[foo \"zip\"]\nbar\n[foo \"zap\"]\nbar=false\nn=3\n");
  104. assertTrue(c.getBoolean("foo", "zip", "bar", false));
  105. assertEquals("", c.getString("foo","zip", "bar"));
  106. assertFalse(c.getBoolean("foo", "zap", "bar", true));
  107. assertEquals("false", c.getString("foo", "zap", "bar"));
  108. assertEquals(3, c.getInt("foo", "zap", "n", 4));
  109. assertEquals(4, c.getInt("foo", "zap","m", 4));
  110. }
  111. @Test
  112. public void test003_PutRemote() {
  113. final Config c = new Config();
  114. c.setString("sec", "ext", "name", "value");
  115. c.setString("sec", "ext", "name2", "value2");
  116. final String expText = "[sec \"ext\"]\n\tname = value\n\tname2 = value2\n";
  117. assertEquals(expText, c.toText());
  118. }
  119. @Test
  120. public void test004_PutGetSimple() {
  121. Config c = new Config();
  122. c.setString("my", null, "somename", "false");
  123. assertEquals("false", c.getString("my", null, "somename"));
  124. assertEquals("[my]\n\tsomename = false\n", c.toText());
  125. }
  126. @Test
  127. public void test005_PutGetStringList() {
  128. Config c = new Config();
  129. final LinkedList<String> values = new LinkedList<>();
  130. values.add("value1");
  131. values.add("value2");
  132. c.setStringList("my", null, "somename", values);
  133. final Object[] expArr = values.toArray();
  134. final String[] actArr = c.getStringList("my", null, "somename");
  135. assertArrayEquals(expArr, actArr);
  136. final String expText = "[my]\n\tsomename = value1\n\tsomename = value2\n";
  137. assertEquals(expText, c.toText());
  138. }
  139. @Test
  140. public void test006_readCaseInsensitive() throws ConfigInvalidException {
  141. final Config c = parse("[Foo]\nBar\n");
  142. assertTrue(c.getBoolean("foo", null, "bar", false));
  143. assertEquals("", c.getString("foo", null, "bar"));
  144. }
  145. @Test
  146. public void test007_readUserConfig() {
  147. final MockSystemReader mockSystemReader = new MockSystemReader();
  148. SystemReader.setInstance(mockSystemReader);
  149. final String hostname = mockSystemReader.getHostname();
  150. final Config userGitConfig = mockSystemReader.openUserConfig(null,
  151. FS.DETECTED);
  152. final Config localConfig = new Config(userGitConfig);
  153. mockSystemReader.clearProperties();
  154. String authorName;
  155. String authorEmail;
  156. // no values defined nowhere
  157. authorName = localConfig.get(UserConfig.KEY).getAuthorName();
  158. authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail();
  159. assertEquals(Constants.UNKNOWN_USER_DEFAULT, authorName);
  160. assertEquals(Constants.UNKNOWN_USER_DEFAULT + "@" + hostname, authorEmail);
  161. assertTrue(localConfig.get(UserConfig.KEY).isAuthorNameImplicit());
  162. assertTrue(localConfig.get(UserConfig.KEY).isAuthorEmailImplicit());
  163. // the system user name is defined
  164. mockSystemReader.setProperty(Constants.OS_USER_NAME_KEY, "os user name");
  165. localConfig.uncache(UserConfig.KEY);
  166. authorName = localConfig.get(UserConfig.KEY).getAuthorName();
  167. assertEquals("os user name", authorName);
  168. assertTrue(localConfig.get(UserConfig.KEY).isAuthorNameImplicit());
  169. if (hostname != null && hostname.length() != 0) {
  170. authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail();
  171. assertEquals("os user name@" + hostname, authorEmail);
  172. }
  173. assertTrue(localConfig.get(UserConfig.KEY).isAuthorEmailImplicit());
  174. // the git environment variables are defined
  175. mockSystemReader.setProperty(Constants.GIT_AUTHOR_NAME_KEY, "git author name");
  176. mockSystemReader.setProperty(Constants.GIT_AUTHOR_EMAIL_KEY, "author@email");
  177. localConfig.uncache(UserConfig.KEY);
  178. authorName = localConfig.get(UserConfig.KEY).getAuthorName();
  179. authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail();
  180. assertEquals("git author name", authorName);
  181. assertEquals("author@email", authorEmail);
  182. assertFalse(localConfig.get(UserConfig.KEY).isAuthorNameImplicit());
  183. assertFalse(localConfig.get(UserConfig.KEY).isAuthorEmailImplicit());
  184. // the values are defined in the global configuration
  185. // first clear environment variables since they would override
  186. // configuration files
  187. mockSystemReader.clearProperties();
  188. userGitConfig.setString("user", null, "name", "global username");
  189. userGitConfig.setString("user", null, "email", "author@globalemail");
  190. authorName = localConfig.get(UserConfig.KEY).getAuthorName();
  191. authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail();
  192. assertEquals("global username", authorName);
  193. assertEquals("author@globalemail", authorEmail);
  194. assertFalse(localConfig.get(UserConfig.KEY).isAuthorNameImplicit());
  195. assertFalse(localConfig.get(UserConfig.KEY).isAuthorEmailImplicit());
  196. // the values are defined in the local configuration
  197. localConfig.setString("user", null, "name", "local username");
  198. localConfig.setString("user", null, "email", "author@localemail");
  199. authorName = localConfig.get(UserConfig.KEY).getAuthorName();
  200. authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail();
  201. assertEquals("local username", authorName);
  202. assertEquals("author@localemail", authorEmail);
  203. assertFalse(localConfig.get(UserConfig.KEY).isAuthorNameImplicit());
  204. assertFalse(localConfig.get(UserConfig.KEY).isAuthorEmailImplicit());
  205. authorName = localConfig.get(UserConfig.KEY).getCommitterName();
  206. authorEmail = localConfig.get(UserConfig.KEY).getCommitterEmail();
  207. assertEquals("local username", authorName);
  208. assertEquals("author@localemail", authorEmail);
  209. assertFalse(localConfig.get(UserConfig.KEY).isCommitterNameImplicit());
  210. assertFalse(localConfig.get(UserConfig.KEY).isCommitterEmailImplicit());
  211. // also git environment variables are defined
  212. mockSystemReader.setProperty(Constants.GIT_AUTHOR_NAME_KEY,
  213. "git author name");
  214. mockSystemReader.setProperty(Constants.GIT_AUTHOR_EMAIL_KEY,
  215. "author@email");
  216. localConfig.setString("user", null, "name", "local username");
  217. localConfig.setString("user", null, "email", "author@localemail");
  218. authorName = localConfig.get(UserConfig.KEY).getAuthorName();
  219. authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail();
  220. assertEquals("git author name", authorName);
  221. assertEquals("author@email", authorEmail);
  222. assertFalse(localConfig.get(UserConfig.KEY).isAuthorNameImplicit());
  223. assertFalse(localConfig.get(UserConfig.KEY).isAuthorEmailImplicit());
  224. }
  225. @Test
  226. public void testReadUserConfigWithInvalidCharactersStripped() {
  227. final MockSystemReader mockSystemReader = new MockSystemReader();
  228. final Config localConfig = new Config(mockSystemReader.openUserConfig(
  229. null, FS.DETECTED));
  230. localConfig.setString("user", null, "name", "foo<bar");
  231. localConfig.setString("user", null, "email", "baz>\nqux@example.com");
  232. UserConfig userConfig = localConfig.get(UserConfig.KEY);
  233. assertEquals("foobar", userConfig.getAuthorName());
  234. assertEquals("bazqux@example.com", userConfig.getAuthorEmail());
  235. }
  236. @Test
  237. public void testReadBoolean_TrueFalse1() throws ConfigInvalidException {
  238. final Config c = parse("[s]\na = true\nb = false\n");
  239. assertEquals("true", c.getString("s", null, "a"));
  240. assertEquals("false", c.getString("s", null, "b"));
  241. assertTrue(c.getBoolean("s", "a", false));
  242. assertFalse(c.getBoolean("s", "b", true));
  243. }
  244. @Test
  245. public void testReadBoolean_TrueFalse2() throws ConfigInvalidException {
  246. final Config c = parse("[s]\na = TrUe\nb = fAlSe\n");
  247. assertEquals("TrUe", c.getString("s", null, "a"));
  248. assertEquals("fAlSe", c.getString("s", null, "b"));
  249. assertTrue(c.getBoolean("s", "a", false));
  250. assertFalse(c.getBoolean("s", "b", true));
  251. }
  252. @Test
  253. public void testReadBoolean_YesNo1() throws ConfigInvalidException {
  254. final Config c = parse("[s]\na = yes\nb = no\n");
  255. assertEquals("yes", c.getString("s", null, "a"));
  256. assertEquals("no", c.getString("s", null, "b"));
  257. assertTrue(c.getBoolean("s", "a", false));
  258. assertFalse(c.getBoolean("s", "b", true));
  259. }
  260. @Test
  261. public void testReadBoolean_YesNo2() throws ConfigInvalidException {
  262. final Config c = parse("[s]\na = yEs\nb = NO\n");
  263. assertEquals("yEs", c.getString("s", null, "a"));
  264. assertEquals("NO", c.getString("s", null, "b"));
  265. assertTrue(c.getBoolean("s", "a", false));
  266. assertFalse(c.getBoolean("s", "b", true));
  267. }
  268. @Test
  269. public void testReadBoolean_OnOff1() throws ConfigInvalidException {
  270. final Config c = parse("[s]\na = on\nb = off\n");
  271. assertEquals("on", c.getString("s", null, "a"));
  272. assertEquals("off", c.getString("s", null, "b"));
  273. assertTrue(c.getBoolean("s", "a", false));
  274. assertFalse(c.getBoolean("s", "b", true));
  275. }
  276. @Test
  277. public void testReadBoolean_OnOff2() throws ConfigInvalidException {
  278. final Config c = parse("[s]\na = ON\nb = OFF\n");
  279. assertEquals("ON", c.getString("s", null, "a"));
  280. assertEquals("OFF", c.getString("s", null, "b"));
  281. assertTrue(c.getBoolean("s", "a", false));
  282. assertFalse(c.getBoolean("s", "b", true));
  283. }
  284. static enum TestEnum {
  285. ONE_TWO;
  286. }
  287. @Test
  288. public void testGetEnum() throws ConfigInvalidException {
  289. Config c = parse("[s]\na = ON\nb = input\nc = true\nd = off\n");
  290. assertSame(CoreConfig.AutoCRLF.TRUE, c.getEnum("s", null, "a",
  291. CoreConfig.AutoCRLF.FALSE));
  292. assertSame(CoreConfig.AutoCRLF.INPUT, c.getEnum("s", null, "b",
  293. CoreConfig.AutoCRLF.FALSE));
  294. assertSame(CoreConfig.AutoCRLF.TRUE, c.getEnum("s", null, "c",
  295. CoreConfig.AutoCRLF.FALSE));
  296. assertSame(CoreConfig.AutoCRLF.FALSE, c.getEnum("s", null, "d",
  297. CoreConfig.AutoCRLF.TRUE));
  298. c = new Config();
  299. assertSame(CoreConfig.AutoCRLF.FALSE, c.getEnum("s", null, "d",
  300. CoreConfig.AutoCRLF.FALSE));
  301. c = parse("[s \"b\"]\n\tc = one two\n");
  302. assertSame(TestEnum.ONE_TWO, c.getEnum("s", "b", "c", TestEnum.ONE_TWO));
  303. c = parse("[s \"b\"]\n\tc = one-two\n");
  304. assertSame(TestEnum.ONE_TWO, c.getEnum("s", "b", "c", TestEnum.ONE_TWO));
  305. }
  306. @Test
  307. public void testGetInvalidEnum() throws ConfigInvalidException {
  308. Config c = parse("[a]\n\tb = invalid\n");
  309. try {
  310. c.getEnum("a", null, "b", TestEnum.ONE_TWO);
  311. fail();
  312. } catch (IllegalArgumentException e) {
  313. assertEquals("Invalid value: a.b=invalid", e.getMessage());
  314. }
  315. c = parse("[a \"b\"]\n\tc = invalid\n");
  316. try {
  317. c.getEnum("a", "b", "c", TestEnum.ONE_TWO);
  318. fail();
  319. } catch (IllegalArgumentException e) {
  320. assertEquals("Invalid value: a.b.c=invalid", e.getMessage());
  321. }
  322. }
  323. @Test
  324. public void testSetEnum() {
  325. final Config c = new Config();
  326. c.setEnum("s", "b", "c", TestEnum.ONE_TWO);
  327. assertEquals("[s \"b\"]\n\tc = one two\n", c.toText());
  328. }
  329. @Test
  330. public void testGetFastForwardMergeoptions() throws ConfigInvalidException {
  331. Config c = new Config(null); // not set
  332. assertSame(FastForwardMode.FF, c.getEnum(
  333. ConfigConstants.CONFIG_BRANCH_SECTION, "side",
  334. ConfigConstants.CONFIG_KEY_MERGEOPTIONS, FastForwardMode.FF));
  335. MergeConfig mergeConfig = c.get(MergeConfig.getParser("side"));
  336. assertSame(FastForwardMode.FF, mergeConfig.getFastForwardMode());
  337. c = parse("[branch \"side\"]\n\tmergeoptions = --ff-only\n");
  338. assertSame(FastForwardMode.FF_ONLY, c.getEnum(
  339. ConfigConstants.CONFIG_BRANCH_SECTION, "side",
  340. ConfigConstants.CONFIG_KEY_MERGEOPTIONS,
  341. FastForwardMode.FF_ONLY));
  342. mergeConfig = c.get(MergeConfig.getParser("side"));
  343. assertSame(FastForwardMode.FF_ONLY, mergeConfig.getFastForwardMode());
  344. c = parse("[branch \"side\"]\n\tmergeoptions = --ff\n");
  345. assertSame(FastForwardMode.FF, c.getEnum(
  346. ConfigConstants.CONFIG_BRANCH_SECTION, "side",
  347. ConfigConstants.CONFIG_KEY_MERGEOPTIONS, FastForwardMode.FF));
  348. mergeConfig = c.get(MergeConfig.getParser("side"));
  349. assertSame(FastForwardMode.FF, mergeConfig.getFastForwardMode());
  350. c = parse("[branch \"side\"]\n\tmergeoptions = --no-ff\n");
  351. assertSame(FastForwardMode.NO_FF, c.getEnum(
  352. ConfigConstants.CONFIG_BRANCH_SECTION, "side",
  353. ConfigConstants.CONFIG_KEY_MERGEOPTIONS, FastForwardMode.NO_FF));
  354. mergeConfig = c.get(MergeConfig.getParser("side"));
  355. assertSame(FastForwardMode.NO_FF, mergeConfig.getFastForwardMode());
  356. }
  357. @Test
  358. public void testSetFastForwardMergeoptions() {
  359. final Config c = new Config();
  360. c.setEnum("branch", "side", "mergeoptions", FastForwardMode.FF);
  361. assertEquals("[branch \"side\"]\n\tmergeoptions = --ff\n", c.toText());
  362. c.setEnum("branch", "side", "mergeoptions", FastForwardMode.FF_ONLY);
  363. assertEquals("[branch \"side\"]\n\tmergeoptions = --ff-only\n",
  364. c.toText());
  365. c.setEnum("branch", "side", "mergeoptions", FastForwardMode.NO_FF);
  366. assertEquals("[branch \"side\"]\n\tmergeoptions = --no-ff\n",
  367. c.toText());
  368. }
  369. @Test
  370. public void testGetFastForwardMerge() throws ConfigInvalidException {
  371. Config c = new Config(null); // not set
  372. assertSame(FastForwardMode.Merge.TRUE, c.getEnum(
  373. ConfigConstants.CONFIG_KEY_MERGE, null,
  374. ConfigConstants.CONFIG_KEY_FF, FastForwardMode.Merge.TRUE));
  375. MergeConfig mergeConfig = c.get(MergeConfig.getParser("side"));
  376. assertSame(FastForwardMode.FF, mergeConfig.getFastForwardMode());
  377. c = parse("[merge]\n\tff = only\n");
  378. assertSame(FastForwardMode.Merge.ONLY, c.getEnum(
  379. ConfigConstants.CONFIG_KEY_MERGE, null,
  380. ConfigConstants.CONFIG_KEY_FF, FastForwardMode.Merge.ONLY));
  381. mergeConfig = c.get(MergeConfig.getParser("side"));
  382. assertSame(FastForwardMode.FF_ONLY, mergeConfig.getFastForwardMode());
  383. c = parse("[merge]\n\tff = true\n");
  384. assertSame(FastForwardMode.Merge.TRUE, c.getEnum(
  385. ConfigConstants.CONFIG_KEY_MERGE, null,
  386. ConfigConstants.CONFIG_KEY_FF, FastForwardMode.Merge.TRUE));
  387. mergeConfig = c.get(MergeConfig.getParser("side"));
  388. assertSame(FastForwardMode.FF, mergeConfig.getFastForwardMode());
  389. c = parse("[merge]\n\tff = false\n");
  390. assertSame(FastForwardMode.Merge.FALSE, c.getEnum(
  391. ConfigConstants.CONFIG_KEY_MERGE, null,
  392. ConfigConstants.CONFIG_KEY_FF, FastForwardMode.Merge.FALSE));
  393. mergeConfig = c.get(MergeConfig.getParser("side"));
  394. assertSame(FastForwardMode.NO_FF, mergeConfig.getFastForwardMode());
  395. }
  396. @Test
  397. public void testCombinedMergeOptions() throws ConfigInvalidException {
  398. Config c = new Config(null); // not set
  399. MergeConfig mergeConfig = c.get(MergeConfig.getParser("side"));
  400. assertSame(FastForwardMode.FF, mergeConfig.getFastForwardMode());
  401. assertTrue(mergeConfig.isCommit());
  402. assertFalse(mergeConfig.isSquash());
  403. // branch..mergeoptions should win over merge.ff
  404. c = parse("[merge]\n\tff = false\n"
  405. + "[branch \"side\"]\n\tmergeoptions = --ff-only\n");
  406. mergeConfig = c.get(MergeConfig.getParser("side"));
  407. assertSame(FastForwardMode.FF_ONLY, mergeConfig.getFastForwardMode());
  408. assertTrue(mergeConfig.isCommit());
  409. assertFalse(mergeConfig.isSquash());
  410. // merge.ff used for ff setting if not set via mergeoptions
  411. c = parse("[merge]\n\tff = only\n"
  412. + "[branch \"side\"]\n\tmergeoptions = --squash\n");
  413. mergeConfig = c.get(MergeConfig.getParser("side"));
  414. assertSame(FastForwardMode.FF_ONLY, mergeConfig.getFastForwardMode());
  415. assertTrue(mergeConfig.isCommit());
  416. assertTrue(mergeConfig.isSquash());
  417. // mergeoptions wins if it has ff options amongst other options
  418. c = parse("[merge]\n\tff = false\n"
  419. + "[branch \"side\"]\n\tmergeoptions = --ff-only --no-commit\n");
  420. mergeConfig = c.get(MergeConfig.getParser("side"));
  421. assertSame(FastForwardMode.FF_ONLY, mergeConfig.getFastForwardMode());
  422. assertFalse(mergeConfig.isCommit());
  423. assertFalse(mergeConfig.isSquash());
  424. }
  425. @Test
  426. public void testSetFastForwardMerge() {
  427. final Config c = new Config();
  428. c.setEnum("merge", null, "ff",
  429. FastForwardMode.Merge.valueOf(FastForwardMode.FF));
  430. assertEquals("[merge]\n\tff = true\n", c.toText());
  431. c.setEnum("merge", null, "ff",
  432. FastForwardMode.Merge.valueOf(FastForwardMode.FF_ONLY));
  433. assertEquals("[merge]\n\tff = only\n", c.toText());
  434. c.setEnum("merge", null, "ff",
  435. FastForwardMode.Merge.valueOf(FastForwardMode.NO_FF));
  436. assertEquals("[merge]\n\tff = false\n", c.toText());
  437. }
  438. @Test
  439. public void testReadLong() throws ConfigInvalidException {
  440. assertReadLong(1L);
  441. assertReadLong(-1L);
  442. assertReadLong(Long.MIN_VALUE);
  443. assertReadLong(Long.MAX_VALUE);
  444. assertReadLong(4L * 1024 * 1024 * 1024, "4g");
  445. assertReadLong(3L * 1024 * 1024, "3 m");
  446. assertReadLong(8L * 1024, "8 k");
  447. try {
  448. assertReadLong(-1, "1.5g");
  449. fail("incorrectly accepted 1.5g");
  450. } catch (IllegalArgumentException e) {
  451. assertEquals("Invalid integer value: s.a=1.5g", e.getMessage());
  452. }
  453. }
  454. @Test
  455. public void testBooleanWithNoValue() throws ConfigInvalidException {
  456. Config c = parse("[my]\n\tempty\n");
  457. assertEquals("", c.getString("my", null, "empty"));
  458. assertEquals(1, c.getStringList("my", null, "empty").length);
  459. assertEquals("", c.getStringList("my", null, "empty")[0]);
  460. assertTrue(c.getBoolean("my", "empty", false));
  461. assertEquals("[my]\n\tempty\n", c.toText());
  462. }
  463. @Test
  464. public void testUnsetBranchSection() throws ConfigInvalidException {
  465. Config c = parse("" //
  466. + "[branch \"keep\"]\n"
  467. + " merge = master.branch.to.keep.in.the.file\n"
  468. + "\n"
  469. + "[branch \"remove\"]\n"
  470. + " merge = this.will.get.deleted\n"
  471. + " remote = origin-for-some-long-gone-place\n"
  472. + "\n"
  473. + "[core-section-not-to-remove-in-test]\n"
  474. + " packedGitLimit = 14\n");
  475. c.unsetSection("branch", "does.not.exist");
  476. c.unsetSection("branch", "remove");
  477. assertEquals("" //
  478. + "[branch \"keep\"]\n"
  479. + " merge = master.branch.to.keep.in.the.file\n"
  480. + "\n"
  481. + "[core-section-not-to-remove-in-test]\n"
  482. + " packedGitLimit = 14\n", c.toText());
  483. }
  484. @Test
  485. public void testUnsetSingleSection() throws ConfigInvalidException {
  486. Config c = parse("" //
  487. + "[branch \"keep\"]\n"
  488. + " merge = master.branch.to.keep.in.the.file\n"
  489. + "\n"
  490. + "[single]\n"
  491. + " merge = this.will.get.deleted\n"
  492. + " remote = origin-for-some-long-gone-place\n"
  493. + "\n"
  494. + "[core-section-not-to-remove-in-test]\n"
  495. + " packedGitLimit = 14\n");
  496. c.unsetSection("single", null);
  497. assertEquals("" //
  498. + "[branch \"keep\"]\n"
  499. + " merge = master.branch.to.keep.in.the.file\n"
  500. + "\n"
  501. + "[core-section-not-to-remove-in-test]\n"
  502. + " packedGitLimit = 14\n", c.toText());
  503. }
  504. @Test
  505. public void test008_readSectionNames() throws ConfigInvalidException {
  506. final Config c = parse("[a]\n [B]\n");
  507. Set<String> sections = c.getSections();
  508. assertTrue("Sections should contain \"a\"", sections.contains("a"));
  509. assertTrue("Sections should contain \"b\"", sections.contains("b"));
  510. }
  511. @Test
  512. public void test009_readNamesInSection() throws ConfigInvalidException {
  513. String configString = "[core]\n" + "repositoryFormatVersion = 0\n"
  514. + "filemode = false\n" + "logAllRefUpdates = true\n";
  515. final Config c = parse(configString);
  516. Set<String> names = c.getNames("core");
  517. assertEquals("Core section size", 3, names.size());
  518. assertTrue("Core section should contain \"filemode\"", names
  519. .contains("filemode"));
  520. assertTrue("Core section should contain \"repositoryFormatVersion\"",
  521. names.contains("repositoryFormatVersion"));
  522. assertTrue("Core section should contain \"repositoryformatversion\"",
  523. names.contains("repositoryformatversion"));
  524. Iterator<String> itr = names.iterator();
  525. assertEquals("filemode", itr.next());
  526. assertEquals("logAllRefUpdates", itr.next());
  527. assertEquals("repositoryFormatVersion", itr.next());
  528. assertFalse(itr.hasNext());
  529. }
  530. @Test
  531. public void test_ReadNamesInSectionRecursive()
  532. throws ConfigInvalidException {
  533. String baseConfigString = "[core]\n" + "logAllRefUpdates = true\n";
  534. String configString = "[core]\n" + "repositoryFormatVersion = 0\n"
  535. + "filemode = false\n";
  536. final Config c = parse(configString, parse(baseConfigString));
  537. Set<String> names = c.getNames("core", true);
  538. assertEquals("Core section size", 3, names.size());
  539. assertTrue("Core section should contain \"filemode\"",
  540. names.contains("filemode"));
  541. assertTrue("Core section should contain \"repositoryFormatVersion\"",
  542. names.contains("repositoryFormatVersion"));
  543. assertTrue("Core section should contain \"logAllRefUpdates\"",
  544. names.contains("logAllRefUpdates"));
  545. assertTrue("Core section should contain \"logallrefupdates\"",
  546. names.contains("logallrefupdates"));
  547. Iterator<String> itr = names.iterator();
  548. assertEquals("filemode", itr.next());
  549. assertEquals("repositoryFormatVersion", itr.next());
  550. assertEquals("logAllRefUpdates", itr.next());
  551. assertFalse(itr.hasNext());
  552. }
  553. @Test
  554. public void test010_readNamesInSubSection() throws ConfigInvalidException {
  555. String configString = "[a \"sub1\"]\n"//
  556. + "x = 0\n" //
  557. + "y = false\n"//
  558. + "z = true\n"//
  559. + "[a \"sub2\"]\n"//
  560. + "a=0\n"//
  561. + "b=1\n";
  562. final Config c = parse(configString);
  563. Set<String> names = c.getNames("a", "sub1");
  564. assertEquals("Subsection size", 3, names.size());
  565. assertTrue("Subsection should contain \"x\"", names.contains("x"));
  566. assertTrue("Subsection should contain \"y\"", names.contains("y"));
  567. assertTrue("Subsection should contain \"z\"", names.contains("z"));
  568. names = c.getNames("a", "sub2");
  569. assertEquals("Subsection size", 2, names.size());
  570. assertTrue("Subsection should contain \"a\"", names.contains("a"));
  571. assertTrue("Subsection should contain \"b\"", names.contains("b"));
  572. }
  573. @Test
  574. public void readNamesInSubSectionRecursive() throws ConfigInvalidException {
  575. String baseConfigString = "[a \"sub1\"]\n"//
  576. + "x = 0\n" //
  577. + "y = false\n"//
  578. + "[a \"sub2\"]\n"//
  579. + "A=0\n";//
  580. String configString = "[a \"sub1\"]\n"//
  581. + "z = true\n"//
  582. + "[a \"sub2\"]\n"//
  583. + "B=1\n";
  584. final Config c = parse(configString, parse(baseConfigString));
  585. Set<String> names = c.getNames("a", "sub1", true);
  586. assertEquals("Subsection size", 3, names.size());
  587. assertTrue("Subsection should contain \"x\"", names.contains("x"));
  588. assertTrue("Subsection should contain \"y\"", names.contains("y"));
  589. assertTrue("Subsection should contain \"z\"", names.contains("z"));
  590. names = c.getNames("a", "sub2", true);
  591. assertEquals("Subsection size", 2, names.size());
  592. assertTrue("Subsection should contain \"A\"", names.contains("A"));
  593. assertTrue("Subsection should contain \"a\"", names.contains("a"));
  594. assertTrue("Subsection should contain \"B\"", names.contains("B"));
  595. }
  596. @Test
  597. public void testQuotingForSubSectionNames() {
  598. String resultPattern = "[testsection \"{0}\"]\n\ttestname = testvalue\n";
  599. String result;
  600. Config config = new Config();
  601. config.setString("testsection", "testsubsection", "testname",
  602. "testvalue");
  603. result = MessageFormat.format(resultPattern, "testsubsection");
  604. assertEquals(result, config.toText());
  605. config.clear();
  606. config.setString("testsection", "#quotable", "testname", "testvalue");
  607. result = MessageFormat.format(resultPattern, "#quotable");
  608. assertEquals(result, config.toText());
  609. config.clear();
  610. config.setString("testsection", "with\"quote", "testname", "testvalue");
  611. result = MessageFormat.format(resultPattern, "with\\\"quote");
  612. assertEquals(result, config.toText());
  613. }
  614. @Test
  615. public void testNoFinalNewline() throws ConfigInvalidException {
  616. Config c = parse("[a]\n"
  617. + "x = 0\n"
  618. + "y = 1");
  619. assertEquals("0", c.getString("a", null, "x"));
  620. assertEquals("1", c.getString("a", null, "y"));
  621. }
  622. @Test
  623. public void testExplicitlySetEmptyString() throws Exception {
  624. Config c = new Config();
  625. c.setString("a", null, "x", "0");
  626. c.setString("a", null, "y", "");
  627. assertEquals("0", c.getString("a", null, "x"));
  628. assertEquals(0, c.getInt("a", null, "x", 1));
  629. assertEquals("", c.getString("a", null, "y"));
  630. assertArrayEquals(new String[]{""}, c.getStringList("a", null, "y"));
  631. try {
  632. c.getInt("a", null, "y", 1);
  633. } catch (IllegalArgumentException e) {
  634. assertEquals("Invalid integer value: a.y=", e.getMessage());
  635. }
  636. assertNull(c.getString("a", null, "z"));
  637. assertArrayEquals(new String[]{}, c.getStringList("a", null, "z"));
  638. }
  639. @Test
  640. public void testParsedEmptyString() throws Exception {
  641. Config c = parse("[a]\n"
  642. + "x = 0\n"
  643. + "y =\n");
  644. assertEquals("0", c.getString("a", null, "x"));
  645. assertEquals(0, c.getInt("a", null, "x", 1));
  646. assertNull(c.getString("a", null, "y"));
  647. assertArrayEquals(new String[]{null}, c.getStringList("a", null, "y"));
  648. try {
  649. c.getInt("a", null, "y", 1);
  650. } catch (IllegalArgumentException e) {
  651. assertEquals("Invalid integer value: a.y=", e.getMessage());
  652. }
  653. assertNull(c.getString("a", null, "z"));
  654. assertArrayEquals(new String[]{}, c.getStringList("a", null, "z"));
  655. }
  656. @Test
  657. public void testSetStringListWithEmptyValue() throws Exception {
  658. Config c = new Config();
  659. c.setStringList("a", null, "x", Arrays.asList(""));
  660. assertArrayEquals(new String[]{""}, c.getStringList("a", null, "x"));
  661. }
  662. @Test
  663. public void testEmptyValueAtEof() throws Exception {
  664. String text = "[a]\nx =";
  665. Config c = parse(text);
  666. assertNull(c.getString("a", null, "x"));
  667. assertArrayEquals(new String[]{null},
  668. c.getStringList("a", null, "x"));
  669. c = parse(text + "\n");
  670. assertNull(c.getString("a", null, "x"));
  671. assertArrayEquals(new String[]{null},
  672. c.getStringList("a", null, "x"));
  673. }
  674. @Test
  675. public void testReadMultipleValuesForName() throws ConfigInvalidException {
  676. Config c = parse("[foo]\nbar=false\nbar=true\n");
  677. assertTrue(c.getBoolean("foo", "bar", false));
  678. }
  679. @Test
  680. public void testIncludeInvalidName() throws ConfigInvalidException {
  681. expectedEx.expect(ConfigInvalidException.class);
  682. expectedEx.expectMessage(JGitText.get().invalidLineInConfigFile);
  683. parse("[include]\nbar\n");
  684. }
  685. @Test
  686. public void testIncludeNoValue() throws ConfigInvalidException {
  687. expectedEx.expect(ConfigInvalidException.class);
  688. expectedEx.expectMessage(JGitText.get().invalidLineInConfigFile);
  689. parse("[include]\npath\n");
  690. }
  691. @Test
  692. public void testIncludeEmptyValue() throws ConfigInvalidException {
  693. expectedEx.expect(ConfigInvalidException.class);
  694. expectedEx.expectMessage(JGitText.get().invalidLineInConfigFile);
  695. parse("[include]\npath=\n");
  696. }
  697. @Test
  698. public void testIncludeValuePathNotFound() throws ConfigInvalidException {
  699. // we do not expect an exception, included path not found are ignored
  700. String notFound = "/not/found";
  701. Config parsed = parse("[include]\npath=" + notFound + "\n");
  702. assertEquals(1, parsed.getSections().size());
  703. assertEquals(notFound, parsed.getString("include", null, "path"));
  704. }
  705. @Test
  706. public void testIncludeValuePathWithTilde() throws ConfigInvalidException {
  707. // we do not expect an exception, included path not supported are
  708. // ignored
  709. String notSupported = "~/someFile";
  710. Config parsed = parse("[include]\npath=" + notSupported + "\n");
  711. assertEquals(1, parsed.getSections().size());
  712. assertEquals(notSupported, parsed.getString("include", null, "path"));
  713. }
  714. @Test
  715. public void testIncludeValuePathRelative() throws ConfigInvalidException {
  716. // we do not expect an exception, included path not supported are
  717. // ignored
  718. String notSupported = "someRelativeFile";
  719. Config parsed = parse("[include]\npath=" + notSupported + "\n");
  720. assertEquals(1, parsed.getSections().size());
  721. assertEquals(notSupported, parsed.getString("include", null, "path"));
  722. }
  723. @Test
  724. public void testIncludeTooManyRecursions() throws IOException {
  725. File config = tmp.newFile("config");
  726. String include = "[include]\npath=" + config.toPath() + "\n";
  727. Files.write(config.toPath(), include.getBytes());
  728. FileBasedConfig fbConfig = new FileBasedConfig(null, config,
  729. FS.DETECTED);
  730. try {
  731. fbConfig.load();
  732. fail();
  733. } catch (ConfigInvalidException cie) {
  734. assertEquals(JGitText.get().tooManyIncludeRecursions,
  735. cie.getCause().getMessage());
  736. }
  737. }
  738. @Test
  739. public void testInclude() throws IOException, ConfigInvalidException {
  740. File config = tmp.newFile("config");
  741. File more = tmp.newFile("config.more");
  742. File other = tmp.newFile("config.other");
  743. String fooBar = "[foo]\nbar=true\n";
  744. String includeMore = "[include]\npath=" + more.toPath() + "\n";
  745. String includeOther = "path=" + other.toPath() + "\n";
  746. String fooPlus = fooBar + includeMore + includeOther;
  747. Files.write(config.toPath(), fooPlus.getBytes());
  748. String fooMore = "[foo]\nmore=bar\n";
  749. Files.write(more.toPath(), fooMore.getBytes());
  750. String otherMore = "[other]\nmore=bar\n";
  751. Files.write(other.toPath(), otherMore.getBytes());
  752. Config parsed = parse("[include]\npath=" + config.toPath() + "\n");
  753. assertTrue(parsed.getBoolean("foo", "bar", false));
  754. assertEquals("bar", parsed.getString("foo", null, "more"));
  755. assertEquals("bar", parsed.getString("other", null, "more"));
  756. }
  757. private static void assertReadLong(long exp) throws ConfigInvalidException {
  758. assertReadLong(exp, String.valueOf(exp));
  759. }
  760. private static void assertReadLong(long exp, String act)
  761. throws ConfigInvalidException {
  762. final Config c = parse("[s]\na = " + act + "\n");
  763. assertEquals(exp, c.getLong("s", null, "a", 0L));
  764. }
  765. private static Config parse(final String content)
  766. throws ConfigInvalidException {
  767. return parse(content, null);
  768. }
  769. private static Config parse(final String content, Config baseConfig)
  770. throws ConfigInvalidException {
  771. final Config c = new Config(baseConfig);
  772. c.fromText(content);
  773. return c;
  774. }
  775. @Test
  776. public void testTimeUnit() throws ConfigInvalidException {
  777. assertEquals(0, parseTime("0", MILLISECONDS));
  778. assertEquals(2, parseTime("2ms", MILLISECONDS));
  779. assertEquals(200, parseTime("200 milliseconds", MILLISECONDS));
  780. assertEquals(0, parseTime("0s", SECONDS));
  781. assertEquals(2, parseTime("2s", SECONDS));
  782. assertEquals(231, parseTime("231sec", SECONDS));
  783. assertEquals(1, parseTime("1second", SECONDS));
  784. assertEquals(300, parseTime("300 seconds", SECONDS));
  785. assertEquals(2, parseTime("2m", MINUTES));
  786. assertEquals(2, parseTime("2min", MINUTES));
  787. assertEquals(1, parseTime("1 minute", MINUTES));
  788. assertEquals(10, parseTime("10 minutes", MINUTES));
  789. assertEquals(5, parseTime("5h", HOURS));
  790. assertEquals(5, parseTime("5hr", HOURS));
  791. assertEquals(1, parseTime("1hour", HOURS));
  792. assertEquals(48, parseTime("48hours", HOURS));
  793. assertEquals(5, parseTime("5 h", HOURS));
  794. assertEquals(5, parseTime("5 hr", HOURS));
  795. assertEquals(1, parseTime("1 hour", HOURS));
  796. assertEquals(48, parseTime("48 hours", HOURS));
  797. assertEquals(48, parseTime("48 \t \r hours", HOURS));
  798. assertEquals(4, parseTime("4d", DAYS));
  799. assertEquals(1, parseTime("1day", DAYS));
  800. assertEquals(14, parseTime("14days", DAYS));
  801. assertEquals(7, parseTime("1w", DAYS));
  802. assertEquals(7, parseTime("1week", DAYS));
  803. assertEquals(14, parseTime("2w", DAYS));
  804. assertEquals(14, parseTime("2weeks", DAYS));
  805. assertEquals(30, parseTime("1mon", DAYS));
  806. assertEquals(30, parseTime("1month", DAYS));
  807. assertEquals(60, parseTime("2mon", DAYS));
  808. assertEquals(60, parseTime("2months", DAYS));
  809. assertEquals(365, parseTime("1y", DAYS));
  810. assertEquals(365, parseTime("1year", DAYS));
  811. assertEquals(365 * 2, parseTime("2years", DAYS));
  812. }
  813. private long parseTime(String value, TimeUnit unit)
  814. throws ConfigInvalidException {
  815. Config c = parse("[a]\na=" + value + "\n");
  816. return c.getTimeUnit("a", null, "a", 0, unit);
  817. }
  818. @Test
  819. public void testTimeUnitDefaultValue() throws ConfigInvalidException {
  820. // value not present
  821. assertEquals(20, parse("[a]\na=0\n").getTimeUnit("a", null, "b", 20,
  822. MILLISECONDS));
  823. // value is empty
  824. assertEquals(20, parse("[a]\na=\" \"\n").getTimeUnit("a", null, "a", 20,
  825. MILLISECONDS));
  826. // value is not numeric
  827. assertEquals(20, parse("[a]\na=test\n").getTimeUnit("a", null, "a", 20,
  828. MILLISECONDS));
  829. }
  830. @Test
  831. public void testTimeUnitInvalid() throws ConfigInvalidException {
  832. expectedEx.expect(IllegalArgumentException.class);
  833. expectedEx
  834. .expectMessage("Invalid time unit value: a.a=1 monttthhh");
  835. parseTime("1 monttthhh", DAYS);
  836. }
  837. @Test
  838. public void testTimeUnitInvalidWithSection() throws ConfigInvalidException {
  839. Config c = parse("[a \"b\"]\na=1 monttthhh\n");
  840. expectedEx.expect(IllegalArgumentException.class);
  841. expectedEx.expectMessage("Invalid time unit value: a.b.a=1 monttthhh");
  842. c.getTimeUnit("a", "b", "a", 0, DAYS);
  843. }
  844. @Test
  845. public void testTimeUnitNegative() throws ConfigInvalidException {
  846. expectedEx.expect(IllegalArgumentException.class);
  847. parseTime("-1", MILLISECONDS);
  848. }
  849. }