diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index e7dbb8e8f..122052e55 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -15,10 +15,6 @@ "Comment": "null-81", "Rev": "9cbe983aed9b0dfc73954433fead5e00866342ac" }, - { - "ImportPath": "github.com/calmh/ini", - "Rev": "386c4240a9684d91d9ec4d93651909b49c7269e1" - }, { "ImportPath": "github.com/codegangsta/inject", "Rev": "9aea7a2fa5b79ef7fc00f63a575e72df33b4e886" diff --git a/Godeps/_workspace/src/github.com/calmh/ini/LICENSE b/Godeps/_workspace/src/github.com/calmh/ini/LICENSE deleted file mode 100644 index fa5b4e205..000000000 --- a/Godeps/_workspace/src/github.com/calmh/ini/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2013 Jakob Borg - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -- The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Godeps/_workspace/src/github.com/calmh/ini/README.md b/Godeps/_workspace/src/github.com/calmh/ini/README.md deleted file mode 100644 index 35791d76b..000000000 --- a/Godeps/_workspace/src/github.com/calmh/ini/README.md +++ /dev/null @@ -1,39 +0,0 @@ -ini [![Build Status](https://drone.io/github.com/calmh/ini/status.png)](https://drone.io/github.com/calmh/ini/latest) -=== - -Yet another .INI file parser / writer. Created because the existing ones -were either not general enough (allowing easy access to all parts of the -original file) or made annoying assumptions about the format. And -probably equal parts NIH. You might want to just write your own instead -of using this one, you know that's where you'll end up in the end -anyhow. - -Documentation -------------- - -http://godoc.org/github.com/calmh/ini - -Example -------- - -```go -fd, _ := os.Open("foo.ini") -cfg := ini.Parse(fd) -fd.Close() - -val := cfg.Get("general", "foo") -cfg.Set("general", "bar", "baz") - -fd, _ = os.Create("bar.ini") -err := cfg.Write(fd) -if err != nil { - // ... -} -err = fd.Close() - -``` - -License -------- - -MIT diff --git a/Godeps/_workspace/src/github.com/calmh/ini/ini.go b/Godeps/_workspace/src/github.com/calmh/ini/ini.go deleted file mode 100644 index 280b6d935..000000000 --- a/Godeps/_workspace/src/github.com/calmh/ini/ini.go +++ /dev/null @@ -1,235 +0,0 @@ -// Package ini provides trivial parsing of .INI format files. -package ini - -import ( - "bufio" - "fmt" - "io" - "regexp" - "strconv" - "strings" -) - -// Config is a parsed INI format file. -type Config struct { - sections []section - comments []string -} - -type section struct { - name string - comments []string - options []option -} - -type option struct { - name, value string -} - -var ( - iniSectionRe = regexp.MustCompile(`^\[(.+)\]$`) - iniOptionRe = regexp.MustCompile(`^([^\s=]+)\s*=\s*(.+?)$`) -) - -// Sections returns the list of sections in the file. -func (c *Config) Sections() []string { - var sections []string - for _, sect := range c.sections { - sections = append(sections, sect.name) - } - return sections -} - -// Options returns the list of options in a given section. -func (c *Config) Options(section string) []string { - var options []string - for _, sect := range c.sections { - if sect.name == section { - for _, opt := range sect.options { - options = append(options, opt.name) - } - break - } - } - return options -} - -// OptionMap returns the map option => value for a given section. -func (c *Config) OptionMap(section string) map[string]string { - options := make(map[string]string) - for _, sect := range c.sections { - if sect.name == section { - for _, opt := range sect.options { - options[opt.name] = opt.value - } - break - } - } - return options -} - -// Comments returns the list of comments in a given section. -// For the empty string, returns the file comments. -func (c *Config) Comments(section string) []string { - if section == "" { - return c.comments - } - for _, sect := range c.sections { - if sect.name == section { - return sect.comments - } - } - return nil -} - -// AddComments appends the comment to the list of comments for the section. -func (c *Config) AddComment(sect, comment string) { - if sect == "" { - c.comments = append(c.comments, comment) - return - } - - for i, s := range c.sections { - if s.name == sect { - c.sections[i].comments = append(s.comments, comment) - return - } - } - - c.sections = append(c.sections, section{ - name: sect, - comments: []string{comment}, - }) -} - -// Parse reads the given io.Reader and returns a parsed Config object. -func Parse(stream io.Reader) Config { - var cfg Config - var curSection string - - scanner := bufio.NewScanner(bufio.NewReader(stream)) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") { - comment := strings.TrimLeft(line, ";# ") - cfg.AddComment(curSection, comment) - } else if len(line) > 0 { - if m := iniSectionRe.FindStringSubmatch(line); len(m) > 0 { - curSection = m[1] - } else if m := iniOptionRe.FindStringSubmatch(line); len(m) > 0 { - key := m[1] - val := m[2] - if !strings.Contains(val, "\"") { - // If val does not contain any quote characers, we can make it - // a quoted string and safely let strconv.Unquote sort out any - // escapes - val = "\"" + val + "\"" - } - if val[0] == '"' { - val, _ = strconv.Unquote(val) - } - - cfg.Set(curSection, key, val) - } - } - } - return cfg -} - -// Write writes the sections and options to the io.Writer in INI format. -func (c *Config) Write(out io.Writer) error { - for _, cmt := range c.comments { - fmt.Fprintln(out, "; "+cmt) - } - if len(c.comments) > 0 { - fmt.Fprintln(out) - } - - for _, sect := range c.sections { - fmt.Fprintf(out, "[%s]\n", sect.name) - for _, cmt := range sect.comments { - fmt.Fprintln(out, "; "+cmt) - } - for _, opt := range sect.options { - val := opt.value - if len(val) == 0 { - continue - } - - // Quote the string if it begins or ends with space - needsQuoting := val[0] == ' ' || val[len(val)-1] == ' ' - - if !needsQuoting { - // Quote the string if it contains any unprintable characters - for _, r := range val { - if !strconv.IsPrint(r) { - needsQuoting = true - break - } - } - } - - if needsQuoting { - val = strconv.Quote(val) - } - - fmt.Fprintf(out, "%s=%s\n", opt.name, val) - } - fmt.Fprintln(out) - } - return nil -} - -// Get gets the value from the specified section and key name, or the empty -// string if either the section or the key is missing. -func (c *Config) Get(section, key string) string { - for _, sect := range c.sections { - if sect.name == section { - for _, opt := range sect.options { - if opt.name == key { - return opt.value - } - } - return "" - } - } - return "" -} - -// Set sets a value for an option in a section. If the option exists, it's -// value will be overwritten. If the option does not exist, it will be added. -// If the section does not exist, it will be added and the option added to it. -func (c *Config) Set(sectionName, key, value string) { - for i, sect := range c.sections { - if sect.name == sectionName { - for j, opt := range sect.options { - if opt.name == key { - c.sections[i].options[j].value = value - return - } - } - c.sections[i].options = append(sect.options, option{key, value}) - return - } - } - - c.sections = append(c.sections, section{ - name: sectionName, - options: []option{{key, value}}, - }) -} - -// Delete removes the option from the specified section. -func (c *Config) Delete(section, key string) { - for sn, sect := range c.sections { - if sect.name == section { - for i, opt := range sect.options { - if opt.name == key { - c.sections[sn].options = append(sect.options[:i], sect.options[i+1:]...) - return - } - } - return - } - } -} diff --git a/Godeps/_workspace/src/github.com/calmh/ini/ini_test.go b/Godeps/_workspace/src/github.com/calmh/ini/ini_test.go deleted file mode 100644 index 8cc0e5a0a..000000000 --- a/Godeps/_workspace/src/github.com/calmh/ini/ini_test.go +++ /dev/null @@ -1,214 +0,0 @@ -package ini_test - -import ( - "bytes" - "strings" - "testing" - - "github.com/calmh/ini" -) - -func TestParseValues(t *testing.T) { - strs := []string{ - `[general]`, - `k1=v1`, - `k2 = v2`, - ` k3 = v3 `, - `k4=" quoted spaces "`, - `k5 = " quoted spaces " `, - `k6 = with\nnewline`, - `k7 = "with\nnewline"`, - `k8 = a "quoted" word`, - `k9 = "a \"quoted\" word"`, - } - buf := bytes.NewBufferString(strings.Join(strs, "\n")) - cfg := ini.Parse(buf) - - correct := map[string]string{ - "k1": "v1", - "k2": "v2", - "k3": "v3", - "k4": " quoted spaces ", - "k5": " quoted spaces ", - "k6": "with\nnewline", - "k7": "with\nnewline", - "k8": "a \"quoted\" word", - "k9": "a \"quoted\" word", - } - - for k, v := range correct { - if v2 := cfg.Get("general", k); v2 != v { - t.Errorf("Incorrect general.%s, %q != %q", k, v2, v) - } - } - - if v := cfg.Get("general", "nonexistant"); v != "" { - t.Errorf("Unexpected non-empty value %q", v) - } -} - -func TestParseComments(t *testing.T) { - strs := []string{ - ";file comment 1", // No leading space - "; file comment 2 ", // Trailing space - "; file comment 3", // Multiple leading spaces - "[general]", - "; b general comment 1", // Comments in unsorted order - "somekey = somevalue", - "; a general comment 2", - "[other]", - "; other comment 1", // Comments in section with no values - "; other comment 2", - "[other2]", - "; other2 comment 1", - "; other2 comment 2", // Comments on last section - "somekey = somevalue", - } - buf := bytes.NewBufferString(strings.Join(strs, "\n")) - - correct := map[string][]string{ - "": []string{"file comment 1", "file comment 2", "file comment 3"}, - "general": []string{"b general comment 1", "a general comment 2"}, - "other": []string{"other comment 1", "other comment 2"}, - "other2": []string{"other2 comment 1", "other2 comment 2"}, - } - - cfg := ini.Parse(buf) - - for section, comments := range correct { - cmts := cfg.Comments(section) - if len(cmts) != len(comments) { - t.Errorf("Incorrect number of comments for section %q: %d != %d", section, len(cmts), len(comments)) - } else { - for i := range comments { - if cmts[i] != comments[i] { - t.Errorf("Incorrect comment: %q != %q", cmts[i], comments[i]) - } - } - } - } -} - -func TestWrite(t *testing.T) { - cfg := ini.Config{} - cfg.Set("general", "k1", "v1") - cfg.Set("general", "k2", "foo bar") - cfg.Set("general", "k3", " foo bar ") - cfg.Set("general", "k4", "foo\nbar") - - var out bytes.Buffer - cfg.Write(&out) - - correct := `[general] -k1=v1 -k2=foo bar -k3=" foo bar " -k4="foo\nbar" - -` - if s := out.String(); s != correct { - t.Errorf("Incorrect written .INI:\n%s\ncorrect:\n%s", s, correct) - } -} - -func TestSet(t *testing.T) { - buf := bytes.NewBufferString("[general]\nfoo=bar\nfoo2=bar2\n") - cfg := ini.Parse(buf) - - cfg.Set("general", "foo", "baz") // Overwrite existing - cfg.Set("general", "baz", "quux") // Create new value - cfg.Set("other", "baz2", "quux2") // Create new section + value - - var out bytes.Buffer - cfg.Write(&out) - - correct := `[general] -foo=baz -foo2=bar2 -baz=quux - -[other] -baz2=quux2 - -` - - if s := out.String(); s != correct { - t.Errorf("Incorrect INI after set:\n%s", s) - } -} - -func TestDelete(t *testing.T) { - buf := bytes.NewBufferString("[general]\nfoo=bar\nfoo2=bar2\nfoo3=baz\n") - cfg := ini.Parse(buf) - cfg.Delete("general", "foo") - out := new(bytes.Buffer) - cfg.Write(out) - correct := "[general]\nfoo2=bar2\nfoo3=baz\n\n" - - if s := out.String(); s != correct { - t.Errorf("Incorrect INI after delete:\n%s", s) - } - - buf = bytes.NewBufferString("[general]\nfoo=bar\nfoo2=bar2\nfoo3=baz\n") - cfg = ini.Parse(buf) - cfg.Delete("general", "foo2") - out = new(bytes.Buffer) - cfg.Write(out) - correct = "[general]\nfoo=bar\nfoo3=baz\n\n" - - if s := out.String(); s != correct { - t.Errorf("Incorrect INI after delete:\n%s", s) - } - - buf = bytes.NewBufferString("[general]\nfoo=bar\nfoo2=bar2\nfoo3=baz\n") - cfg = ini.Parse(buf) - cfg.Delete("general", "foo3") - out = new(bytes.Buffer) - cfg.Write(out) - correct = "[general]\nfoo=bar\nfoo2=bar2\n\n" - - if s := out.String(); s != correct { - t.Errorf("Incorrect INI after delete:\n%s", s) - } -} - -func TestSetManyEquals(t *testing.T) { - buf := bytes.NewBufferString("[general]\nfoo=bar==\nfoo2=bar2==\n") - cfg := ini.Parse(buf) - - cfg.Set("general", "foo", "baz==") - - var out bytes.Buffer - cfg.Write(&out) - - correct := `[general] -foo=baz== -foo2=bar2== - -` - - if s := out.String(); s != correct { - t.Errorf("Incorrect INI after set:\n%s", s) - } -} - -func TestRewriteDuplicate(t *testing.T) { - buf := bytes.NewBufferString("[general]\nfoo=bar==\nfoo=bar2==\n") - cfg := ini.Parse(buf) - - if v := cfg.Get("general", "foo"); v != "bar2==" { - t.Errorf("incorrect get %q", v) - } - - var out bytes.Buffer - cfg.Write(&out) - - correct := `[general] -foo=bar2== - -` - - if s := out.String(); s != correct { - t.Errorf("Incorrect INI after set:\n%s", s) - } -} diff --git a/cmd/syncthing/config.go b/cmd/syncthing/config.go index e4c87486a..b3c6d65eb 100644 --- a/cmd/syncthing/config.go +++ b/cmd/syncthing/config.go @@ -8,7 +8,6 @@ import ( "reflect" "sort" "strconv" - "strings" ) type Configuration struct { @@ -107,41 +106,6 @@ func fillNilSlices(data interface{}) error { return nil } -func readConfigINI(m map[string]string, data interface{}) error { - s := reflect.ValueOf(data).Elem() - t := s.Type() - - for i := 0; i < s.NumField(); i++ { - f := s.Field(i) - tag := t.Field(i).Tag - - name := tag.Get("ini") - if len(name) == 0 { - name = strings.ToLower(t.Field(i).Name) - } - - if v, ok := m[name]; ok { - switch f.Interface().(type) { - case string: - f.SetString(v) - - case int: - i, err := strconv.ParseInt(v, 10, 64) - if err == nil { - f.SetInt(i) - } - - case bool: - f.SetBool(v == "true") - - default: - panic(f.Type()) - } - } - } - return nil -} - func writeConfigXML(wr io.Writer, cfg Configuration) error { e := xml.NewEncoder(wr) e.Indent("", " ") diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index 445dc3ac0..89760db9b 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -16,8 +16,6 @@ import ( "runtime/debug" "strings" "time" - - "github.com/calmh/ini" "github.com/calmh/syncthing/discover" "github.com/calmh/syncthing/protocol" "github.com/juju/ratelimit" @@ -120,31 +118,6 @@ func main() { fatalln(err) } cf.Close() - } else { - // No config.xml, let's try the old syncthing.ini - iniFile := filepath.Join(confDir, "syncthing.ini") - cf, err := os.Open(iniFile) - if err == nil { - infoln("Migrating syncthing.ini to config.xml") - iniCfg := ini.Parse(cf) - cf.Close() - Rename(iniFile, filepath.Join(confDir, "migrated_syncthing.ini")) - - cfg, _ = readConfigXML(nil) - cfg.Repositories = []RepositoryConfiguration{ - {Directory: iniCfg.Get("repository", "dir")}, - } - readConfigINI(iniCfg.OptionMap("settings"), &cfg.Options) - for name, addrs := range iniCfg.OptionMap("nodes") { - n := NodeConfiguration{ - NodeID: name, - Addresses: strings.Fields(addrs), - } - cfg.Repositories[0].Nodes = append(cfg.Repositories[0].Nodes, n) - } - - saveConfig() - } } if len(cfg.Repositories) == 0 {