This file is indexed.

/usr/share/bash-completion/completions/svn is in subversion 1.9.3-2ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   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
# ------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
# ------------------------------------------------------------

# Programmable completion for the Subversion svn command under bash. Source
# this file (or on some systems add it to ~/.bash_completion and start a new
# shell) and bash's completion mechanism will know all about svn's options!
# Provides completion for the svnadmin, svndumpfilter, svnlook and svnsync
# commands as well.  Who wants to read man pages/help text...

# Known to work with bash 3.* with programmable completion and extended
# pattern matching enabled (use 'shopt -s extglob progcomp' to enable
# these if they are not already enabled).

shopt -s extglob

# Tree helper functions which only use bash, to ease readability.

# look for value associated to key from stdin in K/V hash file format
# val=$(_svn_read_hashfile svn:realmstring < some/file)
function _svn_read_hashfile()
{
  local tkey=$1 key= val=
  while true; do
    read tag len
    [ $tag = 'END' ] && break
    [ $tag != 'K' ] && {
      #echo "unexpected tag '$tag' instead of 'K'" >&2
      return
    }
    read -r -n $len key ; read
    read tag len
    [ $tag != 'V' ] && {
      #echo "unexpected tag '$tag' instead of 'V'" >&2
      return
    }
    read -r -n $len val ; read
    if [[ $key = $tkey ]] ; then
      echo "$val"
      return
    fi
  done
  #echo "target key '$tkey' not found" >&2
}

# _svn_grcut shell-regular-expression
# extract filenames from 'svn status' output
function _svn_grcut()
{
    local re=$1 line= old_IFS
    # fix IFS, so that leading spaces are not ignored by next read.
    # (there is a leading space in svn status output if only a prop is changed)
    old_IFS="$IFS"
    IFS=$'\n'
    while read -r line ; do
	[[ ! $re || $line == $re ]] && echo "${line/????????/}"
    done
    IFS="$old_IFS"
}

# extract stuff from svn info output
# _svn_info (URL|Repository Root)
function _svn_info()
{
  local what=$1 line=
  LANG=C LC_MESSAGES=C svn info --non-interactive 2> /dev/null | \
  while read line ; do
    [[ $line == *"$what: "* ]] && echo ${line#*: }
  done
}

# _svn_lls (dir|file|all) files...
# list svn-managed files from list
# some 'svn status --all-files' would be welcome here?
function _svn_lls()
{
    local opt=$1 f=
    shift
    for f in "$@" ; do
	# could try to check in .svn/entries? hmmm...
	if [[ $opt == @(dir|all) && -d "$f" ]] ; then
	    echo "$f/"
	elif [[ $opt == @(file|all) ]] ; then
	    # split f in directory/file names
	    local dn= fn="$f"
	    [[ "$f" == */* ]] && dn=${f%\/*}/ fn=${f##*\/}
	    # ??? this does not work for just added files, because they
	    # do not have a content reference yet...
	    [ -f "${dn}.svn/text-base/${fn}.svn-base" ] && echo "$f"
	fi
    done
}

# This completion guides the command/option order along the one suggested
# by "svn help", although other syntaxes are allowed.
#
# - there is a "real" parser to check for what is available and deduce what
#   can be suggested further.
# - the syntax should be coherent with subversion/svn/{cl.h,main.c}
# - although it is not a good practice, mixed options and arguments
#   is supported by the completion as it is by the svn command.
# - the completion works in the middle of a line,
#   but not really in the middle of an argument or option.
# - property names are completed: see comments about issues related to handling
#   ":" within property names although it is a word completion separator.
# - unknown properties are assumed to be simple file properties.
# - --revprop and --revision options are forced to revision properties
#   as they are mandatory in this case.
# - argument values are suggested to some other options, eg directory names
#   for --config-dir.
# - values for some options can be extended with environment variables:
#   SVN_BASH_FILE_PROPS: other properties on files/directories
#   SVN_BASH_REV_PROPS: other properties on revisions
#   SVN_BASH_ENCODINGS: encodings to be suggested
#   SVN_BASH_MIME_TYPE: mime types to be suggested
#   SVN_BASH_KEYWORDS: "svn:keywords" substitutions to be suggested
#   SVN_BASH_USERNAME: usernames suggested for --username
#   SVN_BASH_COMPL_EXT: completion extensions for file arguments, based on the
#      current subcommand, so that for instance only modified files are
#      suggested for 'revert', only not svn-managed files for 'add', and so on.
#      Possible values are:
#      - username: guess usernames from ~/.subversion/auth/...
#      - urls: guess urls from ~/.subversion/auth/... or others
#      - svnstatus: use 'svn status' for completion
#      - recurse: allow recursion (expensive)
#      - externals: recurse into externals (very expensive)
#     Former options are reasonable, but beware that both later options
#     may be unadvisable if used on large working copies.
#     None of these costly completions are activated by default.
#     Argument completion outside a working copy results in an error message.
#     Filenames with spaces are not completed properly.
#
# TODO
# - other options?
# - obsolete options could be removed from auto-comp? (e.g. -N)
# - obsolete commands could be removed? (e.g. resolved)
# - completion does not work properly when editing in the middle of the line
#   status/previous are those at the end of the line, not at the entry position
# - url completion should select more cases where it is relevant
# - url completion of http:// schemas could suggest sub directories?
# - add completion for experimental 'obliterate' feature?
_svn()
{
	local cur cmds cmdOpts pOpts mOpts rOpts qOpts nOpts optsParam opt

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	# Possible expansions, without pure-prefix abbreviations such as "up".
	cmds='add auth blame annotate praise cat changelist cl checkout co cleanup'
	cmds="$cmds commit ci copy cp delete remove rm diff export help import"
	cmds="$cmds info list ls lock log merge mergeinfo mkdir move mv rename"
	cmds="$cmds patch propdel pdel propedit pedit propget pget proplist"
	cmds="$cmds plist propset pset relocate resolve resolved revert status"
	cmds="$cmds switch unlock update upgrade"

	# help options have a strange command status...
	local helpOpts='--help -h'
	# all special options that have a command status
	local specOpts="--version $helpOpts"

	# options that require a parameter
	# note: continued lines must end '|' continuing lines must start '|'
	optsParam="-r|--revision|--username|--password|--targets"
	optsParam="$optsParam|-x|--extensions|-m|--message|-F|--file"
	optsParam="$optsParam|--encoding|--diff-cmd|--diff3-cmd|--editor-cmd"
	optsParam="$optsParam|--old|--new|--config-dir|--config-option"
	optsParam="$optsParam|--native-eol|-l|--limit|-c|--change"
	optsParam="$optsParam|--depth|--set-depth|--with-revprop"
	optsParam="$optsParam|--cl|--changelist|--accept|--show-revs"

	# svn:* and other (env SVN_BASH_*_PROPS) properties
	local svnProps revProps allProps psCmds propCmds

	# svn and user configured "file" (or directory) properties
	# the "svn:mergeinfo" prop is not included by default because it is
	# managed automatically, so there should be no need to edit it by hand.
	svnProps="svn:keywords svn:executable svn:needs-lock svn:externals
	          svn:ignore svn:eol-style svn:mime-type $SVN_BASH_FILE_PROPS"

	# svn and user configured revision properties
	revProps="svn:author svn:log svn:date $SVN_BASH_REV_PROPS"

	# all properties as an array variable
	allProps=( $svnProps $revProps )

	# subcommands that expect property names
	psCmds='propset|pset|ps'
	propCmds="$psCmds|propget|pget|pg|propedit|pedit|pe|propdel|pdel|pd"

	# possible URL schemas to access a subversion server
	local urlSchemas='file:/// http:// https:// svn:// svn+ssh://'

	# Parse arguments and set various variables about what was found.
	#
	# cmd: the current command if available
	#    isPropCmd: whether it expects a property name argument
	#    isPsCmd: whether it also expects a property value argument
	#    isHelpCmd: whether it is about help
	#    nExpectArgs: how many arguments are expected by the command
	# help: help requested about this command (if cmd=='help')
	# prop: property name (if appropriate)
	#    isRevProp: is it a special revision property
	# val: property value (if appropriate, under pset)
	# options: all options encountered
	#    hasRevPropOpt: is --revprop set
	#    hasRevisionOpt: is --revision set
	#    hasRelocateOpt: is --relocate set
	#    hasReintegrateOpt: is --reintegrate set
	#    acceptOpt: the value of --accept
	# nargs: how many arguments were found
	# stat: status of parsing at the 'current' word
	#
	# prev: previous command in the loop
	# last: status of last parameter analyzed
	# i: index
	local cmd= isPropCmd= isPsCmd= isHelpCmd= nExpectArgs= isCur= i=0
	local prev= help= prop= val= isRevProp= last='none' nargs=0 stat=
	local options= hasRevPropOpt= hasRevisionOpt= hasRelocateOpt=
	local acceptOpt= URL= hasReintegrateOpt=

	for opt in "${COMP_WORDS[@]}"
	do
	    # get status of current word (from previous iteration)
	    [[ $isCur ]] && stat=$last

	    # are we processing the current word
	    isCur=
	    [[ $i -eq $COMP_CWORD ]] && isCur=1
	    let i++

	    # FIRST must be the "svn" command
	    [ $last = 'none' ] && { last='first'; continue ; }

	    # SKIP option arguments
	    if [[ $prev == @($optsParam) ]] ; then

		# record accept value
		[[ $prev = '--accept' ]] && acceptOpt=$opt

		prev=''
		last='skip'
		continue ;
	    fi

	    # Argh...  This looks like a bash bug...
	    # Redirections are passed to the completion function
	    # although it is managed by the shell directly...
	    # It matters because we want to tell the user when no more
	    # completion is available, so it does not necessary
	    # fallback to the default case.
	    if [[ $prev == @(<|>|>>|[12]>|[12]>>) ]] ; then
		prev=''
		last='skip'
		continue ;
	    fi
	    prev=$opt

	    # get the subCoMmanD
	    if [[ ! $cmd && $opt \
               && ( $opt != -* || $opt == @(${specOpts// /|}) ) ]]
            then
		cmd=$opt
		[[ $cmd == @($propCmds) ]] && isPropCmd=1
		[[ $cmd == @($psCmds) ]] && isPsCmd=1
		[[ $cmd == @(${helpOpts// /|}) ]] && cmd='help'
		[[ $cmd = 'help' ]] && isHelpCmd=1
	        # HELP about a command asked with an option
		if [[ $isHelpCmd && $cmd && $cmd != 'help' && ! $help ]]
		then
		    help=$cmd
		    cmd='help'
		fi
		last='cmd'
		continue
	    fi

	    # HELP about a command
	    if [[ $isHelpCmd && ! $help && $opt && $opt != -* ]]
	    then
		help=$opt
		last='help'
		continue
	    fi

	    # PROPerty name
	    if [[ $isPropCmd && ! $prop && $opt && $opt != -* ]]
	    then
		prop=$opt
		[[ $prop == @(${revProps// /|}) ]] && isRevProp=1
		last='prop'
		continue
	    fi

	    # property VALue
	    if [[ $isPsCmd && $prop && ! $val && $opt != -* ]] ;
	    then
		val=$opt
		last='val'
		continue
	    fi

	    if [[ $last != 'onlyarg' ]]
	    then
	      # more OPTions
	      case $opt in
		  -r|--revision|--revision=*)
		      hasRevisionOpt=1
		      ;;
		  --revprop)
		      hasRevPropOpt=1
		      # restrict to revision properties!
		      allProps=( $revProps )
		      # on revprops, only one URL is expected
		      nExpectArgs=1
		      ;;
		  -h|--help)
		      isHelpCmd=1
		      ;;
		  -F|--file)
		      val='-F'
		      ;;
		  --relocate)
		      hasRelocateOpt=1
		      ;;
		  --reintegrate)
		      hasReintegrateOpt=1
		      ;;
	      esac

	      # no more options, only arguments, whatever they look like.
	      if [[ $opt = '--' && ! $isCur ]] ; then
		  last='onlyarg'
		  continue
	      fi

	      # options are recorded...
	      if [[ $opt == -* ]] ; then
		  # but not the current one!
		  [[ ! $isCur ]] && options="$options $opt "
		  last='opt'
		  continue
	      fi
	    else
		# onlyarg
		let nargs++
		continue
	    fi

	    # then we have an argument
	    if [[ $cmd = 'merge' && ! $URL ]] ; then
              # fist argument is the source URL for the merge
	      URL=$opt
	    fi

	    last='arg'
	    let nargs++
	done
	# end opt option processing...
	[[ $stat ]] || stat=$last

	# suggest all subcommands, including special help
	if [[ ! $cmd || $stat = 'cmd' ]]
	then
	    COMPREPLY=( $( compgen -W "$cmds $specOpts" -- $cur ) )
	    return 0
	fi

	# suggest all subcommands
	if [[ $stat = 'help' || ( $isHelpCmd && ! $help ) ]]
	then
	    COMPREPLY=( $( compgen -W "$cmds" -- $cur ) )
	    return 0
	fi

	# URL completion
	if [[ $cmd == @(co|checkout|ls|list) && $stat = 'arg' && \
			$SVN_BASH_COMPL_EXT == *urls* ]]
	then
		# see about COMP_WORDBREAKS workaround in prop completion
		if [[ $cur == file:* ]]
		then
			# file completion for file:// urls
			local where=${cur/file:/}
			COMPREPLY=( $(compgen -d -S '/' -X '*/.*' -- $where ) )
			return
		elif [[ $cur == *:* ]]
		then
			# get known urls
			local urls= file=
			for file in ~/.subversion/auth/svn.simple/* ; do
				if [ -r $file ] ; then
					local url=$(_svn_read_hashfile svn:realmstring < $file)
					url=${url/*</}
					url=${url/>*/}
					urls="$urls $url"
				fi
			done

			# only suggest/show possible suffixes
			local prefix=${cur%:*} suffix=${cur#*:} c= choices=
			for c in $urls ; do
				[[ $c == $prefix:* ]] && choices="$choices ${c#*:}"
			done

			COMPREPLY=( $(compgen -W "$choices" -- $suffix ) )
			return
		else
			# show schemas
			COMPREPLY=( $(compgen -W "$urlSchemas" -- $cur) )
			return
		fi
	fi

	if [[ $cmd = 'merge' || $cmd = 'mergeinfo' ]]
	then
	  local here=$(_svn_info URL)
	  # suggest a possible URL for merging
	  if [[ ! $URL && $stat = 'arg' ]] ; then
	    # we assume a 'standard' repos with branches and trunk
	    if [[ "$here" == */branches/* ]] ; then
	      # we guess that it is a merge from the trunk
	      COMPREPLY=( $(compgen -W ${here/\/branches\/*/\/trunk} -- $cur ) )
	      return 0
	    elif [[ "$here" == */trunk* ]] ; then
	      # we guess that it is a merge from a branch
	      COMPREPLY=( $(compgen -W ${here/\/trunk*/\/branches\/} -- $cur ) )
	      return 0
	    else
	      # no se, let us suggest the repository root...
	      COMPREPLY=( $(compgen -W $(_svn_info Root) -- $cur ) )
	      return 0
	    fi
	  elif [[ $URL == */branches/* && $here == */trunk* && \
	        ! $hasReintegrateOpt && $cur = '' && $stat = 'arg' ]] ; then
	    # force --reintegrate only if the current word is empty
	    COMPREPLY=( $(compgen -W '--reintegrate' -- $cur ) )
	    return 0
	  fi
	fi

	# help about option arguments
	if [[ $stat = 'skip' ]]
	then
	    local previous=${COMP_WORDS[COMP_CWORD-1]}
	    local values= dirs= beep= exes=

	    [[ $previous = '--config-dir' ]] && dirs=1

	    # external editor, diff, diff3...
	    [[ $previous = --*-cmd ]] && exes=1

	    [[ $previous = '--native-eol' ]] && values='LF CR CRLF'

	    # just to suggest that a number is expected. hummm.
	    [[ $previous = '--limit' ]] && values='0 1 2 3 4 5 6 7 8 9'

            # some special partial help about --revision option.
	    [[ $previous = '--revision' || $previous = '-r' ]] && \
		values='HEAD BASE PREV COMMITTED 0 {'

	    [[ $previous = '--encoding' ]] && \
		values="latin1 utf8 $SVN_BASH_ENCODINGS"

	    [[ $previous = '--extensions' || $previous = '-x' ]] && \
		values="--unified --ignore-space-change \
		   --ignore-all-space --ignore-eol-style --show-c-functions"

	    [[ $previous = '--depth' ]] && \
		values='empty files immediates infinity'

	    [[ $previous = '--set-depth' ]] && \
		values='empty exclude files immediates infinity'

	    [[ $previous = '--accept' ]] && \
	    {
	        # the list is different for 'resolve'
                if [[ $cmd = 'resolve' ]] ; then
		    # from svn help resolve
		    values='base working mine-full theirs-full'
		else # checkout merge switch update
		    values="postpone base mine-full theirs-full edit launch \
			mine-conflict theirs-conflict"
		fi
	    }

	    [[ $previous = '--show-revs' ]] && values='merged eligible'

	    if [[ $previous = '--username' ]] ; then
	      values="$SVN_BASH_USERNAME"
	      if [[ $SVN_BASH_COMPL_EXT == *username* ]] ; then
		local file=
		# digest? others?
		for file in ~/.subversion/auth/svn.simple/* ; do
		  if [ -r $file ] ; then
		    values="$values $(_svn_read_hashfile username < $file)"
		  fi
		done
	      fi
	      [[ ! "$values" ]] && beep=1
	    fi

	    # could look at ~/.subversion/ ?
	    # hmmm... this option should not exist
	    [[ $previous = '--password' ]] && beep=1

	    # TODO: provide help about other options such as:
	    # --old --new --with-revprop

	    # if the previous option required a parameter, do something
	    # or fallback on ordinary filename expansion
	    [[ $values ]] && COMPREPLY=( $( compgen -W "$values" -- $cur ) )
	    [[ $dirs ]] && COMPREPLY=( $( compgen -o dirnames -- $cur ) )
	    [[ $exes ]] && COMPREPLY=( $( compgen -c -- $cur ) )
	    [[ $beep ]] &&
	    {
		# 'no known completion'. hummm.
		echo -en "\a"
		COMPREPLY=( '' )
	    }
	    return 0
	fi

	# provide allowed property names after property commands
	if [[ $isPropCmd && ( ! $prop || $stat = 'prop' ) && $cur != -* ]]
	then
	    #
	    # Ok, this part is pretty ugly.
	    #
	    # The issue is that ":" is a completion word separator,
	    # which is a good idea for file:// urls but not within
	    # property names...
	    #
	    # The first idea was to remove locally ":" from COMP_WORDBREAKS
	    # and then put it back in all cases but in property name
	    # completion.  It does not always work.  There is a strange bug
	    # where one may get "svn:svn:xxx" in some unclear cases.
	    #
	    # Thus the handling is reprogrammed here...
	    # The code assumes that property names look like *:*,
	    # but it also works reasonably well with simple names.
	    #
	    # This hack is broken in bash4... not sure what to do about it,
            # especially while keeping the bash3 compatibility:-(
	    local choices=

	    if [[ $cur == *:* ]]
	    then
		# only suggest/show possible suffixes
		local prefix=${cur%:*} suffix=${cur#*:} c=
		for c in ${allProps[@]} ; do
		    [[ $c == $prefix:* ]] && choices="$choices ${c#*:}"
		done
		# everything will be appended to the prefix because ':' is
		# a separator, so cur is restricted to the suffix part.
		cur=$suffix
	    else
		# only one choice is fine
		COMPREPLY=( $( compgen -W "${allProps[*]}" -- $cur ) )
		[ ${#COMPREPLY[@]} -eq 1 ] && return 0

		# no ':' so only suggest prefixes?
		local seen= n=0 last= c=
		for c in ${allProps[@]%:*} ; do
		    # do not put the same prefix twice...
		    if [[ $c == $cur* && ( ! $seen || $c != @($seen) ) ]]
		    then
			let n++
			last=$c
			choices="$choices $c:"
			if [[ $seen ]]
			then
			    seen="$seen|$c*"
			else
			    seen="$c*"
			fi
		    fi
		done

		# supply two choices to force a partial completion and a beep
		[[ $n -eq 1 ]] && choices="$last:1 $last:2"
	    fi

	    COMPREPLY=( $( compgen -W "$choices" -- $cur ) )
	    return 0
	fi

	# force mandatory --revprop option on revision properties
	if [[ $isRevProp && ! $hasRevPropOpt ]]
	then
	    COMPREPLY=( $( compgen -W '--revprop' -- $cur ) )
	    return 0
	fi

	# force mandatory --revision option on revision properties
	if [[ $isRevProp && $hasRevPropOpt && ! $hasRevisionOpt ]]
	then
	    COMPREPLY=( $( compgen -W '--revision' -- $cur ) )
	    return 0
	fi

	# possible completion when setting property values
	if [[ $isPsCmd && $prop && ( ! $val || $stat = 'val' ) ]]
	then
	    # ' is a reminder for an arbitrary value
	    local values="\' --file"
	    case $prop in
		svn:keywords)
		    # just a subset?
		    values="Id Rev URL Date Author Header \' $SVN_BASH_KEYWORDS"
		    ;;
		svn:executable|svn:needs-lock)
		    # hmmm... canonical value * is special to the shell.
		    values='\\*'
		    ;;
		svn:eol-style)
		    values='native LF CR CRLF'
		    ;;
		svn:mime-type)
		    # could read /etc/mime.types if available. overkill.
		    values="text/ text/plain text/html text/xml text/rtf
                       image/ image/png image/gif image/jpeg image/tiff
                       audio/ audio/midi audio/mpeg
                       video/ video/mpeg video/mp4
                       application/ application/octet-stream
                       $SVN_BASH_MIME_TYPE"
		    ;;
	    esac

	    COMPREPLY=( $( compgen -W "$values" -- $cur ) )
	    # special case for --file... return even if within an option
	    [[ ${COMPREPLY} ]] && return 0
	fi

	# maximum number of additional arguments expected in various forms
	case $cmd in
	    merge)
		nExpectArgs=3
		;;
	    mergeinfo)
		nExpectArgs=1
		;;
	    copy|cp|move|mv|rename|ren|export|import)
		nExpectArgs=2
		;;
	    switch|sw)
		[[ ! $hasRelocateOpt ]] && nExpectArgs=2
		;;
	    help|h)
		nExpectArgs=0
		;;
	    --version)
		nExpectArgs=0
		;;
	esac

	# the maximum number of arguments is reached for a command
	if [[ $nExpectArgs && $nargs -gt $nExpectArgs ]]
	then
	    # some way to tell 'no completion at all'... is there a better one?
	    # Do not say 'file completion' here.
	    echo -en "\a"
	    COMPREPLY=( '' )
	    return 0
	fi

	# if not typing an option,
	# then fallback on filename expansion...
	if [[ $cur != -* || $stat = 'onlyarg' ]]  ; then

	    # do we allow possible expensive completion here?
	    if [[ $SVN_BASH_COMPL_EXT == *svnstatus* ]] ; then

		# build status command and options
		# "--quiet" removes 'unknown' files
		local status='svn status --non-interactive'

		[[ $SVN_BASH_COMPL_EXT == *recurse* ]] || \
		    status="$status --non-recursive"

		# I'm not sure that it can work with externals in call cases
		# the output contains translatable sentences (even with quiet)
		[[ $SVN_BASH_COMPL_EXT == *externals* ]] || \
		    status="$status --ignore-externals"

		local cs= files=
		# subtlety: must not set $cur* if $cur is empty in some cases
		[[ $cur ]] && cs=$cur*

		# 'files' is set according to the current subcommand
		case $cmd in
		    st*) # status completion must include all files
			files=$cur*
			;;
		    ci|commit|revert|di*) # anything edited
			files=$($status $cs| _svn_grcut '@([MADR!]*| M*|_M*)')
			;;
		    add) # unknown files
			files=$($status $cs| _svn_grcut '\?*')
			;;
		    unlock) # unlock locked files
			files=$($status $cs| _svn_grcut '@(??L*|?????[KOTB]*)')
			;;
		    resolve*) # files in conflict
			files=$($status $cs| _svn_grcut '@(?C*|C*)')
			;;
		    praise|blame|ann*) # any svn file but added
			files=$( _svn_lls all $cur* )
			;;
		    p*) # prop commands
			if [[ $cmd == @($propCmds) && \
			      $prop == @(svn:ignore|svn:externals) ]] ; then
			    # directory specific props
			    files=$( _svn_lls dir . $cur* )
			else
			    # ??? added directories appear twice: foo foo/
			    files="$( _svn_lls all $cur* )
                                   $($status $cs | _svn_grcut 'A*' )"
			fi
			;;
		    info) # information on any file
			files="$( _svn_lls all $cur* )
                               $($status $cs | _svn_grcut 'A*' )"
			;;
		    remove|rm|del*|move|mv|rename) # changing existing files
			files=$( _svn_lls all $cur* )
			;;
		    mkdir) # completion in mkdir can only be for subdirs?
			files=$( _svn_lls dir $cur* )
			;;
		    log|lock|up*|cl*|switch) # misc, all but added files
			files=$( _svn_lls all $cur* )
			;;
		    merge) # may do a better job? URL/WCPATH
			files=$( _svn_lls all $cur* )
			;;
		    ls|list) # better job? what about URLs?
			files=$( _svn_lls all $cur* )
			;;
		    *) # other commands: changelist export import cat mergeinfo
			local fallback=1
			;;
		esac

		# when not recursive, some relevant files may exist
		# within subdirectories, so they are added here.
		# should it be restricted to svn-managed subdirs? no??
		if [[ $SVN_BASH_COMPL_EXT != *recurse* ]] ; then
		    files="$files $( _svn_lls dir $cur* )"
		fi

		# set completion depending on computed 'files'
		if [[ $files ]] ; then
		    COMPREPLY=( $( compgen -W "$files" -- $cur ) )
		    # if empty, set to nope?
		    [[ "${COMPREPLY[*]}" ]] || COMPREPLY=( '' )
		elif [[ ! $fallback ]] ; then
		    # this suggests no completion...
		    echo -en "\a"
		    COMPREPLY=( '' )
		fi
	    fi
	    # else fallback to ordinary filename completion...
	    return 0
	fi

	# otherwise build possible options for the command
	pOpts="--username --password --no-auth-cache --non-interactive \
	       --trust-server-cert-failures \
	       --force-interactive"
	mOpts="-m --message -F --file --encoding --force-log --with-revprop"
	rOpts="-r --revision"
	qOpts="-q --quiet"
	nOpts="-N --non-recursive --depth"
	gOpts="-g --use-merge-history"
	cOpts="--cl --changelist"

	cmdOpts=
	case $cmd in
	--version)
		cmdOpts="$qOpts"
		;;
	add)
		cmdOpts="--auto-props --no-auto-props --force --targets \
		         --no-ignore --parents $nOpts $qOpts $pOpts"
		;;
	auth)
		cmdOpts="--remove --show-passwords $pOpts"
		;;
	blame|annotate|ann|praise)
		cmdOpts="$rOpts $pOpts -v --verbose --incremental --xml \
		         -x --extensions --force $gOpts"
		;;
	cat)
		cmdOpts="$rOpts $pOpts --ignore-keywords"
		;;
	changelist|cl)
		cmdOpts="--targets $pOpts $qOpts $cOpts \
                         -R --recursive --depth --remove"
		;;
	checkout|co)
		cmdOpts="$rOpts $qOpts $nOpts $pOpts --ignore-externals \
                         --force"
		;;
	cleanup)
		cmdOpts="--diff3-cmd $pOpts --include-externals -q --quiet\
			--remove-ignored --remove-unversioned"
		;;
	commit|ci)
		cmdOpts="$mOpts $qOpts $nOpts --targets --editor-cmd $pOpts \
		         --no-unlock $cOpts --keep-changelists \
		         --include-externals"
		;;
	copy|cp)
		cmdOpts="$mOpts $rOpts $qOpts --editor-cmd $pOpts --parents \
		         --ignore-externals --pin-externals"
		;;
	delete|del|remove|rm)
		cmdOpts="--force $mOpts $qOpts --targets --editor-cmd $pOpts \
                         --keep-local"
		;;
	diff|di)
		cmdOpts="$rOpts -x --extensions --diff-cmd --no-diff-deleted \
		         $nOpts $pOpts --force --old --new --notice-ancestry \
		         -c --change --summarize $cOpts --xml --git \
		         --internal-diff --show-copies-as-adds \
		         --ignore-properties --properties-only --no-diff-added \
		         --patch-compatible"
		;;
	export)
		cmdOpts="$rOpts $qOpts $pOpts $nOpts --force --native-eol \
                         --ignore-externals --ignore-keywords"
		;;
	help|h|\?)
		cmdOpts=
		;;
	import)
		cmdOpts="--auto-props --no-auto-props $mOpts $qOpts $nOpts \
		         --no-ignore --editor-cmd $pOpts --force"
		;;
	info)
		cmdOpts="$pOpts $rOpts --targets -R --recursive --depth \
                         --include-externals --incremental --xml \
                         --show-item --no-newline $cOpts"
		;;
	list|ls)
		cmdOpts="$rOpts -v --verbose -R --recursive $pOpts \
                         --incremental --xml --depth --include-externals"
		;;
	lock)
		cmdOpts="-m --message -F --file --encoding --force-log \
                         --targets --force $pOpts"
		;;
	log)
		cmdOpts="$rOpts -v --verbose --targets $pOpts --stop-on-copy \
		         --incremental --xml $qOpts -l --limit -c --change \
                         $gOpts --with-all-revprops --with-revprop --depth \
		         --diff --diff-cmd -x --extensions --internal-diff \
		         --with-no-revprops --search --search-and"
		;;
	merge)
		cmdOpts="$rOpts $nOpts $qOpts --force --dry-run --diff3-cmd \
		         $pOpts --ignore-ancestry -c --change -x --extensions \
                         --record-only --accept \
		         --allow-mixed-revisions -v --verbose"
		;;
	mergeinfo)
	        cmdOpts="$rOpts $pOpts --depth --show-revs -R --recursive \
		         $qOpts -v --verbose --incremental --log"
		;;
	mkdir)
		cmdOpts="$mOpts $qOpts --editor-cmd $pOpts --parents"
		;;
	move|mv|rename|ren)
		cmdOpts="$mOpts $rOpts $qOpts --force --editor-cmd $pOpts \
                         --parents --allow-mixed-revisions"
		;;
	patch)
		cmdOpts="$qOpts $pOpts --dry-run --ignore-whitespace \
			--reverse-diff --strip"
		;;
	propdel|pdel|pd)
		cmdOpts="$qOpts -R --recursive $rOpts $pOpts $cOpts \
                         --depth"
		[[ $isRevProp || ! $prop ]] && cmdOpts="$cmdOpts --revprop"
		;;
	propedit|pedit|pe)
		cmdOpts="--editor-cmd $pOpts $mOpts --force"
		[[ $isRevProp || ! $prop ]] && \
		    cmdOpts="$cmdOpts --revprop $rOpts"
		;;
	propget|pget|pg)
	        cmdOpts="-v --verbose -R --recursive $rOpts --no-newline \
		         $pOpts $cOpts --depth --xml --show-inherited-props"
		[[ $isRevProp || ! $prop ]] && cmdOpts="$cmdOpts --revprop"
		;;
	proplist|plist|pl)
		cmdOpts="-v --verbose -R --recursive $rOpts --revprop $qOpts \
		         $pOpts $cOpts --depth --xml --show-inherited-props"
		;;
	propset|pset|ps)
		cmdOpts="$qOpts --targets -R --recursive \
		         --encoding $pOpts --force $cOpts --depth"
		[[ $isRevProp || ! $prop ]] && \
		    cmdOpts="$cmdOpts --revprop $rOpts"
		[[ $val ]] || cmdOpts="$cmdOpts -F --file"
		;;
        relocate)
		cmdOpts="--ignore-externals $pOpts"
		;;
        resolve)
                cmdOpts="--targets -R --recursive $qOpts $pOpts --accept \
                         --depth"
                ;;
	resolved)
		cmdOpts="--targets -R --recursive $qOpts $pOpts --depth"
		;;
	revert)
		cmdOpts="--targets -R --recursive $qOpts $cOpts \
                         --depth $pOpts"
		;;
	status|stat|st)
		cmdOpts="-u --show-updates -v --verbose $nOpts $qOpts $pOpts \
		         --no-ignore --ignore-externals --incremental --xml \
                         $rOpts $cOpts"
		;;
	switch|sw)
		cmdOpts="--relocate $rOpts $nOpts $qOpts $pOpts --diff3-cmd \
                         --force --accept --ignore-externals --set-depth \
		         --ignore-ancestry"
		;;
	unlock)
		cmdOpts="--targets --force $pOpts"
		;;
	update|up)
		cmdOpts="$rOpts $nOpts $qOpts $pOpts --diff3-cmd \
                         --ignore-externals --force --accept $cOpts \
                         --parents --editor-cmd --set-depth"
		;;
	upgrade)
		cmdOpts="$qOpts $pOpts"
		;;
	*)
		;;
	esac

	# add options that are nearly always available
	[[ "$cmd" != "--version" ]] && cmdOpts="$cmdOpts $helpOpts"
	cmdOpts="$cmdOpts --config-dir --config-option"

        # --accept (edit|launch) incompatible with --non-interactive
	if [[ $acceptOpt == @(edit|launch) ]] ;
	then
	    cmdOpts=${cmdOpts/ --non-interactive / }
	fi

	# take out options already given
	for opt in $options
	do
		local optBase

		# remove leading dashes and arguments
		case $opt in
		--*)    optBase=${opt/=*/} ;;
		-*)     optBase=${opt:0:2} ;;
		esac

		cmdOpts=" $cmdOpts "
		cmdOpts=${cmdOpts/ ${optBase} / }

		# take out alternatives and mutually exclusives
		case $optBase in
		-v)              cmdOpts=${cmdOpts/ --verbose / } ;;
		--verbose)       cmdOpts=${cmdOpts/ -v / } ;;
		-N)              cmdOpts=${cmdOpts/ --non-recursive / } ;;
		--non-recursive) cmdOpts=${cmdOpts/ -N / } ;;
		-R)              cmdOpts=${cmdOpts/ --recursive / } ;;
		--recursive)     cmdOpts=${cmdOpts/ -R / } ;;
		-x)              cmdOpts=${cmdOpts/ --extensions / } ;;
		--extensions)    cmdOpts=${cmdOpts/ -x / } ;;
		-q)              cmdOpts=${cmdOpts/ --quiet / } ;;
		--quiet)         cmdOpts=${cmdOpts/ -q / } ;;
		-h)              cmdOpts=${cmdOpts/ --help / } ;;
		--help)          cmdOpts=${cmdOpts/ -h / } ;;
		-l)              cmdOpts=${cmdOpts/ --limit / } ;;
		--limit)         cmdOpts=${cmdOpts/ -l / } ;;
		-r)              cmdOpts=${cmdOpts/ --revision / } ;;
		--revision)      cmdOpts=${cmdOpts/ -r / } ;;
		-c)              cmdOpts=${cmdOpts/ --change / } ;;
		--change)        cmdOpts=${cmdOpts/ -c / } ;;
		--auto-props)    cmdOpts=${cmdOpts/ --no-auto-props / } ;;
		--no-auto-props) cmdOpts=${cmdOpts/ --auto-props / } ;;
		-g)              cmdOpts=${cmdOpts/ --use-merge-history / } ;;
		--use-merge-history)
                                 cmdOpts=${cmdOpts/ -g / } ;;
		-m|--message|-F|--file)
			cmdOpts=${cmdOpts/ --message / }
			cmdOpts=${cmdOpts/ -m / }
			cmdOpts=${cmdOpts/ --file / }
			cmdOpts=${cmdOpts/ -F / }
			;;
		esac

		# remove help options within help subcommand
		if [ $isHelpCmd ] ; then
		    cmdOpts=${cmdOpts/ -h / }
		    cmdOpts=${cmdOpts/ --help / }
		fi
	done

	# provide help about available options
	COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) )
	return 0
}
complete -F _svn -o default -X '@(*/.svn|*/.svn/|.svn|.svn/)' svn

_svnadmin ()
{
	local cur cmds cmdOpts optsParam opt helpCmds optBase i

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	# Possible expansions, without pure-prefix abbreviations such as "h".
	cmds='crashtest create delrevprop deltify dump freeze help hotcopy \
	      info list-dblogs \
	      list-unused-dblogs load lock lslocks lstxns pack recover rmlocks \
	      rmtxns setlog setrevprop setuuid unlock upgrade verify --version'

	if [[ $COMP_CWORD -eq 1 ]] ; then
		COMPREPLY=( $( compgen -W "$cmds" -- $cur ) )
		return 0
	fi

	# options that require a parameter
	# note: continued lines must end '|' continuing lines must start '|'
	optsParam="-r|--revision|--parent-dir|--fs-type|-M|--memory-cache-size"
	optsParam="$optsParam|-F|--file"

	# if not typing an option, or if the previous option required a
	# parameter, then fallback on ordinary filename expansion
	helpCmds='help|--help|h|\?'
	if [[ ${COMP_WORDS[1]} != @($helpCmds) ]] && \
	   [[ "$cur" != -* ]] || \
	   [[ ${COMP_WORDS[COMP_CWORD-1]} == @($optsParam) ]] ; then
		return 0
	fi

	cmdOpts=
	case ${COMP_WORDS[1]} in
	create)
		cmdOpts="--bdb-txn-nosync --bdb-log-keep --config-dir \
		         --fs-type --pre-1.4-compatible --pre-1.5-compatible \
		         --pre-1.6-compatible --compatible-version"
		;;
	deltify)
		cmdOpts="-r --revision -q --quiet"
		;;
	dump)
		cmdOpts="-r --revision --incremental -q --quiet --deltas \
		         -M --memory-cache-size"
		;;
	freeze)
		cmdOpts="-F --file"
		;;
	help|h|\?)
		cmdOpts="$cmds"
		;;
	hotcopy)
		cmdOpts="--clean-logs"
		;;
	load)
		cmdOpts="--ignore-uuid --force-uuid --parent-dir -q --quiet \
		         --use-pre-commit-hook --use-post-commit-hook \
		         --bypass-prop-validation -M --memory-cache-size"
		;;
	lock|unlock)
		cmdOpts="--bypass-hooks"
		;;
	recover)
		cmdOpts="--wait"
		;;
	rmtxns)
		cmdOpts="-q --quiet"
		;;
	setlog)
		cmdOpts="-r --revision --bypass-hooks"
		;;
	setrevprop|delrevprop)
		cmdOpts="-r --revision -t --transaction \
		         --use-pre-revprop-change-hook \
		         --use-post-revprop-change-hook"
		;;
	verify)
		cmdOpts="-r --revision -q --quiet"
		;;
	*)
		;;
	esac

	cmdOpts="$cmdOpts --help -h"

	# take out options already given
	for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do
		opt=${COMP_WORDS[$i]}

		case $opt in
		--*)    optBase=${opt/=*/} ;;
		-*)     optBase=${opt:0:2} ;;
		esac

		cmdOpts=" $cmdOpts "
		cmdOpts=${cmdOpts/ ${optBase} / }

		# take out alternatives
		case $optBase in
		-q)              cmdOpts=${cmdOpts/ --quiet / } ;;
		--quiet)         cmdOpts=${cmdOpts/ -q / } ;;
		-h)              cmdOpts=${cmdOpts/ --help / } ;;
		--help)          cmdOpts=${cmdOpts/ -h / } ;;
		-r)              cmdOpts=${cmdOpts/ --revision / } ;;
		--revision)      cmdOpts=${cmdOpts/ -r / } ;;
		-t)              cmdOpts=${cmdOpts/ --transaction / } ;;
		--transaction)   cmdOpts=${cmdOpts/ -t / } ;;
		-F)              cmdOpts=${cmdOpts/ --file / } ;;
		--file)          cmdOpts=${cmdOpts/ -F / } ;;
		-M)              cmdOpts=${cmdOpts/ --memory-cache-size / } ;;
		--memory-cache-size) cmdOpts=${cmdOpts/ --M / } ;;
		esac

		# skip next option if this one requires a parameter
		if [[ $opt == @($optsParam) ]] ; then
			((++i))
		fi
	done

	COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) )

	return 0
}
complete -F _svnadmin -o default svnadmin

_svndumpfilter ()
{
	local cur cmds cmdOpts optsParam opt helpCmds optBase i

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	# Possible expansions, without pure-prefix abbreviations such as "h".
	cmds='exclude help include --version'

	if [[ $COMP_CWORD -eq 1 ]] ; then
		COMPREPLY=( $( compgen -W "$cmds" -- $cur ) )
		return 0
	fi

	# options that require a parameter
	# note: continued lines must end '|' continuing lines must start '|'
	optsParam="--targets"

	# if not typing an option, or if the previous option required a
	# parameter, then fallback on ordinary filename expansion
	helpCmds='help|--help|h|\?'
	if [[ ${COMP_WORDS[1]} != @($helpCmds) ]] && \
	   [[ "$cur" != -* ]] || \
	   [[ ${COMP_WORDS[COMP_CWORD-1]} == @($optsParam) ]] ; then
		return 0
	fi

	cmdOpts=
	case ${COMP_WORDS[1]} in
	exclude|include)
		cmdOpts="--drop-empty-revs --renumber-revs
		         --skip-missing-merge-sources --targets
		         --preserve-revprops --quiet"
		;;
	help|h|\?)
		cmdOpts="$cmds"
		;;
	*)
		;;
	esac

	cmdOpts="$cmdOpts --help -h"

	# take out options already given
	for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do
		opt=${COMP_WORDS[$i]}

		case $opt in
		--*)    optBase=${opt/=*/} ;;
		-*)     optBase=${opt:0:2} ;;
		esac

		cmdOpts=" $cmdOpts "
		cmdOpts=${cmdOpts/ ${optBase} / }

		# take out alternatives
		case $optBase in
		-h)              cmdOpts=${cmdOpts/ --help / } ;;
		--help)          cmdOpts=${cmdOpts/ -h / } ;;
		esac

		# skip next option if this one requires a parameter
		if [[ $opt == @($optsParam) ]] ; then
			((++i))
		fi
	done

	COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) )

	return 0
}
complete -F _svndumpfilter -o default svndumpfilter

_svnlook ()
{
	local cur cmds cmdOpts optsParam opt helpCmds optBase i

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	# Possible expansions, without pure-prefix abbreviations such as "h".
	cmds='author cat changed date diff dirs-changed filesize help history \
	      info lock log propget proplist tree uuid youngest --version'

	if [[ $COMP_CWORD -eq 1 ]] ; then
		COMPREPLY=( $( compgen -W "$cmds" -- $cur ) )
		return 0
	fi

	# options that require a parameter
	# note: continued lines must end '|' continuing lines must start '|'
	optsParam="-r|--revision|-t|--transaction|-l|--limit|-x|--extensions"

	# if not typing an option, or if the previous option required a
	# parameter, then fallback on ordinary filename expansion
	helpCmds='help|--help|h|\?'
	if [[ ${COMP_WORDS[1]} != @($helpCmds) ]] && \
	   [[ "$cur" != -* ]] || \
	   [[ ${COMP_WORDS[COMP_CWORD-1]} == @($optsParam) ]] ; then
		return 0
	fi

	cmdOpts=
	case ${COMP_WORDS[1]} in
	author)
		cmdOpts="-r --revision -t --transaction"
		;;
	cat)
		cmdOpts="-r --revision -t --transaction"
		;;
	changed)
		cmdOpts="-r --revision -t --transaction --copy-info"
		;;
	date)
		cmdOpts="-r --revision -t --transaction"
		;;
	diff)
		cmdOpts="-r --revision -t --transaction --diff-copy-from \
		         --no-diff-added --no-diff-deleted -x --extensions"
		;;
	dirs-changed)
		cmdOpts="-r --revision -t --transaction"
		;;
	filesize)
		cmdOpts="-r --revision -t --transaction"
		;;
	help|h|\?)
		cmdOpts="$cmds"
		;;
	history)
		cmdOpts="-r --revision -l --limit --show-ids"
		;;
	info)
		cmdOpts="-r --revision -t --transaction"
		;;
	lock)
		cmdOpts=
		;;
	log)
		cmdOpts="-r --revision -t --transaction"
		;;
	propget|pget|pg)
		cmdOpts="-r --revision -t --transaction --revprop"
		;;
	proplist|plist|pl)
		cmdOpts="-r --revision -t --transaction --revprop -v --verbose --xml"
		;;
	tree)
		cmdOpts="-r --revision -t --transaction --full-paths -N --non-recursive --show-ids"
		;;
	uuid)
		cmdOpts=
		;;
	youngest)
		cmdOpts=
		;;
	*)
		;;
	esac

	cmdOpts="$cmdOpts --help -h"

	# take out options already given
	for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do
		opt=${COMP_WORDS[$i]}

		case $opt in
		--*)    optBase=${opt/=*/} ;;
		-*)     optBase=${opt:0:2} ;;
		esac

		cmdOpts=" $cmdOpts "
		cmdOpts=${cmdOpts/ ${optBase} / }

		# take out alternatives
		case $optBase in
		-N)              cmdOpts=${cmdOpts/ --non-recursive / } ;;
		--non-recursive) cmdOpts=${cmdOpts/ -N / } ;;
		-h)              cmdOpts=${cmdOpts/ --help / } ;;
		--help)          cmdOpts=${cmdOpts/ -h / } ;;
		-l)              cmdOpts=${cmdOpts/ --limit / } ;;
		--limit)         cmdOpts=${cmdOpts/ -l / } ;;
		-r)              cmdOpts=${cmdOpts/ --revision / } ;;
		--revision)      cmdOpts=${cmdOpts/ -r / } ;;
		-t)              cmdOpts=${cmdOpts/ --transaction / } ;;
		--transaction)   cmdOpts=${cmdOpts/ -t / } ;;
		-v)              cmdOpts=${cmdOpts/ --verbose / } ;;
		--verbose)       cmdOpts=${cmdOpts/ -v / } ;;
		-x)              cmdOpts=${cmdOpts/ --extensions / } ;;
		--extensions)    cmdOpts=${cmdOpts/ -x / } ;;
		esac

		# skip next option if this one requires a parameter
		if [[ $opt == @($optsParam) ]] ; then
			((++i))
		fi
	done

	COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) )

	return 0
}
complete -F _svnlook -o default svnlook

_svnsync ()
{
	local cur cmds cmdOpts optsParam opt helpCmds optBase i

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}

	# Possible expansions, without pure-prefix abbreviations such as "h".
	cmds='copy-revprops help info initialize synchronize --version'

	if [[ $COMP_CWORD -eq 1 ]] ; then
		COMPREPLY=( $( compgen -W "$cmds" -- $cur ) )
		return 0
	fi

	# options that require a parameter
	# note: continued lines must end '|' continuing lines must start '|'
	optsParam="--config-dir|--config-option|--source-username|--source-password"
	optsParam="$optsParam|--sync-username|--sync-password"

	# if not typing an option, or if the previous option required a
	# parameter, then fallback on ordinary filename expansion
	helpCmds='help|--help|h|\?'
	if [[ ${COMP_WORDS[1]} != @($helpCmds) ]] && \
	   [[ "$cur" != -* ]] || \
	   [[ ${COMP_WORDS[COMP_CWORD-1]} == @($optsParam) ]] ; then
		return 0
	fi

	cmdOpts=
	case ${COMP_WORDS[1]} in
	copy-revprops|initialize|init|synchronize|sync)
		cmdOpts="--non-interactive --no-auth-cache --trust-server-cert \
		         --source-username --source-password --sync-username \
		         --sync-password --config-dir --config-option \
		         -q --quiet -M --memory-cache-size"
		;;
	help|h|\?)
		cmdOpts="$cmds"
		;;
	info)
		cmdOpts="--non-interactive --no-auth-cache --trust-server-cert \
		         --source-username --source-password --sync-username \
		         --sync-password --config-dir --config-option"
		;;
	*)
		;;
	esac

	cmdOpts="$cmdOpts --help -h"

	# take out options already given
	for (( i=2; i<=$COMP_CWORD-1; ++i )) ; do
		opt=${COMP_WORDS[$i]}

		case $opt in
		--*)    optBase=${opt/=*/} ;;
		-*)     optBase=${opt:0:2} ;;
		esac

		cmdOpts=" $cmdOpts "
		cmdOpts=${cmdOpts/ ${optBase} / }

		# take out alternatives
		case $optBase in
		-h)              cmdOpts=${cmdOpts/ --help / } ;;
		--help)          cmdOpts=${cmdOpts/ -h / } ;;
		-q)              cmdOpts=${cmdOpts/ --quiet / } ;;
		--quiet)         cmdOpts=${cmdOpts/ -q / } ;;
		esac

		# skip next option if this one requires a parameter
		if [[ $opt == @($optsParam) ]] ; then
			((++i))
		fi
	done

	COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) )

	return 0
}
complete -F _svnsync -o default svnsync

# reasonable completion for 'svnversion'
_svnversion ()
{
	local cmdOpts=" -n --no-newline -c --committed -h --help --version "
	local cur=${COMP_WORDS[COMP_CWORD]}

	COMPREPLY=()

	# parse current options
	local options= wcpath= trailurl= last='none' stat= opt= i=-1 isCur=
	for opt in ${COMP_WORDS[@]}
	do
		[[ $i -eq $COMP_CWORD ]] && stat=$last
		let i++

		# are we processing the current word?
		isCur=
		[[ $i -eq $COMP_CWORD ]] && isCur=1

		# skip first command, should be 'svnversion'
		if [ $last = 'none' ] ; then
			last='first'
			continue
		fi

		# get options
		if [[ $last != 'arg' && $opt == -* ]]
		then
			# if '--' is at the current position, it means that we are looking
			# for '--*' options, and not the end of option processing.
			if [[ $opt = '--' && ! $isCur ]]
			then
				last='arg'
			else
				options="$options $opt "
				last='opt'
			fi
			continue
		fi
		# get arguments
		if [[ $opt != -* ]]
		then
			last='arg'
			if [[ ! $wcpath ]]
			then
				wcpath=$opt
			elif [[ ! $trailurl ]]
			then
				trailurl=$opt
			fi
		fi
	done
	[[ $stat ]] || stat=$last

	# argument part
	if [[ $cur != -* || $stat = 'arg' ]]
	then
		[[ $wcpath && $trailurl ]] && COMPREPLY=( '' )
		return 0
	fi

	# suggest options, and  take out already given options
	for opt in $options
	do
		# take out options
		cmdOpts=${cmdOpts/ $opt / }

		# take out alternatives
		case $opt in
			-n)              cmdOpts=${cmdOpts/ --no-newline / } ;;
			--no-newline)    cmdOpts=${cmdOpts/ -n / } ;;
			-h)              cmdOpts=${cmdOpts/ --help / } ;;
			--help)          cmdOpts=${cmdOpts/ -h / } ;;
			-c)              cmdOpts=${cmdOpts/ --committed / } ;;
			--committed)     cmdOpts=${cmdOpts/ -c / } ;;
		esac
	done

	COMPREPLY=( $( compgen -W "$cmdOpts" -- $cur ) )

	return 0
}
# -X option does not seem to work?
complete -F _svnversion -o dirnames -X '*.svn*' svnversion