Index: src/db.c ================================================================== --- src/db.c +++ src/db.c @@ -2881,16 +2881,20 @@ ** ** Options: ** --global set or unset the given property globally instead of ** setting or unsetting it for the open repository only. ** +** --exact only consider exact name matches. +** ** See also: configuration */ void setting_cmd(void){ int i; int globalFlag = find_option("global","g",0)!=0; + int exactFlag = find_option("exact",0,0)!=0; int unsetFlag = g.argv[1][0]=='u'; + verify_all_options(); db_open_config(1, 0); if( !globalFlag ){ db_find_and_open_repository(OPEN_ANY_SCHEMA | OPEN_OK_NOT_FOUND, 0); } if( !g.repositoryOpen ){ @@ -2916,11 +2920,11 @@ print_setting(&aSetting[i]); } }else if( g.argc==3 || g.argc==4 ){ const char *zName = g.argv[2]; int n = (int)strlen(zName); - const Setting *pSetting = db_find_setting(zName, 1); + const Setting *pSetting = db_find_setting(zName, !exactFlag); if( pSetting==0 ){ fossil_fatal("no such setting: %s", zName); } if( globalFlag && fossil_strcmp(pSetting->name, "manifest")==0 ){ fossil_fatal("cannot set 'manifest' globally"); @@ -2949,11 +2953,16 @@ } if( isManifest && g.localOpen ){ manifest_to_disk(db_lget_int("checkout", 0)); } }else{ - while( pSetting->name && fossil_strncmp(pSetting->name,zName,n)==0 ){ + while( pSetting->name ){ + if( exactFlag ){ + if( fossil_strcmp(pSetting->name,zName)!=0 ) break; + }else{ + if( fossil_strncmp(pSetting->name,zName,n)!=0 ) break; + } print_setting(pSetting); pSetting++; } } }else{ ADDED test/settings-repo.test Index: test/settings-repo.test ================================================================== --- /dev/null +++ test/settings-repo.test @@ -0,0 +1,259 @@ +# +# Copyright (c) 2016 D. Richard Hipp +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the Simplified BSD License (also +# known as the "2-Clause License" or "FreeBSD License".) +# +# This program is distributed in the hope that it will be useful, +# but without any warranty; without even the implied warranty of +# merchantability or fitness for a particular purpose. +# +# Author contact information: +# drh@hwaci.com +# http://www.hwaci.com/drh/ +# +############################################################################ +# +# The "settings" and "unset" commands that may modify the repository. +# + +require_no_open_checkout +set dir [file dirname [info script]]; test_setup + +############################################################################### +# +# Complete syntax as tested: +# +# fossil settings ?PROPERTY? ?VALUE? ?OPTIONS? +# fossil unset PROPERTY ?OPTIONS? +# +# Where the only supported options are "--global" and "--exact". +# +############################################################################### + +set all_settings [get_all_settings] + +foreach name $all_settings { + # + # HACK: Make 100% sure that there are no non-default setting values + # present anywhere. + # + fossil unset $name --exact --global + fossil unset $name --exact + + # + # NOTE: Query for the hard-coded default value of this setting and + # save it. + # + fossil test-th-eval "setting $name" + set defaults($name) [normalize_result] +} + +############################################################################### + +fossil settings bad-setting some_value + +test settings-set-bad-local { + [normalize_result] eq "no such setting: bad-setting" +} + +fossil settings bad-setting some_value --global + +test settings-set-bad-global { + [normalize_result] eq "no such setting: bad-setting" +} + +############################################################################### + +fossil unset bad-setting + +test settings-unset-bad-local { + [normalize_result] eq "no such setting: bad-setting" +} + +fossil unset bad-setting --global + +test settings-unset-bad-global { + [normalize_result] eq "no such setting: bad-setting" +} + +############################################################################### + +fossil settings ssl some_value + +test settings-set-ambiguous-local { + [normalize_result] eq + "ambiguous setting \"ssl\" - might be: ssl-ca-location ssl-identity" +} + +fossil settings ssl some_value --global + +test settings-set-ambiguous-global { + [normalize_result] eq + "ambiguous setting \"ssl\" - might be: ssl-ca-location ssl-identity" +} + +############################################################################### + +fossil unset ssl + +test settings-unset-ambiguous-local { + [normalize_result] eq + "ambiguous setting \"ssl\" - might be: ssl-ca-location ssl-identity" +} + +fossil unset ssl --global + +test settings-unset-ambiguous-global { + [normalize_result] eq + "ambiguous setting \"ssl\" - might be: ssl-ca-location ssl-identity" +} + +############################################################################### + +set pattern(1) {^%name%$} +set pattern(3) {^%name%[ ]+\(global\)[ ]+%value%+$} +set pattern(4) {^%name%[ ]+\(local\)[ ]+%value%+$} + +foreach name $all_settings { + if {$name ne "manifest"} { + set value #global_for_$name + fossil settings $name $value --exact --global + set data [normalize_result] + + test settings-set-$name-global { + $data eq "" + } + + fossil settings $name --exact --global + set data [normalize_result] + + test settings-set-check1-$name-global { + [regexp -- [string map \ + [list %name% $name %value% $value] $pattern(3)] $data] + } + + fossil test-th-eval --open-config "setting $name" + set data [normalize_result] + + test settings-set-check2-$name-global { + $data eq $value + } + + fossil unset $name --exact --global + set data [normalize_result] + + test settings-unset-$name-global { + $data eq "" + } + + fossil settings $name --exact --global + set data [normalize_result] + + test settings-unset-check1-$name-global { + [regexp -- [string map \ + [list %name% $name %value% $value] $pattern(1)] $data] + } + + fossil test-th-eval --open-config "setting $name" + set data [normalize_result] + + test settings-unset-check2-$name-global { + $data eq $defaults($name) + } + } + + set value #local_for_$name + fossil settings $name $value --exact + set data [normalize_result] + + test settings-set-$name-local { + $data eq "" + } + + fossil settings $name --exact + set data [normalize_result] + + test settings-set-check1-$name-local { + [regexp -- [string map \ + [list %name% $name %value% $value] $pattern(4)] $data] + } + + fossil test-th-eval --open-config "setting $name" + set data [normalize_result] + + test settings-set-check2-$name-local { + $data eq $value + } + + fossil unset $name --exact + set data [normalize_result] + + test settings-unset-$name-local { + $data eq "" + } + + fossil settings $name --exact + set data [normalize_result] + + test settings-unset-check1-$name-local { + [regexp -- [string map \ + [list %name% $name %value% $value] $pattern(1)] $data] + } + + fossil test-th-eval --open-config "setting $name" + set data [normalize_result] + + test settings-unset-check2-$name-local { + $data eq $defaults($name) + } +} + +############################################################################### + +set pattern(5) \ + {^%name%[ ]+\n \(overridden by contents of file \.fossil-settings/%name%\)$} + +set versionable_settings [get_versionable_settings] +file mkdir .fossil-settings + +foreach name $versionable_settings { + fossil settings $name --exact + set data [normalize_result] + + test settings-before-versionable-$name { + [regexp -- [string map [list %name% $name] $pattern(1)] $data] + } + + set value #versionable_for_$name + set fileName [file join .fossil-settings $name] + write_file $fileName $value + + fossil settings $name --exact + set data [normalize_result] + + test settings-set-check1-versionable-$name { + [regexp -- [string map [list %name% $name] $pattern(5)] $data] + } + + fossil test-th-eval --open-config "setting $name" + set data [normalize_result] + + test settings-set-check2-versionable-$name { + $data eq $value + } + + file delete $fileName + + fossil settings $name --exact + set data [normalize_result] + + test settings-after-versionable-$name { + [regexp -- [string map [list %name% $name] $pattern(1)] $data] + } +} + +############################################################################### + +test_cleanup ADDED test/settings.test Index: test/settings.test ================================================================== --- /dev/null +++ test/settings.test @@ -0,0 +1,128 @@ +# +# Copyright (c) 2016 D. Richard Hipp +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the Simplified BSD License (also +# known as the "2-Clause License" or "FreeBSD License".) +# +# This program is distributed in the hope that it will be useful, +# but without any warranty; without even the implied warranty of +# merchantability or fitness for a particular purpose. +# +# Author contact information: +# drh@hwaci.com +# http://www.hwaci.com/drh/ +# +############################################################################ +# +# The "settings" and "unset" commands. +# + +set dir [file dirname [info script]]; test_setup + +############################################################################### +# +# Complete syntax as tested: +# +# fossil settings ?PROPERTY? ?VALUE? ?OPTIONS? +# fossil unset PROPERTY ?OPTIONS? +# +# Where the only supported options are "--global" and "--exact". +# +############################################################################### +# +# NOTE: The [extract_setting_names] procedure extracts the list of setting +# names from the line-ending normalized output of the "fossil settings" +# command. It assumes that a setting name must begin with a lowercase +# letter. It also assumes that any output lines that start with a +# lowercase letter contain a setting name starting at that same point. +# +proc extract_setting_names { data } { + set names [list] + + foreach {dummy name} [regexp \ + -all -line -inline -- {^([a-z][a-z0-9\-]*) } $data] { + lappend names $name + } + + return $names +} + +############################################################################### + +set all_settings [get_all_settings] + +fossil settings +set local_settings [extract_setting_names [normalize_result_no_trim]] + +fossil settings --global +set global_settings [extract_setting_names [normalize_result_no_trim]] + +foreach name $all_settings { + test settings-have-local-$name { + [lsearch -exact $local_settings $name] != -1 + } + + test settings-have-global-$name { + [lsearch -exact $global_settings $name] != -1 + } +} + +foreach name $local_settings { + test settings-valid-local-$name { + [lsearch -exact $all_settings $name] != -1 + } +} + +foreach name $global_settings { + test settings-valid-global-$name { + [lsearch -exact $all_settings $name] != -1 + } +} + +############################################################################### + +set pattern(1) {^%name%$} +set pattern(2) {^%name%[ ]+\((?:local|global)\)[ ]+[^ ]+$} + +foreach name $all_settings { + fossil settings $name --exact + set data [normalize_result] + + test settings-query-local-$name { + [regexp -- [string map [list %name% $name] $pattern(1)] $data] || + [regexp -- [string map [list %name% $name] $pattern(2)] $data] + } + + fossil settings $name --exact --global + set data [normalize_result] + + if {$name eq "manifest"} { + test settings-query-global-$name { + $data eq "cannot set 'manifest' globally" + } + } else { + test settings-query-global-$name { + [regexp -- [string map [list %name% $name] $pattern(1)] $data] || + [regexp -- [string map [list %name% $name] $pattern(2)] $data] + } + } +} + +############################################################################### + +fossil settings bad-setting + +test settings-query-bad-local { + [normalize_result] eq "no such setting: bad-setting" +} + +fossil settings bad-setting --global + +test settings-query-bad-global { + [normalize_result] eq "no such setting: bad-setting" +} + +############################################################################### + +test_cleanup Index: test/tester.tcl ================================================================== --- test/tester.tcl +++ test/tester.tcl @@ -186,10 +186,122 @@ close $out } proc write_file_indented {filename txt} { write_file $filename [string trim [string map [list "\n " \n] $txt]]\n } + +# Returns the list of all supported versionable settings. +# +proc get_versionable_settings {} { + # + # TODO: If the list of supported versionable settings in "db.c" is modified, + # this list (and procedure) most likely needs to be modified as well. + # + set result [list \ + allow-symlinks \ + binary-glob \ + clean-glob \ + crnl-glob \ + dotfiles \ + empty-dirs \ + encoding-glob \ + ignore-glob \ + keep-glob \ + manifest \ + th1-setup \ + th1-uri-regexp] + + fossil test-th-eval "hasfeature tcl" + + if {$::RESULT eq "1"} { + lappend result tcl-setup + } + + return $result +} + +# Returns the list of all supported settings. +# +proc get_all_settings {} { + # + # TODO: If the list of supported settings in "db.c" is modified, this list + # (and procedure) most likely needs to be modified as well. + # + set result [list \ + access-log \ + admin-log \ + allow-symlinks \ + auto-captcha \ + auto-hyperlink \ + auto-shun \ + autosync \ + autosync-tries \ + binary-glob \ + case-sensitive \ + clean-glob \ + clearsign \ + crnl-glob \ + default-perms \ + diff-binary \ + diff-command \ + dont-push \ + dotfiles \ + editor \ + empty-dirs \ + encoding-glob \ + exec-rel-paths \ + gdiff-command \ + gmerge-command \ + hash-digits \ + http-port \ + https-login \ + ignore-glob \ + keep-glob \ + localauth \ + main-branch \ + manifest \ + max-loadavg \ + max-upload \ + mtime-changes \ + pgp-command \ + proxy \ + relative-paths \ + repo-cksum \ + self-register \ + ssh-command \ + ssl-ca-location \ + ssl-identity \ + th1-setup \ + th1-uri-regexp \ + web-browser] + + fossil test-th-eval "hasfeature legacyMvRm" + + if {$::RESULT eq "1"} { + lappend result mv-rm-files + } + + fossil test-th-eval "hasfeature tcl" + + if {$::RESULT eq "1"} { + lappend result tcl tcl-setup + } + + fossil test-th-eval "hasfeature th1Docs" + + if {$::RESULT eq "1"} { + lappend result th1-docs + } + + fossil test-th-eval "hasfeature th1Hooks" + + if {$::RESULT eq "1"} { + lappend result th1-hooks + } + + return [lsort -dictionary $result] +} # Return true if two files are the same # proc same_file {a b} { set x [read_file $a] @@ -655,10 +767,15 @@ # fixup the whitespace in the result to make it easier to compare. proc normalize_result {} { return [string map [list \r\n \n] [string trim $::RESULT]] } + +# fixup the line-endings in the result to make it easier to compare. +proc normalize_result_no_trim {} { + return [string map [list \r\n \n] $::RESULT] +} # returns the first line of the normalized result. proc first_data_line {} { return [lindex [split [normalize_result] \n] 0] }