File: hacking.html

package info (click to toggle)
subversion 1.4.2dfsg1-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 37,268 kB
  • ctags: 32,888
  • sloc: ansic: 406,472; python: 38,378; sh: 15,248; cpp: 9,604; ruby: 8,313; perl: 5,308; java: 4,576; lisp: 3,860; xml: 3,298; makefile: 856
file content (2698 lines) | stat: -rw-r--r-- 106,159 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style type="text/css"> /* <![CDATA[ */
  @import "tigris-branding/css/tigris.css";
  @import "tigris-branding/css/inst.css";
  /* ]]> */</style>
<link rel="stylesheet" type="text/css" media="print"
  href="tigris-branding/css/print.css"/>
<script type="text/javascript" src="tigris-branding/scripts/tigris.js"></script>
<title>Hacker's Guide to Subversion</title>
</head>

<body>
<div class="app">

<h1 style="text-align: center;">Hacker's Guide to Subversion</h1>

<p>If you are contributing code to the Subversion project, please read
this first.</p>

<pre>
$LastChangedDate: 2006-04-28 19:46:57 +0000 (Fri, 28 Apr 2006) $
</pre>

<![CDATA[=========================================================]]>

<!-- Other pages seem to use "h2" for ToC, but I think "h1" works
     better, because the ToC is fundamentally different from other
     sections and therefore it's confusing when it looks the same as
     the others. -->
<div class="h1"><!-- no 'id' or 'title' attribute for ToC -->
<h1>Table of Contents</h1>

<ul>
<li><a href="#participating"
             >Participating in the community</a></li>
<li><a href="#docs"
             >Theory and documentation</a></li>
<li><a href="#code-to-read"
             >Code to read</a></li>
<li><a href="#directory-layout"
             >Directory layout</a></li>
<li><a href="#coding-style"
             >Coding style</a></li>
<li><a href="#secure-coding"
             >Secure coding guidelines</a></li>
<li><a href="#destruction-of-stacked-resources"
             >Destruction of stacked resources</a></li>
<li><a href="#documenting"
             >Document everything</a></li>
<li><a href="#use-page-breaks"
             >Using page breaks</a></li>
<li><a href="#error-messages"
             >Error message conventions</a></li>
<li><a href="#other-conventions"
             >Other conventions</a></li>
<li><a href="#apr-pools"
             >APR pool usage conventions</a></li>
<li><a href="#apr-status-codes"
             >APR status codes</a></li>
<li><a href="#exception-handling"
             >Exception handling</a></li>
<li><a href="#automated-tests"
             >Automated tests</a></li>
<li><a href="#write-test-cases-first"
             >Writing test cases before code</a></li>
<li><a href="#server-debugging"
             >Debugging the server</a></li>
<li><a href="#tracing-memory-leaks"
             >Tracking down memory leaks</a></li>
<li><a href="#log-messages"
             >Writing log messages</a></li>
<li><a href="#crediting"
             >Crediting</a></li>
<li><a href="#patches"
             >Patch submission guidelines</a></li>
<li><a href="#filing-issues"
             >Filing bugs / issues</a></li>
<li><a href="#commit-access"
             >Commit access</a></li>
<li><a href="#configury"
             >The configuration/build system under unix</a></li>
<li><a href="#releasing"
             >How to release a distribution tarball</a></li>
<li><a href="#release-numbering"
             >Release numbering, compatibility, and deprecation</a></li>
<li><a href="#release-stabilization"
             >Stabilizing and maintaining releases</a></li>
<li><a href="#tarball-signing"
             >Signing source distribution packages</a></li>
<li><a href="#l10n"
             >Localization (l10n)</a></li>
</ul>

</div>

<![CDATA[=========================================================]]>

<div class="h2" id="participating" title="participating">
<h2>Participating in the community</h2>

<p>Although Subversion is originally sponsored and hosted by CollabNet
(<a href="http://www.collab.net">http://www.collab.net</a>), it's a
true open-source project under a BSD-style license.  A number of
developers work for CollabNet, some work for other large companies
(such as RedHat), and many others are simply excellent volunteers who
are interested in building a better version control system.</p>

<p>The community exists mainly through mailing lists and a Subversion
repository.  To participate:</p>

<p>Go to <a href="http://subversion.tigris.org/"
>http://subversion.tigris.org/</a> and</p>

<ul>
<li><p>Join the "dev", "svn", and "announce" mailing lists.
       The dev list, dev@subversion.tigris.org, is where almost all
       discussion takes place.  All development questions should go
       there, though you might want to check the list archives first.
       The "svn" list receives automated commit emails.</p></li>

<li><p>Get a copy of the latest development sources from
       <a href="http://svn.collab.net/repos/svn/trunk/"
               >http://svn.collab.net/repos/svn/trunk/</a>.
       <br />
       New development always takes place on trunk.  Bugfixes,
       enhancements, and new features are backported from there to the
       various release branches.</p></li> 
</ul>

<p>There are many ways to join the project, either by writing code, or
by testing and/or helping to manage the bug database.  If you'd like
to contribute, then look at:</p>

<ul>
<li><p>The bugs/issues database
       <a href="http://subversion.tigris.org/project_issues.html"
               >http://subversion.tigris.org/project_issues.html</a></p></li>

<li><p>The bite-sized tasks page
       <a href="http://subversion.tigris.org/project_tasks.html"
               >http://subversion.tigris.org/project_tasks.html</a></p></li>
</ul>

<p>To submit code, simply send your patches to
dev@subversion.tigris.org.  No, wait, first read the rest of this
file, <i>then</i> start sending patches to
dev@subversion.tigris.org. :-)</p>

<p>To help manage the issues database, read over the issue summaries,
looking and testing for issues that are either invalid, or are
duplicates of other issues.  Both kinds are very common, the first
because bugs often get unknowingly fixed as side effects of other
changes in the code, and the second because people sometimes file an
issue without noticing that it has already been reported.  If you are
not sure about an issue, post a question to dev@subversion.tigris.org.
("Subversion: We're here to help you help us!")</p>

<p>Another way to help is to set up automated builds and test suite
runs of Subversion on some platform, and have the output sent to the
svn-breakage@subversion.tigris.org mailing list.  See fooo more details at
<a href="http://subversion.tigris.org/servlets/ProjectMailingListList"
        >http://subversion.tigris.org/servlets/ProjectMailingListList</a>
in the description for the svn-breakage list.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="docs" title="docs">
<h2>Theory and documentation</h2>

<ol>
<li><p>Design</p>

     <p>A design spec was written in June 2000, and is a bit out of
     date.  But it still gives a good theoretical introduction to the
     inner workings of the repository, and to Subversion's various
     layers.  The DocBook XML source is in
     <a href="http://svn.collab.net/repos/svn/trunk/doc/design/"
     >doc/design/</a> in the Subversion repository trunk,
     or look at one of the generated versions posted on the Subversion
     website in the <a
 href="http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=259"
     >Documentation Folder</a>.</p>
</li>

<li><p>API documentation</p>
     <p>The <a href="http://svn.collab.net/svn-doxygen/">API documentation</a>
     is generated by doxygen from the C header files and gives detailed
     information about all functions, types and so on available in the
     Subversion API. </p>
</li>

<li> <p>Network Protocols</p>

     <p>The <a href="webdav-usage.html">WebDAV Usage</a> document is
     an introduction to Subversion's ra_dav network protocol, which is
     an extended dialect of HTTP and uses URLs beginning with
     "http://" or "https://".</p>

     <p>The <a
href="http://svn.collab.net/repos/svn/trunk/subversion/libsvn_ra_svn/protocol"
     >SVN Protocol</a> document contains a formal description of
     Subversion ra_svn network protocol, which is a custom protocol
     on port 3690 (by default), whose URLs begin with "svn://" or
     "svn+ssh://".</p>
</li>

<li><p>User Manual</p>

     <p>Version Control with Subversion is a book published by
     O'Reilly that shows in detail how to effectively use Subversion.
     The text of the book is free, and is actively being revised.
     On-line versions are available
     at <a href="http://svnbook.red-bean.com"
     >http://svnbook.red-bean.com</a>.  The XML source and
     translations to other languages are maintained in their own
     repository at <a href="http://svn.red-bean.com/svnbook"
     >http://svn.red-bean.com/svnbook</a>.</p>
</li>

<li><p>System notes</p>

     <p>A lot of the design ideas for particular aspects of the system
     have been documented in individual files in the 
     <a href="http://svn.collab.net/repos/svn/trunk/notes/">notes/</a>
     directory.</p>
</li>

</ol>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="code-to-read" title="code-to-read">
<h2>Code to read</h2>

<p>Before you can contribute code, you'll need to familiarize yourself
with the existing code base and interfaces.</p>

<p>Check out a copy of Subversion (anonymously, if you don't yet have
an account with commit access)&nbsp;&mdash;&nbsp;so you can look at
the code.</p>

<p>Within 'subversion/include/' are a bunch of header files with huge
doc comments.  If you read through these, you'll have a pretty good
understanding of the implementation details.  Here's a suggested
perusal order:</p>

<ol>
<li><p>the basic building blocks:  svn_string.h, svn_error.h, svn_types.h</p>
</li>
<li><p>useful utilities:  svn_io.h, svn_path.h, svn_hash.h, svn_xml.h</p>
</li>
<li><p>the critical interface:  svn_delta.h</p>
</li>
<li><p>client-side interfaces:  svn_ra.h, svn_wc.h, svn_client.h</p>
</li>
<li><p>the repository and versioned filesystem:  svn_repos.h, svn_fs.h</p>
</li>
</ol>

<p>Subversion tries to stay portable by using only ANSI/ISO C and by
using the Apache Portable Runtime (APR) library.  APR is the
portability layer used by the Apache httpd server, and more
information can be found at <a href="http://apr.apache.org/"
>http://apr.apache.org/</a>.</p>

<p>Because Subversion depends so heavily on APR, it may be hard to
understand Subversion without first glancing over certain header files
in APR (look in 'apr/include/'):</p>

<ul>
<li><p>memory pools:  apr_pools.h</p></li>
<li><p>filesystem access:  apr_file_io.h</p></li>
<li><p>hashes and arrays:  apr_hash.h, apr_tables.h</p></li>
</ul>

<p>Subversion also tries to deliver reliable and secure software. This
can only be achieved by developers who understand secure programming
in the C programming language. Please see 'notes/assurance.txt' for
the full rationale behind this.  Specifically, you should make it a
point to carefully read David Wheeler's Secure Programming (as
mentioned in 'notes/assurance.txt'). If at any point you have
questions about the security implications of a change, you are urged
to ask for review on the developer mailing list.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="directory-layout" title="directory-layout">
<h2>Directory layout</h2>

<p>A rough guide to the source tree:</p>

<ul>
<li><p><tt>doc/</tt><br />
    User and Developer documentation.</p>
</li>
<li><p><tt>www/</tt><br />
    Subversion web pages (live content at
      <a href="http://subversion.tigris.org/"
      >http://subversion.tigris.org/</a>).</p>
</li>
<li><p><tt>tools/</tt><br />
    Stuff that works with Subversion, but that Subversion doesn't
    depend on.  Code in tools/ is maintained collectively by the
    Subversion project, and is under the same open source copyright as
    Subversion itself.</p>
</li>
<li><p><tt>contrib/</tt><br />
    Stuff that works with Subversion, but that Subversion doesn't
    depend on, and that is maintained by individuals who may or may
    not participate in Subversion development.  Code in contrib/ is
    open source, but may have a different license or copyright holder
    than Subversion itself.</p>
</li>
<li><p><tt>packages/</tt><br />
    Stuff to help packaging systems, like rpm and dpkg.</p>
</li>
<li><p><tt>subversion/</tt><br />
    Source code to subversion itself (as opposed to external
    libraries).</p>
</li>
<li><p><tt>subversion/include/</tt><br />
    Public header files for users of subversion libraries.</p>
</li>
<li><p><tt>subversion/libsvn_fs/</tt><br />
    The versioning "filesystem" API.</p>
</li>
<li><p><tt>subversion/libsvn_repos/</tt><br />
    Repository functionality built around the `libsvn_fs' core.</p>
</li>
<li><p><tt>subversion/libsvn_delta/</tt><br />
    Common code for tree deltas, text deltas, and property deltas.</p>
</li>
<li><p><tt>subversion/libsvn_wc/</tt><br />
    Common code for working copies.</p>
</li>
<li><p><tt>subversion/libsvn_ra/</tt><br />
    Common code for repository access.</p>
</li>
<li><p><tt>subversion/libsvn_client/</tt><br />
    Common code for client operations.</p>
</li>
<li><p><tt>subversion/svn/</tt><br />
    The command line client.</p>
</li>
<li><p><tt>subversion/tests/</tt><br />
    Automated test suite.</p>
</li>
<li><p><tt>apr/</tt><br />
    Apache Portable Runtime library.  (Note: This is not in the same
    repository as Subversion.  Read INSTALL for instructions on how to
    get it if you don't already have it.)</p>
</li>
<li><p><tt>neon/</tt><br />
    Neon library from Joe Orton.  (Note: This is not in the same
    repository as Subversion.  Read INSTALL for instructions on how to
    get it if you don't already have it.)</p>
</li>
</ul>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="coding-style" title="coding-style">
<h2>Coding style</h2>

<p>Subversion uses ANSI C, and follows the GNU coding standards,
except that we do not put a space between the name of a function and
the opening parenthesis of its parameter list.  Emacs users can just
load svn-dev.el to get the right indentation behavior (most source
files here will load it automatically, if `enable-local-eval' is set
appropriately).</p>

<p>Read <a href="http://www.gnu.org/prep/standards.html"
>http://www.gnu.org/prep/standards.html</a> for a full description of
the GNU coding standards.  Below is a short example demonstrating the
most important formatting guidelines, including our
no-space-before-param-list-paren exception:</p>

<pre>
   char *                                     /* func type on own line */
   argblarg(char *arg1, int arg2)             /* func name on own line */
   {                                          /* first brace on own line */
     if ((some_very_long_condition &amp;&amp; arg2)   /* indent 2 cols */
         || remaining_condition)              /* new line before operator */
       {                                      /* brace on own line, indent 2 */
         arg1 = some_func(arg1, arg2);        /* NO SPACE BEFORE PAREN */
       }                                      /* close brace on own line */
     else
       {
         do                                   /* format do-while like this */
           {
             arg1 = another_func(arg1);
           }
         while (*arg1);
       }
   }
</pre>

<p>In general, be generous with parentheses even when you're sure
about the operator precedence, and be willing to add spaces and
newlines to avoid "code crunch".  Don't worry too much about vertical
density; it's more important to make code readable than to fit that
extra line on the screen.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="secure-coding" title="secure-coding">
<h2>Secure coding guidelines</h2>

<p>Just like almost any other programming language, C has undesirable
features which enables an attacker to make your program fail in
predictable ways, often to the attacker's benefit. The goal of these
guidelines is to make you aware of the pitfalls of C as they apply to
the Subversion project.  You are encouraged to keep these pitfalls in
mind when reviewing code of your peers, as even the most skilled and
paranoid programmers make occasional mistakes.</p>

<p>Input validation is the act of defining legal input and rejecting
everything else. The code must perform input validation on all
untrusted input. </p>

<p>Security boundaries:</p>

<p>A security boundary in the Subversion server code must be
identified as such as this enables auditors to quickly determine the
quality of the boundary.  Security boundaries exist where the running
code has access to information the user does not or where the code
runs with privileges above those of the user making the
request. Typical examples of such is code that does access control or
an application with the SUID bit set.</p>

<p>Functions which make calls to a security boundary must include
validation checks of the arguments passed. Functions which themselves
are security boundaries should audit the input received and alarm when
invoked with improper values. </p>

<p>[### todo: need some examples from Subversion here...]</p>

<p>String operations:</p>

<p>Use the string functions provided in apr_strings.h instead of
standard C library functions that write to strings.  The APR functions
are safer because they do bounds-checking and dest allocation
automatically.  Although there may be circumstances where it's
theoretically safe to use plain C string functions (such as when you
already know the lengths of the source and dest), please use the APR
functions anyway, so the code is less brittle and more reviewable.</p>

<p>Password storage:</p>

<p>Help users keep their passwords secret: When the client reads or
writes password locally, it should ensure that the file is mode
0600. If the file is readable by other users, the client should exit
with a message that tells the user to change the filemode due to the
risk of exposure.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="destruction-of-stacked-resources"
     title="destruction-of-stacked-resources">
<h2>Destruction of stacked resources</h2>

<p>Some resources need destruction to ensure correct functioning of the
application.  Such resources include files, especially since open
files cannot be deleted on Windows.</p>

<p>When writing an API which creates and returns a stream, in the
background this stream may be stacked on a file or other stream.  To
ensure correct destruction of the resources the stream is built upon,
it must correctly call the destructors of the stream(s) it is built
upon (owns).</p>

<p>At first in <a href="http://svn.haxx.se/dev/archive-2005-12/0487.shtml">
http://svn.haxx.se/dev/archive-2005-12/0487.shtml</a>
and later in <a href="http://svn.haxx.se/dev/archive-2005-12/0633.shtml">
http://svn.haxx.se/dev/archive-2005-12/0633.shtml</a> this
was discussed in more general terms for files, streams, editors and
window handlers.</p>

<p>As Greg Hudson put it:</p>

<blockquote>
<p>On consideration, here is where I would like us to be:</p>

<ul><li>Streams which read from or write to an underlying object own that
object, i.e. closing the stream closes the underlying object, if
applicable.</li>

<li>The layer (function or data type) which created a stream is
responsible for closing it, except when the above rule applies.</li>

<li>Window handlers are thought of as an odd kind of stream, and passing
the final NULL window is considered closing the stream.</li>
</ul>

<p>If you think of apply_textdelta as creating a window handler, then I
don't think we're too far off.  svn_stream_from_aprfile isn't owning its
subsidiary file, svn_txdelta_apply is erroneously taking responsibility
for closing the window stream it is passed, and there may be some other
deviations.</p>
</blockquote>

<p>There is one exception to the rules above though.  When a stream is passed
to a function as an argument (for example: the 'out' parameter of
svn_client_cat2()), that routine can't call the streams destructor, since
it did not create that resource.</p>

<p>If svn_client_cat2() creates a stream, it must also call the destructor
for that stream.  By the above model, that stream will call the destructor
for the 'out' parameter.  This is however wrong, because the responsibility
to destruct the 'out' parameter lies elsewhere.</p>

<p>To solve this problem, at least in the stream case, svn_stream_disown()
has been introduced.  This function wraps a stream, making sure it's
<em>not</em> destroyed, even though any streams stacked upon it may try
to do so.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="documenting" title="documenting">
<h2>Document everything</h2>

<p>Every function, whether public or internal, must start out with a
documentation comment that describes what the function does.  The
documentation should mention every parameter received by the function,
every possible return value, and (if not obvious) the conditions under
which the function could return an error.  Put the parameter names in
upper case in the doc string, even when they are not upper case in the
actual declaration, so that they stand out to human readers.</p>

<p>For public or semi-public API functions, the doc string should go
above the function in the .h file where it is declared; otherwise, it
goes above the function definition in the .c file.</p>

<p>For structure types, document each individual member of the
structure as well as the structure itself.</p>

<p>Use the doxygen (www.doxygen.org) format for interface
documentation.  There is still some legacy documentation in Subversion
that uses a different style, from before we adopted doxygen, but it
will eventually be converted.  New documentation should start out in
doxygen format.</p>

<p>Read over the Subversion code to get an overview of how
documentation looks in practice; in particular, see
subversion/include/*.h for doxygen examples.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="use-page-breaks" title="use-page-breaks">
<h2>Using page breaks</h2>

<p>We're using page breaks (the Ctrl-L character, ASCII 12) for
section boundaries in both code and plaintext prose files.  Each
section starts with a page break, and immediately after the page break
comes the title of the section.</p>

<p>This helps out people who use the Emacs page commands, such as
`pages-directory' and `narrow-to-page'.  Such people are not as scarce
as you might think, and if you'd like to become one of them, then add
(require 'page-ext) to your .emacs and type C-x C-p C-h sometime.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="error-messages" title="error-messages">
<h2>Error message conventions</h2>

<p>For error messages the following conventions apply:</p>

<ul>

<li><p>Provide specific error messages only when there is information 
     to add to the general error message found in 
     subversion/include/svn_error_codes.h.</p></li>

<li><p>Messages start with a capital letter.</p></li>

<li><p>Try keeping messages below 70 characters.</p></li>

<li><p>Don't end the error message with a period (".").</p></li>

<li><p>Don't include newline characters in error messages.</p></li>

<li><p>Quoting information is done using single quotes (e.g. "'some info'").</p></li>

<li><p>Don't include the name of the function where the error occurs
     in the error message. If subversion is compiled using the
     '--enable-maintainer-mode' configure-flag, it will provide this
     information by itself.</p></li>

<li><p>When including path or filenames in the error string, be sure
     to quote them (e.g. "Can't find '/path/to/repos/userfile'").</p></li>

<li><p>When including path or filenames in the error string, be sure
     to convert them using 'svn_path_local_style()' before inclusion.</p></li>

<li><p>If you want to add an explanation to the error, report it
     followed by a colon and the explanation like this:</p>
     <pre>
       "Invalid " SVN_PROP_EXTERNALS " property on '%s': "
       "target involves '.' or '..'".
     </pre></li>

<li><p>Suggestions or other additions can be added after a semi-colon, 
     like this:</p>
     <pre>
       "Can't write to '%s': object of same name already exists; remove "
       "before retrying".
     </pre></li>

<li><p>Try to stay within the boundaries of these conventions, so please avoid
     separating different parts of error messages by other separators such 
     as '--' and others.</p></li>

</ul>

<p>Also read about <a href="#l10n">Localization</a>.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="other-conventions" title="other-conventions">
<h2>Other conventions</h2>

<p>In addition to the GNU standards, Subversion uses these
conventions:</p>

<ul>
<li><p>Use only spaces for indenting code, never tabs.  Tab display
      width is not standardized enough, and anyway it's easier to
      manually adjust indentation that uses spaces.</p>
</li>

<li><p>Restrict lines to 79 columns, so that code will display well in a
      minimal standard display window.  (There can be exceptions, such
      as when declaring a block of 80-column text with a few extra
      columns taken up by indentation, quotes, etc., if splitting each
      line in two would be unreasonably messy.)</p>
</li>

<li><p>All published functions, variables, and structures must be signified
      with the corresponding library name - such as libsvn_wc's
      svn_wc_adm_open.  All library-internal declarations made in a
      library-private header file (such as libsvn_wc/wc.h) must be signified
      by two underscores after the library prefix (such as
      svn_wc__ensure_directory).  All declarations private to a single file
      (such as the static function get_entry_url inside
      libsvn_wc/update_editor.c) do not require any additional namespace
      decorations.  Symbols that need to be used outside a library, but
      still are not public are put in a public header, but use the
      double underscore notation.  Such symbols may be used by
      Subversion core code only, and we try to be restrictive
      regarding the introduction of such entities.</p>
      
      <p>To recap:</p>
      <pre>
         /* Part of published API: subversion/include/svn_wc.h */
         svn_wc_adm_open()            
         #define SVN_WC_ADM_DIR_NAME ...
         typedef enum svn_wc_schedule_t ...
         /* For use within one library only: subversion/libsvn_wc/wc.h */
         svn_wc__ensure_directory()   
         #define SVN_WC__BASE_EXT ... 
         typedef struct svn_wc__compat_notify_baton_t ...
         /* For use within one file: subversion/libsvn_wc/update_editor.c */ 
         get_entry_url()
         struct handler_baton {
         /* For internal use in svn core code only:
            subversion/include/svn_types.h */
         #define SVN__STREAM_CHUNK_SIZE
         /* subversion/include/svn_error.h */
         void svn_error__locate(const char *file, long line);
      </pre>
</li>

<li><p>In text strings that might be printed out (or otherwise made
      available) to users, use only forward quotes around paths and
      other quotable things.  For example:</p>
      <pre>
         $ svn revert foo
         svn: warning: svn_wc_is_wc_root: 'foo' is not a versioned resource
         $
      </pre>

      <p>There used to be a lot of strings that used a backtick for
      the first quote (`foo' instead of 'foo'), but that looked bad in
      some fonts, and also messed up some people's auto-highlighting,
      so we settled on the convention of always using forward
      quotes.</p>
</li>

<li><p>If you use Emacs, put something like this in your .emacs file,
      so you get svn-dev.el and svnbook.el when needed:</p>
      <pre>
         ;;; Begin Subversion development section
         (defun my-find-file-hook ()
           (let ((svn-tree-path (expand-file-name "~/projects/subversion"))
                 (book-tree-path (expand-file-name "~/projects/svnbook")))
             (cond
              ((string-match svn-tree-path buffer-file-name)
               (load (concat svn-tree-path "/tools/dev/svn-dev")))
              ((string-match book-tree-path buffer-file-name)
               ;; Handle load exception for svnbook.el, because it tries to
               ;; load psgml, and not everyone has that available.
               (condition-case nil
                   (load (concat book-tree-path "/src/tools/svnbook"))
                 (error
                  (message "(Ignored problem loading svnbook.el.)")))))))

         (add-hook 'find-file-hooks 'my-find-file-hook)
         ;;; End Subversion development section
      </pre>

      <p>You'll need to customize the path for your setup, of course.
      You can also make the regexp to string-match more selective; for
      example, one developer says:</p>
      <pre>
      &gt; Here's the regexp I'm using:
      &gt; 
      &gt;     "src/svn/[^/]*/\\(subversion\\|tools\\|build\\)/"
      &gt;
      &gt; Two things to notice there: (1) I sometimes have several
      &gt; working copies checked out under ...src/svn, and I want the
      &gt; regexp to match all of them; (2) I want the hook to catch only
      &gt; in "our" directories within the working copy, so I match
      &gt; "subversion", "tools" and "build" explicitly; I don't want to
      &gt; use GNU style in the APR that's checked out into my repo. :-)
      </pre>
</li>

<li><p>We have a tradition of not marking files with the names of
      individual authors (i.e., we don't put lines like
      "Author:&nbsp;foo" or "@author&nbsp;foo" in a special position
      at the top of a source file).  This is to discourage
      territoriality&nbsp;&mdash;&nbsp;even when a file has only one
      author, we want to make sure others feel free to make changes.
      People might be unnecessarily hesitant if someone appears to
      have staked a personal claim to the file.</p>
</li>

<li><p>Put two spaces between the end of one sentence and the start of
      the next.  This helps readability, and allows people to use
      their editors' sentence-motion and -manipulation commands.</p>
</li>

<li><p>There are many other unspoken conventions maintained throughout
      the code, that are only noticed when someone unintentionally
      fails to follow them.  Just try to have a sensitive eye for the
      way things are done, and when in doubt, ask.</p>
</li>
</ul>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="apr-pools" title="apr-pools">
<h2>APR pool usage conventions</h2>

<p>(This assumes you already basically understand how APR pools work;
see apr_pools.h for details.)</p>

<p>Applications using the Subversion libraries must call
apr_initialize() before calling any Subversion functions.</p>

<p>Subversion's general pool usage strategy can be summed up in two
principles:</p>

<ol>
<li><p>The call level that created a pool is the only place to clear or
       destroy that pool.</p>
</li>
<li><p>When iterating an unbounded number of times, create a subpool
       before entering the iteration, use it inside the loop and clear 
       it at the start of each iteration, then destroy it after the loop 
       is done, like so:</p>
       <pre>
         apr_pool_t *subpool = svn_pool_create(pool);

         for (i = 0; i &lt; n; ++i)
         {
           svn_pool_clear(subpool);
           do_operation(..., subpool);
         }

         svn_pool_destroy(subpool);
       </pre>
</li>
</ol>

<p>By using a loop subpool for loop-bounded data, you ensure O(1) instead
of O(N) memory leakage should the function return abruptly from
within the loop (say, due to error).  That's why you shouldn't make a
subpool for data which persists throughout a function, but instead
should use the pool passed in by the caller.  That memory will be
reclaimed when the caller's pool is cleared or destroyed.  If the
caller is invoking the callee in a loop, then trust the caller to take
care of clearing the pool on each iteration.  The same logic
propagates all the way up the call stack.</p>

<p>The pool you use also helps readers of the code understand object
lifetimes.  Is a given object used only during one iteration of the
loop, or will it need to last beyond the end of the loop?  For
example, pool choices indicate a lot about what's going on in this
code:</p>

<pre>
      apr_hash_t *persistent_objects = apr_hash_make(pool);
      apr_pool_t *subpool = svn_pool_create(pool);

      for (i = 0; i &lt; n; ++i)
      {
        const char *intermediate_result;
        const char *key, *val;
        
        svn_pool_clear(subpool);
        SVN_ERR(do_something(&amp;intermediate_result, ..., subpool));
        SVN_ERR(get_result(intermediate_result, &amp;key, &amp;val, ..., pool));
        apr_hash_set(persistent_objects, key, APR_HASH_KEY_STRING, val);
      }
      svn_pool_destroy(subpool);

      return persistent_objects;
</pre>

<p>Except for some legacy code, which was written before these
principles were fully understood, virtually all pool usage in
Subversion follows the above guidelines.</p>

<p>One such legacy pattern is a tendency to allocate an object inside
a pool, store the pool in the object, and then free that pool (either
directly or through a close_foo() function) to destroy the object.</p>

<p>For example:</p>

<pre>
   <span style="color: red;">/*** Example of how NOT to use pools.  Don't be like this. ***/</span>

   static foo_t *
   make_foo_object(arg1, arg2, apr_pool_t *pool)
   {
      apr_pool_t *subpool = svn_pool_create(pool);
      foo_t *foo = apr_palloc(subpool, sizeof(*foo));

      foo-&gt;field1 = arg1;
      foo-&gt;field2 = arg2;
      foo-&gt;pool   = subpool;
   }

   [...]

   [Now some function calls make_foo_object() and returns, passing
   back a new foo object.]

   [...]

   [Now someone, at some random call level, decides that the foo's
   lifetime is over, and calls svn_pool_destroy(foo-&gt;pool).]
</pre>

<p>This is tempting, but it defeats the point of using pools, which is
to not worry so much about individual allocations, but rather about
overall performance and lifetime groups.  Instead, foo_t generally
should not have a `pool' field.  Just allocate as many foo objects as
you need in the current pool&nbsp;&mdash;&nbsp;when that pool gets
cleared or destroyed, they will all go away simultaneously.</p>

<p>See also the <a href="#exception-handling">Exception handling</a>
section, for details of how resources associated with a pool are
cleaned up when that pool is destroyed.</p>

<p>In summary:</p>

<ul>

<li><p>Objects should not have their own pools.  An object is
       allocated into a pool defined by the constructor's caller.  The
       caller knows the lifetime of the object and will manage it via
       the pool.</p>
</li>

<li><p>Functions should not create/destroy pools for their operation;
       they should use a pool provided by the caller.  Again, the
       caller knows more about how the function will be used, how
       often, how many times, etc. thus, it should be in charge of the
       function's memory usage.</p>

    <p>For example, the caller might know that the app will exit upon
       the function's return. Thus, the function would create extra
       work if it built/destroyed a pool. Instead, it should use the
       passed-in pool, which the caller is going to be tossing as part
       of app-exit anyway.</p>
</li>

<li><p>Whenever an unbounded iteration occurs, an iteration subpool
       should be used.</p>
</li>

<li><p>Given all of the above, it is pretty well mandatory to pass a
       pool to every function.  Since objects are not recording pools
       for themselves, and the caller is always supposed to be
       managing memory, then each function needs a pool, rather than
       relying on some hidden magic pool.  In limited cases, objects
       may record the pool used for their construction so that they
       can construct sub-parts, but these cases should be examined
       carefully.</p>
</li>
</ul>


<p>See also <a href="#tracing-memory-leaks">Tracking down memory
leaks</a> for tips on diagnosing pool usage problems.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="apr-status-codes" title="apr-status-codes">
<h2>APR status codes</h2>

<p>Always check for APR status codes (except APR_SUCCESS) with the
APR_STATUS_IS_...() macros, not by direct comparison. This is required
for portability to non-Unix platforms.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="exception-handling" title="exception-handling">
<h2>Exception handling</h2>

<p>OK, here's how to use exceptions in Subversion.</p>

<ol>

<li><p>Exceptions are stored in svn_error_t structures:</p>

<pre>
typedef struct svn_error
{
  apr_status_t apr_err;      /* APR error value, possibly SVN_ custom err */
  const char *message;       /* details from producer of error */
  struct svn_error *child;   /* ptr to the error we "wrap" */
  ap_pool_t *pool;           /* place to generate message strings from */
  const char *file;          /* Only used iff SVN_DEBUG */
  long line;                 /* Only used iff SVN_DEBUG */
} svn_error_t;
</pre>

</li>

<li><p>If you are the *original* creator of an error, you would do
       something like this:</p>

    <pre>
return svn_error_create(SVN_ERR_FOO, NULL, 
                        "User not permitted to write file");
    </pre>

    <p>NOTICE the NULL field... indicating that this error has no
    child, i.e. it is the bottom-most error.</p>

    <p>See also the <a href="#error-messages"> section on writing
    error messages</a>.</p>

    <p>Subversion internally uses UTF-8 to store its data. This also
    applies to the 'message' string. APR is assumed to return its data
    in the current locale, so any text returned by APR needs
    conversion to UTF-8 before inclusion in the message string.</p>
</li>

<li><p>If you *receive* an error, you have three choices:</p>

    <ol>
    <li><p>Handle the error yourself.  Use either your own code, or
           just call the primitive svn_handle_error(err).  (This
           routine unwinds the error stack and prints out messages
           converting them from UTF-8 to the current locale.)</p>

        <p>When your routine receives an error which it intends to
           ignore or handle itself, be sure to clean it up using
           svn_error_clear(). Any time such an error is not cleared
           constitutes a *memory leak*.</p>
    </li>

    <li><p>Throw the error upwards, unmodified:</p>

        <pre>
        error = some_routine(foo);
        if (error)
          return (error);
        </pre>

        <p>Actually, a better way to do this would be with the
        SVN_ERR() macro, which does the same thing:</p>
        <pre>
        SVN_ERR(some_routine(foo));
        </pre>
     </li>

    <li><p>Throw the error upwards, wrapping it in a new error
           structure by including it as the "child" argument:</p>

        <pre>
        error = some_routine(foo);
        if (error)
          {
           svn_error_t *wrapper = svn_error_create(SVN_ERR_FOO, error,
                                                   "Authorization failed");
           return wrapper;
          }
        </pre>

        <p>Of course, there's a convenience routine which creates a
           wrapper error with the same fields as the child, except for
           your custom message:</p>

        <pre>
        error = some_routine(foo);
        if (error)
          {
           return svn_error_quick_wrap(error, 
                                       "Authorization failed");
          }
        </pre>

        <p>The same can (and should) be done by using the SVN_ERR_W()
           macro:</p>

        <pre>
          SVN_ERR_W(some_routine(foo), "Authorization failed");
        </pre>
    </li>
    </ol>

    <p>In cases (b) and (c) it is important to know that resources
    allocated by your routine which are associated with a pool, are
    automatically cleaned up when the pool is destroyed. This means
    that there is no need to cleanup these resources before passing
    the error. There is therefore no reason not to use the SVN_ERR()
    and SVN_ERR_W() macros.  Resources associated with pools are:</p>

    <ul>

    <li><p>Memory</p></li>

    <li><p>Files</p>

        <p>All files opened with apr_file_open are closed at pool
        cleanup.  Subversion uses this function in its svn_io_file_*
        api, which means that files opened with svn_io_file_* or
        apr_file_open will be closed at pool cleanup.</p>

        <p>Some files (lock files for example) need to be removed when
        an operation is finished. APR has the APR_DELONCLOSE flag for
        this purpose.  The following functions create files which are
        removed on pool cleanup:</p>

        <ul>
        <li><p>apr_file_open and svn_io_file_open (when passed the 
               APR_DELONCLOSE flag)</p></li>
        <li><p>svn_io_open_unique_file (when passed TRUE in its
               delete_on_close)</p></li>
        </ul>
   
        <p>Locked files are unlocked if they were locked using
        svn_io_file_lock.</p>
    </li>
    </ul>

</li>
</ol>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="automated-tests" title="automated-tests">
<h2>Automated tests</h2>

<p>For a description of how to use and add tests to Subversion's
automated test framework, please read <a
href="http://svn.collab.net/repos/svn/trunk/subversion/tests/README"
>subversion/tests/README</a> and <a
href="http://svn.collab.net/repos/svn/trunk/subversion/tests/cmdline/README"
>subversion/tests/cmdline/README</a>.</p>

<p>Various people have arranged for the automated test framework to
run at regular intervals on their own machines, sending the results to
the svn-breakage@subversion.tigris.org mailing list.  The more
different platforms the tests run on, the more quickly we can detect
portability bugs in Subversion.  If you'd like to send svn-breakage
messages too, use the <a
href="http://svn.collab.net/repos/svn/trunk/tools/test-scripts/svntest/" 
>svntest</a> framework (start at the <a
href="http://svn.collab.net/repos/svn/trunk/tools/test-scripts/svntest/README" 
>README</a>).</p>

<p>Lieven Govaerts has set up a
<a href="http://buildbot.sourceforge.net/" >BuildBot</a> build/test
farm at <a href="http://www.mobsol.be/buildbot/"
>http://www.mobsol.be/buildbot/</a>, see his message</p>

<pre>
   <a href="http://subversion.tigris.org/servlets/ReadMsg?list=dev&amp;msgNo=114212">http://subversion.tigris.org/servlets/ReadMsg?list=dev&amp;msgNo=114212</a>
   (Thread URL: <a href="http://subversion.tigris.org/servlets/BrowseList?list=dev&amp;by=thread&amp;from=450110">http://subversion.tigris.org/servlets/BrowseList?list=dev&amp;by=thread&amp;from=450110</a>)
   Message-ID: 20060326205918.F3C50708B0@adicia.telenet-ops.be
   From: "Lieven Govaerts" &lt;lgo@mobsol.be&gt;
   To: &lt;dev@subversion.tigris.org&gt;
   Subject: Update: Subversion build and test farm with Buildbot.
   Date: Sun, 26 Mar 2006 22:56:11 +0200
</pre>

<p>for more details.  (<a href="http://buildbot.sourceforge.net/"
>BuildBot</a> is a system for centrally managing multiple automated
testing environments; it's especially useful for portability testing,
including of uncommitted changes.)</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="write-test-cases-first" title="write-test-cases-first">
<h2>Writing test cases before code</h2>

<pre>
From: Karl Fogel &lt;kfogel@collab.net&gt;
Subject: writing test cases
To: dev@subversion.tigris.org
Date: Mon, 5 Mar 2001 15:58:46 -0600

Many of us implementing the filesystem interface have now gotten into
the habit of writing the test cases (see fs-test.c) *before* writing
the actual code.  It's really helping us out a lot -- for one thing,
it forces one to define the task precisely in advance, and also it
speedily reveals the bugs in one's first try (and second, and
third...).

I'd like to recommend this practice to everyone.  If you're
implementing an interface, or adding an entirely new feature, or even
just fixing a bug, a test for it is a good idea.  And if you're going
to write the test anyway, you might as well write it first. :-)

Yoshiki Hayashi's been sending test cases with all his patches lately,
which is what inspired me to write this mail to encourage everyone to
do the same.  Having those test cases makes patches easier to examine,
because they show the patch's purpose very clearly.  It's like having
a second log message, one whose accuracy is verified at run-time.

That said, I don't think we want a rigid policy about this, at least
not yet.  If you encounter a bug somewhere in the code, but you only
have time to write a patch with no test case, that's okay -- having
the patch is still useful; someone else can write the test case.

As Subversion gets more complex, though, the automated test suite gets
more crucial, so let's all get in the habit of using it early.

-K
</pre>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="server-debugging" title="server-debugging">
<h2>Debugging the server</h2>

<div class="h3" id="debugging-ra-dav" title="debugging-ra-dav">
<h3>Debugging the ra_dav server</h3>

<p>'mod_dav_svn.so' contains the main Subversion server logic; it runs
as a module within mod_dav, which runs as a module within httpd.
Since httpd is probably using dynamic shared modules, you normally
won't be able to set breakpoints in advance when you start Apache in a
debugger such as GDB.  Instead, you'll need to start up, then
interrupt httpd, set your breakpoint, and continue:</p>

<pre>
   % gdb httpd
   (gdb) run -X
   ^C
   (gdb) break some_func_in_mod_dav_svn
   (gdb) continue
</pre>

<p>The -X switch is equivalent to -DONE_PROCESS and -DNO_DETACH, which
ensure that httpd runs as a single thread and remains attached to the
tty, respectively.  As soon as it starts, it sits and waits for
requests; that's when you hit control-C and set your breakpoint.</p>

<p>You'll probably want to watch Apache's run-time logs</p>

<pre>
   /usr/local/apache2/logs/error_log
   /usr/local/apache2/logs/access_log
</pre>

<p>to help determine what might be going wrong and where to set
breakpoints.</p>

</div>

<div class="h3" id="debugging-ra-svn" title="debugging-ra-svn">
<h3>Debugging the ra_svn client and server, on Unix</h3>

<p>Bugs in ra_svn usually manifest themselves with one of the
following cryptic error messages:</p>

<pre>
  svn: Malformed network data
  svn: Connection closed unexpectedly
</pre>

<p>(The first message can also mean the data stream was corrupted in
tunnel mode by user dotfiles or hook scripts; see 
<a href="http://subversion.tigris.org/issues/show_bug.cgi?id=1145"
>issue&nbsp;#1145</a>.)  The first message generally means you to have
to debug the client; the second message generally means you have to
debug the server.</p>

<p>It is easiest to debug ra_svn using a build with --disable-shared
--enable-maintainer-mode.  With the latter option, the error message
will tell you exactly what line to set a breakpoint at; otherwise,
look up the line number at the end of marshal.c:vparse_tuple() where
it returns the "Malformed network data" error.</p>

<p>To debug the client, simply pull it up in gdb, set a breakpoint,
and run the offending command:</p>

<pre>
  % gdb svn
  (gdb) break marshal.c:NNN
  (gdb) run ARGS
  Breakpoint 1, vparse_tuple (list=___, pool=___, fmt=___, 
    ap=___) at subversion/libsvn_ra_svn/marshal.c:NNN
  NNN                                 "Malformed network data");
</pre>

<p>There are several bits of useful information:</p>

<ul>
<li><p>A backtrace will tell you exactly what protocol exchange is
    failing.</p>
</li>

<li><p>"print *conn" will show you the connection buffer.  read_buf,
    read_ptr, and read_end represent the read buffer, which can
    show
    you the data the marshaller is looking at.  (Since read_buf isn't
    generally 0-terminated at read_end, be careful of falsely assuming
    that there's garbage data in the buffer.)</p>
</li>

<li><p>The format string determines what the marshaller was expecting to
    see.</p>
</li>
</ul>

<p>To debug the server in daemon mode, pull it up in gdb, set a
breakpoint (usually a "Connection closed unexpectedly" error on the
client indicates a "Malformed network data" error on the server,
although it can also indicate a core dump), and run it with the "-X"
option to serve a single connection:</p>

<pre>
  % gdb svnserve
  (gdb) break marshal.c:NNN
  (gdb) run -X
</pre>

<p>Then run the offending client command.  From there, it's just like
debugging the client.</p>

<p>Debugging the server in tunnel mode is more of a pain.  You'll need
to stick something like "{ int x = 1; while (x); }" near the top of
svnserve's main() and put the resulting svnserve in the user path on
the server.  Then start an operation, gdb attach the process on the
server, "set x = 0", and step through the code as desired.</p>

</div>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="tracing-memory-leaks" title="tracing-memory-leaks">
<h2>Tracking down memory leaks</h2>

<p>Our use of APR pools makes it unusual for us to have memory leaks
in the strictest sense; all the memory we allocate will be cleaned up
eventually.  But sometimes an operation takes more memory than it
should; for instance, a checkout of a large source tree should not use
much more memory than a checkout of a small source tree.  When that
happens, it generally means we're allocating memory from a pool whose
lifetime is too long.</p>

<p>If you have a favorite memory leak tracking tool, you can configure
with --enable-pool-debug (which will make every pool allocation use
its own malloc()), arrange to exit in the middle of the operation, and
go to it.  If not, here's another way:</p>

<ul>

<li><p>Configure with --enable-pool-debug=verbose-alloc.  Make sure to
       rebuild all of APR and Subversion so that every allocation gets
       file-and-line information.</p>
</li>

<li><p>Run the operation, piping stderr to a file.  Hopefully you have
      lots of disk space.</p>
</li>

<li><p>In the file, you'll see lots of lines which look like:</p>

   <pre>
    POOL DEBUG: [5383/1024] PCALLOC (      2763/      2763/      5419) \
    0x08102D48 "subversion/svn/main.c:612"                             \
    &lt;subversion/libsvn_subr/auth.c:122&gt; (118/118/0)
   </pre>

    <p>What you care about most is the tenth field (the one in
       quotes), which gives you the file and line number where the
       pool for this allocation was created.  Go to that file and line
       and determine the lifetime of the pool.  In the example above,
       main.c:612 indicates that this allocation was made in the
       top-level pool of the svn client.  If this were an allocation
       which was repeated many times during the course of an
       operation, that would indicate a source of a memory leak.  The
       eleventh field (the one in brackets) gives the file and line
       number of the allocation itself.</p>
</li>

</ul>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="log-messages" title="log-messages">
<h2>Writing log messages</h2>

<p>Every commit needs a log message.  </p>

<p>The intended audience for a log message is a developer who is
already familiar with Subversion, but not necessarily familiar with
this particular commit.  Usually when someone goes back and reads a
change, he no longer has in his head all the context around that
change.  This is true even if he is the author of the change!  All the
discussions and mailing list threads and everything else may be
forgotten; the only clue to what the change is about comes from the
log message and the diff itself.  People revisit changes with
surprising frequency, too: for example, it might be months after the
original commit and now the change is being ported to a maintenance
branch.</p>

<p>The log message is the introduction to the change.  Start it off
with one line indicating the general nature of the change, and follow
that with a descriptive paragraph if necessary.  This not only helps
put developers in the right frame of mind for reading the rest of the
log message, but also plays well with the "CIA" bot that echoes the
first line of each commit to realtime forums like IRC.  (For details,
see <a href="http://cia.navi.cx/">http://cia.navi.cx/</a>.)  However,
if the commit is just one simple change to one file, then you can
dispense with the general description and simply go straight to the
detailed description, in the standard filename-then-symbol format
shown below.</p>

<p>Throughout the log message, use full sentences, not sentence
fragments.  Fragments are more often ambiguous, and it takes only a
few more seconds to write out what you mean.  Certain fragments like
"Doc fix", "New file", or "New function" are acceptable because they
are standard idioms, and all further details should appear in the
source code.</p>

<p>The log message should name every affected function, variable,
macro, makefile target, grammar rule, etc, including the names of
symbols that are being removed in this commit.  This helps people
searching through the logs later.  Don't hide names in wildcards,
because the globbed portion may be what someone searches for later.
For example, this is bad:</p>

<pre>
   * subversion/libsvn_ra_pigeons/twirl.c
     (twirling_baton_*): Removed these obsolete structures.
     (handle_parser_warning): Pass data directly to callees, instead
     of storing in twirling_baton_*.

   * subversion/libsvn_ra_pigeons/twirl.h: Fix indentation.
</pre>

<p>Later on, when someone is trying to figure out what happened to
`twirling_baton_fast', they may not find it if they just search for
"_fast".  A better entry would be:</p>

<pre>
   * subversion/libsvn_ra_pigeons/twirl.c
     (twirling_baton_fast, twirling_baton_slow): Removed these
     obsolete structures. 
     (handle_parser_warning): Pass data directly to callees, instead
     of storing in twirling_baton_*. 

   * subversion/libsvn_ra_pigeons/twirl.h: Fix indentation.
</pre>

<p>The wildcard is okay in the description for
`handle_parser_warning', but only because the two structures were
mentioned by full name elsewhere in the log entry.</p>

<p>Note how each file gets its own entry prefixed with an "*", and the
changes within a file are grouped by symbol, with the symbols listed
in parentheses followed by a colon, followed by text describing the
change.  Please adhere to this format, even when only one file is
changed&nbsp;&mdash;&nbsp;not only does consistency aid readability,
it also allows software to colorize log entries automatically.</p>

<p>As an exception to the above, if you make exactly the same change
in several files, list all the changed files in one entry. For
example:</p>

<pre>
   * subversion/libsvn_ra_pigeons/twirl.c,
     subversion/libsvn_ra_pigeons/roost.c:
     Include svn_private_config.h.
</pre>

<p>If all the changed files are deep inside the source tree, you can
shorten the file name entries by noting the common prefix before the
change entries:</p>

<pre>
   [in subversion/bindings/swig/birdsong]

   * dialects/nightingale.c (get_base_pitch): Allow 3/4-tone
     pitch variation to account for trait variability amongst
     isolated populations Erithacus megarhynchos.

   * dialects/gallus_domesticus.c: Remove. Unreliable due to
     extremely low brain-to-body mass ratio.
</pre>

<p>If your change is related to a specific issue in the issue tracker,
then include a string like "issue #N" in the log message, but make
sure you still summarize what the change is about.  For example, if a
patch resolves issue #1729, then the log message might be:</p>

<pre>
   Fix issue #1729: Don't crash because of a missing file.

   * subversion/libsvn_ra_ansible/get_editor.c
     (frobnicate_file): Check that file exists before frobnicating.
</pre>

<p>Try to put related changes together.  For example, if you create
svn_ra_get_ansible2(), deprecating svn_ra_get_ansible(), then those
two things should be near each other in the log message:</p>

<pre>
   * subversion/include/svn_ra.h
     (svn_ra_get_ansible2): New prototype, obsoletes svn_ra_get_ansible.
     (svn_ra_get_ansible): Deprecate.
</pre>

<p>For large changes or change groups, group the log entry into
paragraphs separated by blank lines.  Each paragraph should be a set
of changes that accomplishes a single goal, and each group should
start with a sentence or two summarizing the change.  Truly
independent changes should be made in separate commits, of course.</p>

<p>See <a href="#crediting">Crediting</a> for how to give credit to
someone else if you are committing their patch, or committing a change
they suggested.</p>

<p>One should never need the log entries to understand the current
code.  If you find yourself writing a significant explanation in the
log, you should consider carefully whether your text doesn't actually
belong in a comment, alongside the code it explains.  Here's an
example of doing it right:</p>

<pre>
   (consume_count): If `count' is unreasonable, return 0 and don't
   advance input pointer.
</pre>

<p>And then, in `consume_count' in `cplus-dem.c':</p>

<pre>
   while (isdigit((unsigned char)**type))
     {
       count *= 10;
       count += **type - '0';
       /* A sanity check.  Otherwise a symbol like
         `_Utf390_1__1_9223372036854775807__9223372036854775'
         can cause this function to return a negative value.
         In this case we just consume until the end of the string.  */
      if (count &gt; strlen(*type))
        {
          *type = save;
          return 0;
        }
</pre>

<p>This is why a new function, for example, needs only a log entry
saying "New Function" --- all the details should be in the source.</p>

<p>There are some common-sense exceptions to the need to name
everything that was changed:</p>

<ul>

<li><p>If you have made a change which requires trivial changes
       throughout the rest of the program (e.g., renaming a variable),
       you needn't name all the functions affected, you can just say
       "All callers changed".</p>
</li>

<li><p>If you have rewritten a file completely, the reader understands
       that everything in it has changed, so your log entry may simply
       give the file name, and say "Rewritten".</p>
</li>

<li><p>If your change was to multiple files, provide a brief summary
       of the change at the top of the log message (before the paths
       and symbols list).</p>
</li>

</ul>

<p>In general, there is a tension between making entries easy to find
by searching for identifiers, and wasting time or producing unreadable
entries by being exhaustive.  Use your best judgment --- and be
considerate of your fellow developers.  (Also, run "svn log" to see
how others have been writing their log entries.)</p>

<p>Log messages for documentation or translation have somewhat looser
guidelines.  The requirement to name every symbol obviously does not
apply, and if the change is just one more increment in a continuous
process such as translation, it's not even necessary to name every
file.  Just briefly summarize the change, for example: "More work on
Malagasy translation."  Please write your log messages in English, so
everybody involved in the project can understand the changes you
made.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="crediting" title="crediting">
<h2>Crediting</h2>

<p>It is very important to record code contributions in a consistent
and parseable way.  This allows us to write scripts to figure out who
has been actively contributing&nbsp;&mdash;&nbsp;and what they have
contributed&nbsp;&mdash;&nbsp;so we can <a
href="http://www.red-bean.com/svnproject/contribulyzer/">spot
potential new committers quickly</a>.  The Subversion project uses
human-readable but machine-parseable fields in log messages to
accomplish this.</p>

<p>When committing a patch written by someone else, use
"Patch&nbsp;by:&nbsp;" at the beginning of a line to indicate the
author:</p>

<pre>
   Fix issue #1729: Don't crash because of a missing file.

   Patch by: J. Random &lt;jrandom@example.com&gt;

   * subversion/libsvn_ra_ansible/get_editor.c
     (frobnicate_file): Check that file exists before frobnicating.
</pre>

<p>If multiple individuals wrote the patch, list them each on a
separate line&nbsp;&mdash;&nbsp;making sure to start each continuation
line with whitespace.  Non-committers should be listed by name, if
known, and e-mail.  Committers may be listed similarly, or by their
canonical usernames from COMMITTERS (the leftmost column).
Additionally, "me" is an acceptable shorthand for the person actually
committing the change.</p>

<pre>
   Fix issue #1729: Don't crash because of a missing file.

   Patch by: J. Random &lt;jrandom@example.com&gt;
             Enrico Caruso &lt;codingtenor@codingtenor.com&gt;
             jcommitter
             me

   * subversion/libsvn_ra_ansible/get_editor.c
     (frobnicate_file): Check that file exists before frobnicating.
</pre>

<p>If someone found the bug or pointed out the problem, but didn't
write the patch, indicate their contribution with
"Found&nbsp;by:&nbsp;":</p>

<pre>
   Fix issue #1729: Don't crash because of a missing file.

   Found by: J. Random &lt;jrandom@example.com&gt;

   * subversion/libsvn_ra_ansible/get_editor.c
     (frobnicate_file): Check that file exists before frobnicating.
</pre>

<p>If someone suggested something useful, but didn't write the patch,
indicate their contribution with "Suggested&nbsp;by:&nbsp;":</p>

<pre>
   Extend the Contribulyzer syntax to distinguish finds from ideas.

   Suggested by: dlr

   * www/hacking.html (crediting): Adjust accordingly.
</pre>

<p>If someone reviewed the change, use "Review&nbsp;by:&nbsp;"
(or "Reviewed&nbsp;by:&nbsp;" if you prefer):</p>

<pre>
   Fix issue #1729: Don't crash because of a missing file.

   Review by: Eagle Eyes &lt;eeyes@example.com&gt;

   * subversion/libsvn_ra_ansible/get_editor.c
     (frobnicate_file): Check that file exists before frobnicating.
</pre>

<p>A field may have multiple lines, and a log message may contain any
combination of fields:</p>

<pre>
   Fix issue #1729: Don't crash because of a missing file.

   Patch by: J. Random &lt;jrandom@example.com&gt;
             Enrico Caruso &lt;codingtenor@codingtenor.com&gt;
             me
   Found by: J. Random &lt;jrandom@example.com&gt;
   Review by: Eagle Eyes &lt;eeyes@example.com&gt;
              jcommitter

   * subversion/libsvn_ra_ansible/get_editor.c
     (frobnicate_file): Check that file exists before frobnicating.
</pre>

<p>Further details about a contribution should be listed in a
parenthetical aside immediately after the corresponding field.  Such
an aside always applies to the field right above it; in the following
example, the fields have been spaced out for readability, but note
that the spacing is optional and not necessary for parseability:</p>

<pre>
   Fix issue #1729: Don't crash because of a missing file.

   Patch by: J. Random &lt;jrandom@example.com&gt;
   (Tweaked by me.)

   Review by: Eagle Eyes &lt;eeyes@example.com&gt;
              jcommitter
   (Eagle Eyes caught an off-by-one-error in the basename extraction.)

   * subversion/libsvn_ra_ansible/get_editor.c
     (frobnicate_file): Check that file exists before frobnicating.
</pre>

<p>Currently, these fields</p>

<pre>
   Patch by:
   Suggested by:
   Found by:
   Review by:
</pre>

<p>are the only officially-supported crediting fields (where
"supported" means scripts know to look for them), and they are widely
used in Subversion log messages.  Future fields will probably be of
the form "VERB&nbsp;by:&nbsp;", and from time to time someone may use
a field that sounds official but really is not&nbsp;&mdash;&nbsp;for
example, there are a few instances of "Reported&nbsp;by:&nbsp;".
These are okay, but try to use an official field, or a parenthetical
aside, in preference to creating your own.  Also, don't use
"Reported&nbsp;by:&nbsp;" when the reporter is already recorded in an
issue; instead, simply refer to the issue.</p>

<p>Look over Subversion's existing log messages to see how to use
these fields in practice.  This command from the top of your trunk
working copy will help:</p>

<pre>
svn log | contrib/client-side/search-svnlog.pl "(Patch|Review|Suggested) by: "
</pre>

<p><b>Note:</b> The "Approved&nbsp;by:&nbsp;" field seen in some
commit messages is totally unrelated to these crediting fields, and is
generally not parsed by scripts.  It is simply the standard syntax for
indicating either who approved a partial committer's commit outside
their usual area, or (in the case of merges to release branches) who
voted for the change to be merged.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="patches" title="patches">
<h2>Patch submission guidelines</h2>

<p>Mail patches to dev@subversion.tigris.org, with a subject line
that contains the word "PATCH" in all uppercase, for example</p>

<pre>
   Subject: [PATCH] fix for rev printing bug in svn status
</pre>

<p>A patch submission should contain one logical change; please don't
mix N unrelated changes in one submission&nbsp;&mdash;&nbsp;send N
separate emails instead.</p>

<p>You can put the patch's log message in the body of the email, or at
the top of the patch attachment (see below).  Either way, it should
follow the guidelines given in <a href="#log-messages">Writing
log messages</a>, and be enclosed in triple square brackets, like so:</p>

<pre>
   [[[
   Fix issue #1729: Don't crash because of a missing file.

   * subversion/libsvn_ra_ansible/get_editor.c
     (frobnicate_file): Check that file exists before frobnicating.
   ]]]
</pre>

<p>The brackets are not actually part of the log message, they are
just a way to clearly mark off the log message from its surrounding
context.</p>

<p>The patch itself should be in unified diff format (e.g., "svn diff"
or "diff -u").  Send the patch as an attachment, with a mime-type of
text/x-diff, text/x-patch, or text/plain.  (Most people's mailreaders
can display those inline, and having the patch as an attachment allows
them to extract the patch from the message conveniently.)</p>

<p>If you can't attach the patch with one of these mime-types, or if
the patch is very short, then just include it directly in the body of
your message.  But if your mailer forces wrapping of long lines, then
you must attach the patch, otherwise it is likely to get munged.
Never send patches in archived or compressed form (e.g., tar, gzip,
zip, bzip2), because that prevents people from reviewing the patch
directly in their mailreaders.</p>

<p>If the patch implements a new feature, make sure to describe the
feature completely in your mail; if the patch fixes a bug, describe
the bug in detail and give a reproduction recipe.  An exception to
these guidelines is when the patch addresses a specific issue in the
issues database&nbsp;&mdash;&nbsp;in that case, just make sure to
refer to the issue number in your log message, as described
in <a href="#log-messages">Writing log messages</a>.</p>

<p>It is normal for patches to undergo several rounds of feedback and
change before being applied.  Don't be discouraged if your patch is
not accepted immediately&nbsp;&mdash;&nbsp;it doesn't mean you goofed,
it just means that there are a *lot* of eyes looking at every code
submission, and it's a rare patch that doesn't have at least a little
room for improvement.  After reading people's responses to your patch,
make the appropriate changes and resubmit, wait for the next round of
feedback, and lather, rinse, repeat, until some committer applies
it.</p>

<p>If you don't get a response for a while, and don't see the patch
applied, it may just mean that people are really busy.  Go ahead and
repost, and don't hesitate to point out that you're still waiting for
a response.  One way to think of it is that patch management is highly
parallizable, and we need you to shoulder your share of the management
as well as the coding.  Every patch needs someone to shepherd it
through the process, and the person best qualified to do that is the
original submitter.</p>

<div class="h3" id="patch-manager" title="patch-manager">
<h3>The "Patch Manager" Role</h3>

<p>Subversion usually has a Patch Manager, whose job is to watch the
dev@ mailing list and make sure that no patches "slip through the
cracks".</p>

<p>This means watching every thread containing "[PATCH]" mails, and
taking appropriate action based on the progress of the thread.  If the
thread resolves on its own (because the patch gets committed, or
because there is consensus that the patch doesn't need to be applied,
or whatever) then no further action need be taken.  But if the thread
fades out without any clear decision, then the patch needs to be saved
in the issue tracker.  This means that a summary of any discussion
threads around that patch, and links to relevant mailing list
archives, will be added to some issue in the tracker.  For a patch
which addresses an existing issue tracker item, the patch is saved to
that item.  Otherwise, a new issue of type 'PATCH' is filed, and the
patch is saved to that new issue.</p>

<p>The Patch Manager needs a basic technical understanding of
Subversion, and the ability to skim a thread and get a rough
understanding of whether consensus has been reached, and if so, of
what kind.  It does *not* require actual Subversion development
experience or commit access.  Expertise in using one's mail reading
software is optional, but recommended :-).</p>

<p>The current patch manager is Michael Thelen
&lt;mike@pietdepsi.com&gt;.</p>

</div>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="filing-issues" title="filing-issues">
<h2>Filing bugs / issues</h2>

<p>This pretty much says it all:</p>

<pre>
   From: Karl Fogel &lt;kfogel@collab.net&gt;
   Subject: Please ask on the list before filing a new issue.
   To: dev@subversion.tigris.org
   Date: Tue, 30 Jul 2002 10:51:24 (CDT)
   
   Folks, we're getting tons of new issues, which is a Good Thing in
   general, but some of them don't really belong in the issue tracker.
   They're things that would be better solved by a quick conversation
   here on the dev list.  Compilation problems, behavior questions,
   feature ideas that have been discussed before, that sort of thing.
   
   *Please* be more conservative about filing issues.  The issues
   database is physically much more cumbersome than email.  It wastes
   people's time to have conversations in the issues database that should
   be had in email.  (This is not a libel against the issue tracker, it's
   just a result of the fact that the issues database is for permanent
   storage and flow annotation, not for real-time conversation.)
   
   If you encounter a situation where Subversion is clearly behaving
   wrongly, or behaving opposite to what the documentation says, then
   it's okay to file the issue right away (after searching to make sure
   it isn't already filed, of course!).  But if you're
   
      a) Requesting a new feature, or
      b) Having build problems, or
      c) Not sure what the behavior should be, or
      d) Disagreeing with current intended behavior, or
      e) Not TOTALLY sure that others would agree this is a bug, or
      f) For any reason at all not sure this should be filed,
   
   ...then please post to the dev list first.  You'll get a faster
   response, and others won't be forced to use the issues database to
   have the initial real-time conversations.
   
   Nothing is lost this way.  If we eventually conclude that it should be
   in the issue tracker, then we can still file it later, after the
   description and reproduction recipe have been honed on the dev list.
   
   Thank you,
   -Karl
</pre>
   
</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="commit-access" title="commit-access">
<h2>Commit access</h2>

<p>There are two types of commit access: full and partial.  Full means
anywhere in the tree, partial means only in that committer's specific
area(s) of expertise.  The COMMITTERS file lists all committers, both
full and partial, and says the domains for each partial committer.</p>

<div class="h3" id="full-commit-access" title="full-commit-access">
<h3>How full commit access is granted</h3>

<p>After someone has successfully contributed a few non-trivial
patches, some full committer, usually whoever has reviewed and applied
the most patches from that contributor, proposes them for commit
access.  This proposal is sent only to the other full committers --
the ensuing discussion is private, so that everyone can feel
comfortable speaking their minds.  Assuming there are no objections,
the contributor is granted commit access.  The decision is made by
consensus; there are no formal rules governing the procedure, though
generally if someone strongly objects the access is not offered, or is
offered on a provisional basis.</p>

<p><i>The primary criterion for full commit access is good
judgment.</i></p>

<p>You do not have to be a technical wizard, or demonstrate deep
knowledge of the entire codebase, to become a full committer.  You
just need to know what you don't know.  If your patches adhere to the
guidelines in this file, adhere to all the usual unquantifiable rules
of coding (code should be readable, robust, maintainable, etc.), and
respect the Hippocratic Principle of "first, do no harm", then you
will probably get commit access pretty quickly.  The size, complexity,
and quantity of your patches do not matter as much as the degree of
care you show in avoiding bugs and minimizing unnecessary impact on
the rest of the code.  Many full committers are people who have not
made major code contributions, but rather lots of small, clean fixes,
each of which was an unambiguous improvement to the code.  (Of course,
this does not mean the project needs a bunch of very trivial patches
whose only purpose is to gain commit access; knowing what's worth a
patch post and what's not is part of showing good judgement :-) .)</p>

<p>To assist developers in discovering new committers, we record
patches and other contributions in a <a href="#crediting">special
crediting format</a>, which is then parsed to produce a
browser-friendly <a
href="http://www.red-bean.com/svnproject/contribulyzer/">contribution
list</a>, updated nightly.  If you're thinking of proposing someone
for commit access and want to look over all their changes, that <a
href="http://www.red-bean.com/svnproject/contribulyzer/">contribution
list</a> might be the most convenient place to do it.</p>

</div>

<div class="h3" id="partial-commit-access" title="partial-commit-access">
<h3>How partial commit access is granted</h3>

<p>A full committer sponsors the partial committer.  Usually this
means the full committer has applied several patches to the same area
from the proposed partial committer, and realizes things would be
easier if the person were just committing directly.  Approval is not
required from the full committers; it is assumed that sponsors know
what they're doing and will watch the partial committer's first few
commits to make sure everything's going smoothly.</p>

<p>Patches submitted by a partial committer may be committed by that
committer even if they are outside that person's domain.  This
requires approval (often expressed as a +1 vote) from at least one
full committer.  In such a case, the approval should be noted in the
log message, like so:</p>

<pre>
   Approved by: lundblad
</pre>

</div>

<div class="h3" id="contrib-area" title="contrib-area">
<h3>The contrib/ area</h3>

<p>When a tool is accepted into the <i>contrib/</i> area, we
automatically offer its author partial commit access to maintain the
tool there.  Any full committer can sponsor this.  Usually no
discussion or vote is necessary, though if there are objections then
the usual decision-making procedures apply (attempt to reach consensus
first, then vote among the full committers if consensus cannot be
reached).</p>

<p>Code under contrib/ must be open source, but need not have the same
license or copyright holder as Subversion itself.</p>

</div>

<div class="h3" id="obvious-fix" title="obvious-fix">
<h3>The "obvious fix" rule</h3>

<p>Any committer, whether full or partial, may commit fixes for
obvious typos, grammar mistakes, and formatting problems wherever they
may be&nbsp;&mdash;&nbsp;in the web pages, API documentation, code
comments, commit messages, etc.  We rely on the committer's judgement
to determine what is "obvious"; if you're not sure, just ask.</p>

</div>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="configury" title="configury">
<h2>The configuration/build system under unix</h2>

<p>Greg Stein wrote a custom build system for Subversion, which had
been using `automake' and recursive Makefiles.  Now it uses a single,
top-level Makefile, generated from Makefile.in (which is kept under
revision control).  `Makefile.in' in turn includes `build-outputs.mk',
which is automatically generated from `build.conf' by the
`gen-make.py' script.  Thus, the latter two are under revision
control, but `build-outputs.mk' is not.</p>

<p>Here is Greg's original mail describing the system, followed by
some advice about hacking it:</p>

<pre>
   From: Greg Stein &lt;gstein@lyra.org&gt;
   Subject:  new build system (was: Re: CVS update: MODIFIED: ac-helpers ...)
   To: dev@subversion.tigris.org
   Date: Thu, 24 May 2001 07:20:55 -0700
   Message-ID: &lt;20010524072055.F5402@lyra.org&gt;

   On Thu, May 24, 2001 at 01:40:17PM -0000, gstein@tigris.org wrote:
   &gt;   User: gstein
   &gt;   Date: 01/05/24 06:40:17
   &gt;
   &gt;   Modified:    ac-helpers .cvsignore svn-apache.m4
   &gt;   Added:       .        Makefile.in
   &gt;   Log:
   &gt;   Switch over to the new non-recursive build system.
   &gt;...

   Okay... this is it. We're now on the build system.

       "It works on my machine."

   I suspect there may be some tweaks to make on different OSs. I'd be
   interested to hear if Ben can really build with normal BSD make. It
   should be possible.

   The code supports building, installation, checking, and
   dependencies. It does *NOT* yet deal with the doc/ subdirectory. That
   is next; I figured this could be rolled out and get the kinks worked
   out while I do the doc/ stuff.  Oh, it doesn't build Neon or APR yet
   either. I also saw a problem where libsvn_fs wasn't getting built
   before linking one of the test proggies (see below).

   Basic operation: same as before.

   $ ./autogen.sh
   $ ./configure OPTIONS
   $ make
   $ make check
   $ make install

   There are some "make check" scripts that need to be fixed up. That'll
   happen RSN. Some of them create their own log, rather than spewing to
   stdout (where the top-level make will place the output into
   [TOP]/tests.log).

   The old Makefile.am files are still around, but I'll be tossing those
   along with a bunch of tweaks to all the .cvsignore files. There are a
   few other cleanups, too. But that can happen as a step two.

   [ $ cvs rm -f `find . -name Makefile.rm`

     See the mistake in that line? I didn't when I typed it. The find
     returned nothing, so cvs rm -f proceeded to delete my entire
     tree. And the -f made sure to delete all my source files, too. Good
     fugging thing that I had my mods in some Emacs buffers, or I'd be
     bitching.

     I am *so* glad that Ben coded SVN to *not* delete locally modified
     files *and* that we have an "undel" command. I had to go and tweak a
     bazillion Entries files to undo the delete...
   ]

   The top-level make has a number of shortcuts in it (well, actually in
   build-outputs.mk):

   $ make subversion/libsvn_fs/libsvn_fs.la

   or

   $ make libsvn_fs

   The two are the same. So... when your test proggie fails to link
   because libsvn_fs isn't around, just run "make libsvn_fs" to build it
   immediately, then go back to the regular "make".

   Note that the system still conditionally builds the FS stuff based
   on whether DB (See 'Building on Unix' below) is available, and
   mod_dav_svn if Apache is available.

   Handy hint: if you don't like dependencies, then you can do:

   $ ./autogen.sh -s

   That will skip the dependency generation that goes into
   build-outputs.mk. It makes the script run quite a bit faster (48 secs
   vs 2 secs on my poor little Pentium 120).

   Note that if you change build.conf, you can simply run:

   $ ./gen-make.py build.conf

   to regen build-outputs.mk. You don't have to go back through the whole
   autogen.sh / configure process.

   You should also note that autogen.sh and configure run much faster now
   that we don't have the automake crap. Oh, and our makefiles never
   re-run configure on you out of the blue (gawd, I hated when automake
   did that to me).

   Obviously, there are going to be some tweaky things going on. I also
   think that the "shadow" builds or whatever they're called (different
   source and build dirs) are totally broken. Something tweaky will have
   to happen there.  But, thankfully, we only have one Makefile to deal
   with.

   Note that I arrange things so that we have one generated file
   (build-outputs.mk), and one autoconf-generated file (Makefile from
   .in).  I also tried to shove as much logic/rules into
   Makefile.in. Keeping build-outputs.mk devoid of rules (thus, implying
   gen-make.py devoid of rules in its output generation) manes that
   tweaking rules in Makefile.in is much more approachable to people.

   I think that is about it. Send problems to the dev@ list and/or feel
   free to dig in and fix them yourself. My next steps are mostly
   cleanup. After that, I'm going to toss out our use of libtool and rely
   on APR's libtool setup (no need for us to replicate what APR already
   did).

   Cheers,
   -g

   --
   Greg Stein, http://www.lyra.org/
</pre>

<p>And here is some advice for those changing or testing the
configuration/build system:</p>

<pre>
   From: Karl Fogel &lt;kfogel@collab.net&gt;
   To: dev@subversion.tigris.org
   Subject: when changing build/config stuff, always do this first
   Date: Wed 28 Nov 2001

   Yo everyone: if you change part of the configuration/build system,
   please make sure to clean out any old installed Subversion libs
   *before* you try building with your changes.  If you don't do this,
   your changes may appear to work fine, when in fact they would fail if
   run on a truly pristine system.

   This script demonstrates what I mean by "clean out".  This is
   `/usr/local/cleanup.sh' on my system.  It cleans out the Subversion
   libs (and the installed httpd-2.0 libs, since I'm often reinstalling
   that too):

      #!/bin/sh

      # Take care of libs
      cd /usr/local/lib
      rm -f APRVARS
      rm -f libapr*
      rm -f libexpat*
      rm -f libneon*
      rm -f libsvn*

      # Take care of headers
      cd /usr/local/include
      rm -f apr*
      rm -f svn*
      rm -f neon/*

      # Take care of headers
      cd /usr/local/apache2/lib
      rm -f *

   When someone reports a configuration bug and you're trying to
   reproduce it, run this first. :-)

   The voice of experience,
   -Karl
</pre>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="releasing" title="releasing">
<h2>How to release a distribution tarball</h2>

<p>See notes/releases.txt.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="release-numbering" title="release-numbering">
<h2>Release numbering, compatibility, and deprecation</h2>

<p>Subversion uses "MAJOR.MINOR.PATCH" release numbers, with the same
guidelines as APR (see <a href="http://apr.apache.org/versioning.html"
>http://apr.apache.org/versioning.html</a>), plus a few extensions,
described later.  The general idea is:</p>

<ol>

<li><p>Upgrading/downgrading between different patch releases in the
       same MAJOR.MINOR line never breaks code.  It may cause bugfixes
       to disappear/reappear, but API signatures and semantics remain
       the same.  (Of course, the semantics may change in the trivial
       ways appropriate for bugfixes, just not in ways that would
       force adjustments in calling code.)</p>
</li>

<li><p>Upgrading to a new minor release in the same major line may
       cause new APIs to appear, but not remove any APIs.  Any code
       written to the old minor number will work with any later minor
       number in that line.  However, downgrading afterwards may not
       work, if new code has been written that takes advantage of the
       new APIs.</p>
</li>

<li><p>When the major number changes, all bets are off.  This is the
       only opportunity for a full reset of the APIs, and while we try
       not to gratuitously remove interfaces, we will use it to clean
       house a bit.</p>
</li>

</ol>

<p>Subversion extends the APR guidelines to cover client/server
compatibility questions:</p>

<ol>

<li><p>A patch or minor number release of a server (or client) never
       breaks compatibility with a client (or server) in the same
       major line.  However, new features offered by the release might
       be unsupported without a corresponding upgrade to the other
       side of the connection.  For updating ra_svn code specifically,
       please observe these principles:</p>

    <ol>

    <li><p>Fields can be added to any tuple; old clients will simply
           ignore them.  (Right now, the marshalling implementation
           does not let you put number or boolean values in the
           optional part of a tuple, but changing that will not affect
           the protocol.)</p>
   
        <p>We can use this mechanism when information is added to an
           API call.</p>
    </li>
   
    <li><p>At connection establishment time, clients and servers exchange
           a list of capability keywords.</p>
   
         <p>We can use this mechanism for more complicated changes,
           like introducing pipelining or removing information from
           API calls.</p>
    </li>
   
    <li><p>New commands can be added; trying to use an unsupported
           command will result in an error which can be checked and dealt
           with.</p>
    </li>
   
    <li><p>The protocol version number can be bumped to allow graceful
           refusal of old clients or servers, or to allow a client or
           server to detect when it has to do things the old way.</p>
 
        <p>This mechanism is a last resort, to be used when capability
           keywords would be too hard to manage.</p>
    </li>

    </ol>
</li>

<li><p>Working copy and repository formats are backward- and
       forward-compatible for all patch releases in the same minor
       series.  They are forward-compatible for all minor releases in
       the same major series; however, a minor release is allowed to
       make a working copy or repository that doesn't work with
       previous minor releases, where "make" could mean "upgrade" as
       well as "create".</p>
</li>

</ol>

<p>Subversion does not use the "even==stable, odd==unstable"
convention; any unqualified triplet indicates a stable release:</p>

<pre>
   1.0.1  --&gt;  first stable patch release of 1.0
   1.1.0  --&gt;  next stable minor release of 1.x after 1.0.x
   1.1.1  --&gt;  first stable patch release of 1.1.x
   1.1.2  --&gt;  second stable patch release of 1.1.x
   1.2.0  --&gt;  next stable minor release after that
</pre>

<p>The order of releases is semi-nonlinear&nbsp;&mdash;&nbsp;a 1.0.3
*might* come out after a 1.1.0.  But it's only "semi"-nonlinear
because eventually we declare a patch line defunct and tell people to
upgrade to the next minor release, so over the long run the numbering
is basically linear.</p>

<p>Non-stable releases are qualified with "alphaN" or "betaN"
suffixes, and release candidates with "-rcN".  For example, the
prereleases leading to 1.3.7 might look like this:</p>

<pre>
   subversion-1.3.7-rc1.tar.gz
   subversion-1.3.7-rc2.tar.gz
   subversion-1.3.7-rc3.tar.gz
   subversion-1.3.7.tar.gz
</pre>

<p>The output of 'svn --version' corresponds in the obvious way:</p>

<pre>
   version 1.3.7 (Release Candidate 1)
   version 1.3.7 (Release Candidate 2)
   version 1.3.7 (Release Candidate 3)
   version 1.3.7
</pre>

<p>When you 'make install' subversion-1.3.7-rc1, it still installs as
though it were "1.3.7", of course.  The qualifiers are metadata on the
release; we want each subsequent prerelease release to overwrite the
previous one, and the final release to overwrite the last
prerelease.</p>

<p>For working copy builds, there is no tarball name to worry about,
but 'svn --version' still produces special output:</p>

<pre>
   version 1.3.7 (dev build, rXXXX)
</pre>

<p>The "rXXXX" is not important (if it proves difficult to implement,
we may omit it).  The important thing is to say "dev build".  This
indicates that the build came from a working copy, which is useful in
bug reports.</p>

<p>We have no mechanism for releasing dated snapshots.  If we want
code to get wider distribution than just those who build from working
copies, we put out a prerelease.</p>

<div class="h3" id="name-reuse" title="name-reuse">
<h3>Reuse of release names</h3>

<p>If a release or candidate release needs to be quickly re-issued due
to some non-code problem (say, a packaging glitch), it's okay to reuse
the same name, as long as the tarball hasn't been
<a href="#tarball-signing">blessed by signing</a> yet.  But if it has
been uploaded to the standard distribution area with signatures, or if
the re-issue was due to a change in code a user might run, then the
old name must be tossed and the next name used.</p>

</div>

<div class="h3" id="deprecation" title="deprecation">
<h3>Deprecation</h3>

<p>When a new, improved version of an API is introduced, the old one
remains for compatibility, at least until the next major release.
However, we mark the old one as deprecated and point to the new one,
so people know to write to the new API if at all possible.  When
deprecating, mention the release after which the deprecation was
introduced, and point to the new API.  If possible, replace the old
API documentation with a diff to the new one.  For example:</p>

<pre>
   /**
    * @deprecated Provided for backward compatibility with the 1.0.0 API.
    *
    * Similar to svn_repos_dump_fs2(), but with the @a use_deltas
    * parameter always set to @c FALSE.
    */
   svn_error_t *svn_repos_dump_fs(svn_repos_t *repos,
                                  svn_stream_t *dumpstream,
                                  svn_stream_t *feedback_stream,
                                  svn_revnum_t start_rev,
                                  svn_revnum_t end_rev,
                                  svn_boolean_t incremental,
                                  svn_cancel_func_t cancel_func,
                                  void *cancel_baton,
                                  apr_pool_t *pool);
</pre>

<p>When the major release number changes, the "best" new API in a
series generally replaces all the previous ones (assuming it subsumes
their functionality), and it will take the name of the original API.
Thus, marking 'svn_repos_dump_fs' as deprecated in 1.1.x doesn't mean
that 2.0.0 doesn't have 'svn_repos_dump_fs', it just means the
function's signature will be different: it will have the signature
held by svn_repos_dump_fs2 (or svn_repos_dump_fs3, or whatever) in
1.1.x.  The numbered-suffix names disappear, and there is a single
(shiny, new) svn_repos_dump_fs again.</p>

<p>One exception to this replacement strategy is when the old function
has a totally unsatisfying name anyway.  Deprecation is a chance to
fix that: we give the new API a totally new name, mark the old API as
deprecated, point to the new API; then at the major version change, we
remove the old API, but don't rename the new one to the old name,
because its new name is fine.</p>
   
</div>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="release-stabilization" title="release-stabilization">
<h2>Stabilizing and maintaining releases</h2>

<p>Minor and major number releases go through a stabilization period
before release, and remain in maintenance (bugfix) mode after release.
To start the release process, we create an "A.B.x" branch based on the
latest trunk, for example:</p>

<pre>
   $ svn cp http://svn.collab.net/repos/svn/trunk \
            http://svn.collab.net/repos/svn/branches/A.B.x
</pre>

<p>The stabilization period for a new A.B.0 release normally lasts
four weeks, and allows us to make conservative bugfixes and discover
showstopper issues.  The stabilization period begins with a release
candidate tarball with the version A.B.0-rc1.  Further release
candidate tarballs may be made as blocking bugs are fixed; for
example, if a set of language bindings is found to be broken, it is
prudent to make a new release candidate when they are fixed so that
those language bindings may be tested.</p>

<p>At the beginning of the final week of the stabilization period, a
new release candidate tarball should be made if there are any changes
pending since the last one.  The final week of the stabilization
period is reserved for critical bugfixes; fixes for minor bugs should
be deferred to the A.B.1 release.  A critical bug is a non-edge-case
crash, a data corruption problem, a major security hole, or something
equally serious.</p>

<p>Under some circumstances, the stabilization period will be
extended:</p>

<ul>
<li><p>If a potentially destabilizing change must be made in order to
       fix a bug, the entire four-week stabilization period is
       restarted.  A potentially destabilizing change is one which
       could affect many parts of Subversion in unpredictable ways, or
       which involves adding a substantial amount of new code.  Any
       incompatible API change (only allowable in the first place if
       the new release is an A.0.0 release) should be considered a
       potentially destabilizing change.</p>
</li>

<li><p>If a critical bugfix is made during the final week of the
       stabilization period, the final week is restarted.  The final
       A.B.0 release is always identical to the release candidate made
       one week before (with the exceptions discussed below).</p>
</li>

</ul>

<p>If there are disagreements over whether a change is potentially
destabilizing or over whether a bug is critical, they may be settled
with a committer vote.</p>

<p>After the A.B.0 release is out, patch releases (A.B.1, A.B.2, etc.)
follow when bugfixes warrant them.  Patch releases do not require a
four week soak, because only conservative changes go into the
line.</p>

<p>Certain kinds of commits can go into A.B.0 without restarting the
soak period, or into a later release without affecting the testing
schedule or release date:</p>

<ul>
<li><p>Without voting:</p>
    <ul>
    <li><p>Changes to the STATUS file.</p></li>
    <li><p>Documentation file changes, including to the book, README,
           INSTALL, www/, etc.</p></li>
    <li><p>Changes that are a normal part of release bookkeeping, for
           example, the steps listed in notes/releases.txt.</p></li>
    <li><p>Changes to dist.sh by, or approved by, the release manager.</p></li>
    <li><p>Changes to message translations in .po files or additions of
           new .po files.</p></li>
    </ul>
</li>

<li><p>With voting:</p>
    <ul>
    <li><p>Anything affecting only tools/, packages/, or bindings/.</p></li>
    <li><p>Doc fixes in core code header or source files.</p></li>
    <li><p>Changes to printed output, such as error and usage messages, as
           long as format string "%" codes and their args are not
           touched.</p></li>
    </ul>
</li>

</ul>

<p>NOTE: The requirements on message translation changes are looser
than for text messages in C code.  Changing format specifiers in .po
files is allowed because their validity can be checked mechanically
(with the -c flag on msgfmt of GNU gettext).  This is done at build
time if GNU gettext is in use.</p>

<p>Core code changes, of course, require voting, and restart the soak
or test period, since otherwise the change could be undertested.</p>

<p>The voting system works like this:</p>

<p>A change to the A.B.x line must be first proposed in the
A.B.x/STATUS file.  Each proposal consists of a short identifying
block (e.g., the revision number of a trunk or related-line commit, or
perhaps an issue number), a brief description of the change, an
at-most-one-line justification of why it should be in A.B.x, perhaps
some notes/concerns, and finally the votes.  The notes and concerns
are meant to be brief summaries to help a reader get oriented; please
don't use the STATUS file for actual discussion, use dev@ instead.</p>

<p>Here's an example, probably as complex as an entry would ever
get:</p>

<pre>
   * r98765 (issue #56789)
     Make commit editor take a closure object for future mindreading.
     Justification: API stability, as prep for future enhancement.
     Notes: There was consensus on the desirability of this feature in
       the near future; see thread at http://... (Message-Id: blahblah).
     Concerns: Vetoed by jerenkrantz due to privacy concerns with the
       implementation; see thread at http://... (Message-Id: blahblah)
     Votes:
       +1: ghudson, bliss
       +0: cmpilato
       -0: gstein
       -1: jerenkrantz
</pre>

<p>A change needs three +1 votes from full committers (or partial
committers for the involved areas), and no vetoes, to go into
A.B.x.</p>

<p>If you cast a veto (i.e. -1), please state the reason in the
concerns field, and include a url / message-id for the list discussion
if any.  You can go back and add the link later if the thread isn't
available at the time you commit the veto.</p>

<p>Voting +1 on a change doesn't just mean you approve of it in
principle.  It means you have thoroughly reviewed the change, and find
it correct and as nondisruptive as possible.  When it is committed to
the release branch, the log message will include the names of all who
voted for it, as well as the original author and the person making the
commit.  All of these people are considered equally answerable for
bugs.</p>

<p>If you've reviewed a patch, and like it but have some reservations,
you can write "+1 (concept)" and then ask questions on the list about
your concerns.  You can write "+0" if you like the general idea but
haven't reviewed the patch carefully.  Neither of these votes counts
toward the total, but they can be useful for tracking down people who
are following the change and might be willing to spend more time on
it.</p>

<p>There is a somewhat looser voting system for areas that are not
core code, and that may have fewer experts available to review changes
(for example, tools/, packages/, bindings/, test scripts, etc.).  A
change in these areas can go in with a +1 from a full committer or a
partial committer for that area, at least one +0 or "concept +1" from
any other committer, and no vetoes.  (If a change affects the build
system, however, it is considered a core change, and needs three
+1's.)  Use your judgment and don't review changes unless you have
some competence to do so, of course.  The goal is to get at least two
pairs of eyes on the change, without demanding that every reviewer
have the same amount of expertise as the area maintainer.  This way
one can review for general sanity, accurate comments, obvious
mistakes, etc, without being forced to assert "Yes, I understand these
changes in every detail and have tested them."</p>

<p>Before proposing a change in STATUS, you should try merging it onto
the branch to ensure that it doesn't produce merge conflicts.  If
conflicts occur, please create a new temporary branch from the release
branch with your changed merged and the conflicts resolved.  The
branch should be named A.B.x-rYYYY, where YYYY is the first revision
of your change in the STATUS file.  Add a note in the STATUS file
about the existence of the temporary branch.  If the change involves
further work, you can merge those revisions to the branch.  When the
entry for this change is removed from STATUS, this temporary branch
should also be removed to avoid cluttering the /branches
directory.</p>

<p>NOTE: Changes to STATUS regarding the temporary branch, including
voting, are always kept on the main release branch.</p>

</div>

<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="tarball-signing">
<h2>Signing source distribution packages (a.k.a tarballs)</h2>

<p>Before a release or release candidate is officially made public, it is
made available in a temporary location for committers to test and sign.
The point is to have the tarballs tested on more systems than just that of the
person who rolled the release.  When there are three signatures from full
committers for each of the <tt>.tar.bz2</tt>, <tt>.tar.gz</tt> and
<tt>.zip</tt> files, the release (candidate) can go public.</p>

<p>Signing a tarball means that you assert certain things about it.  When
sending your signature (see below), indicate in the mail what steps
you've taken to verify that the tarball is correct.  Running
<tt>make check</tt> over all RA layers and FS backends is a good idea,
as well as building and testing the bindings.</p>

<p>After having extracted and tested the tarball, you should sign it using
<a href="http://www.gnupg.org">gpg</a>.  To do so, use a command like:</p>

<pre>
    gpg -ba subversion-1.3.0-rc4.tar.bz2
</pre>

<p>This will result in a file with the same name as the signed file, but with
a <tt>.asc</tt> extension in the appropriate format for inclusion in the
release announcement.  Include this file in a mail, typically in reply
to the announcement of the unofficial tarball.</p>

<p>If you've downloaded and tested a <tt>.tar.bz2</tt> file, it is possible to
sign a <tt>.tar.gz</tt> file with the same contents without having
to download and test it separately.  The trick is to extract the
<tt>.bz2</tt> file, and pack it using <tt>gzip</tt> like this:</p>

<pre>
    bzip2 -cd subversion-1.3.0-rc4.tar.bz2 \
    | gzip -9n > subversion-1.3.0-rc4.tar.gz
</pre>

<p>The resulting file should be identical to the file generated by the
release manager, and thus can be signed as described above.
To verify that the files are identical, you may use either the MD5 checksums
or the release manager's signature, both of which should be provided with the
tarballs.
</p>
</div>
<![CDATA[---------------------------------------------------------]]>

<div class="h2" id="l10n" title="l10n">
<h2>Localization (l10n)</h2>

<p>Translation has been divided into two domains.  First, there is the
translation of server messages sent to connecting clients.  This issue
has been <a
href="http://svn.collab.net/repos/svn/trunk/notes/l10n-problems">punted
for now</a>.  Second there is the translation of the client and its
libraries.</p>

<p>The gettext package provides services for translating messages.  It
uses the xgettext tool to extract strings from the sources for
translation.  This works by extracting the arguments of the _() and
N_() macros.  The former is used in context where function calls are
allowed (typically anything except static initializers).  The latter
is used whenever _() isn't.  Strings marked with N_() need to be
passed to gettext translation routines whenever referenced in the
code.  For an example, look at how the header and footer are handled
in subversion/svn/help-cmd.c.</p>

<p>When using direct calls to gettext routines (*gettext or
*dgettext), keep in mind that most of Subversion code is library code.
Therefore the default domain is not necessarily Subversion's own
domain.  In library code you should use the dgettext versions of the
gettext functions.  The domain name is defined in the PACKAGE_NAME
define.</p>

<p>All required setup for localization is controlled by the ENABLE_NLS
conditional in svn_private_config.h (for *nix) and
svn_private_config.hw (for Windows).  Be sure to put</p>

<pre>
   #include "svn_private_config.h"
</pre>

<p>as the last include in any file which requires localization.</p>

<p>Also note that return values of _() and *gettext() calls are UTF-8
encoded; this means that they should be translated to the current
locale being written as any form of program output.</p>

<p>The GNU gettext manual
(<a
href="http://www.gnu.org/software/gettext/manual/html_node/gettext_toc.html"
>http://www.gnu.org/software/gettext/manual/html_node/gettext_toc.html</a>)
provides additional information on writing translatable programs in
its section "Preparing Program Sources".  Its hints mainly apply to
string composition.</p>

</div>

</div>
</body>
</html>