From 09744748af07f78eacd5a49796216a7fc16845ae Mon Sep 17 00:00:00 2001 From: Stefan Majewsky Date: Tue, 4 Apr 2017 01:22:17 +0200 Subject: read and write index file --- index.go | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 index.go (limited to 'index.go') diff --git a/index.go b/index.go new file mode 100644 index 0000000..967fe35 --- /dev/null +++ b/index.go @@ -0,0 +1,116 @@ +/******************************************************************************* +* +* Copyright 2017 Stefan Majewsky +* +* This program is free software: you can redistribute it and/or modify it under +* the terms of the GNU General Public License as published by the Free Software +* Foundation, either version 3 of the License, or (at your option) any later +* version. +* +* 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. See the GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see . +* +*******************************************************************************/ + +package main + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + + yaml "gopkg.in/yaml.v2" +) + +//Repo describes the entry for a repository in the index file. +type Repo struct { + //Remotes maps remote names (as noted in the .git/config of the repo) to + //remote URLs (as they appear in the .git/config of the repo, i.e. possibly + //abbreviated). + Remotes map[string]string `yaml:"remotes"` + //CheckoutPath shall be relative to the Index.RootPath. + CheckoutPath string `yaml:"path"` +} + +//Index represents the contents of the index file. +type Index struct { + RootPath string `yaml:"root"` + Repos []Repo `yaml:"repos"` +} + +func indexPath() string { + homeDir := os.Getenv("HOME") + if homeDir == "" { + FatalIfError(errors.New("$HOME is not set")) + } + return filepath.Join(homeDir, ".rtree/index.yaml") +} + +//ReadIndex reads the index file. +func ReadIndex() *Index { + //read contents of index file + path := indexPath() + buf, err := ioutil.ReadFile(path) + if err != nil { + if os.IsNotExist(err) { + //initialize empty index + rootPath := os.Getenv("GOPATH") + if rootPath == "" { + FatalIfError(fmt.Errorf("cannot initialize %s ($GOPATH not set)", path)) + } + return &Index{RootPath: rootPath} + } + FatalIfError(err) + } + + //deserialize YAML + var index Index + FatalIfError(yaml.Unmarshal(buf, &index)) + + //validate YAML + valid := true + if index.RootPath == "" { + ShowError(errors.New("missing \"root\"")) + valid = false + } + for idx, repo := range index.Repos { + if repo.CheckoutPath == "" { + ShowError(fmt.Errorf("missing \"repos[%d].path\"", idx)) + valid = false + } + if len(repo.Remotes) == 0 { + ShowError(fmt.Errorf("missing \"repos[%d].remotes\"", idx)) + valid = false + } + for remoteName, remoteURL := range repo.Remotes { + switch { + case remoteName == "": + ShowError(fmt.Errorf("empty remote name found in \"repos[%d]\"", idx)) + valid = false + case remoteURL == "": + ShowError(fmt.Errorf("missing remote URL for remote \"%s\" in \"repos[%d]\"", idx, remoteName)) + valid = false + } + } + } + + if !valid { + FatalIfError(errors.New("index file is corrupted; see errors above")) + } + return &index +} + +//Write writes the index file to disk. +func (i *Index) Write() { + buf, err := yaml.Marshal(i) + FatalIfError(err) + path := indexPath() + FatalIfError(os.MkdirAll(filepath.Dir(path), 0755)) + FatalIfError(ioutil.WriteFile(path, buf, 0644)) +} -- cgit v1.3.1