refactored command parsing; update --help

master
Oliver Tonnhofer 2013-08-01 16:19:20 +02:00
parent 0aba137bb8
commit 87d79a576d
3 changed files with 153 additions and 161 deletions

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"flag" "flag"
"fmt"
"log" "log"
"os" "os"
) )
@ -21,9 +22,9 @@ const defaultSrid = 3857
const defaultCacheDir = "/tmp/goposm" const defaultCacheDir = "/tmp/goposm"
var ImportFlags = flag.NewFlagSet("import", flag.ExitOnError) var ImportFlags = flag.NewFlagSet("import", flag.ExitOnError)
var DiffImportFlags = flag.NewFlagSet("diff", flag.ExitOnError) var DiffFlags = flag.NewFlagSet("diff", flag.ExitOnError)
type ImportBaseOptions struct { type _BaseOptions struct {
Connection string Connection string
CacheDir string CacheDir string
MappingFile string MappingFile string
@ -33,8 +34,60 @@ type ImportBaseOptions struct {
ConfigFile string ConfigFile string
} }
func (o *_BaseOptions) updateFromConfig() error {
conf := &Config{
CacheDir: defaultCacheDir,
Srid: defaultSrid,
}
if o.ConfigFile != "" {
f, err := os.Open(o.ConfigFile)
if err != nil {
return err
}
decoder := json.NewDecoder(f)
err = decoder.Decode(&conf)
if err != nil {
return err
}
}
if o.Connection == "" {
o.Connection = conf.Connection
}
if conf.Srid == 0 {
conf.Srid = defaultSrid
}
if o.Srid != defaultSrid {
o.Srid = conf.Srid
}
if o.MappingFile == "" {
o.MappingFile = conf.MappingFile
}
if o.LimitTo == "" {
o.LimitTo = conf.LimitTo
}
if o.LimitToCacheBuffer == 0.0 {
o.LimitToCacheBuffer = conf.LimitToCacheBuffer
}
if o.CacheDir == defaultCacheDir {
o.CacheDir = conf.CacheDir
}
return nil
}
func (o *_BaseOptions) check() []error {
errs := []error{}
if o.Srid != 3857 {
errs = append(errs, errors.New("srid!=3857 not implemented"))
}
if o.MappingFile == "" {
errs = append(errs, errors.New("missing mapping"))
}
return errs
}
type _ImportOptions struct { type _ImportOptions struct {
Base ImportBaseOptions
Cpuprofile string Cpuprofile string
Httpprofile string Httpprofile string
Memprofile string Memprofile string
@ -50,141 +103,95 @@ type _ImportOptions struct {
Quiet bool Quiet bool
} }
type _DiffImportOptions struct { var BaseOptions = _BaseOptions{}
Base ImportBaseOptions
}
var ImportOptions = _ImportOptions{} var ImportOptions = _ImportOptions{}
var DiffImportOptions = _DiffImportOptions{}
func addBaseFlags(flags *flag.FlagSet, baseOptions *ImportBaseOptions) { func addBaseFlags(flags *flag.FlagSet) {
flags.StringVar(&baseOptions.Connection, "connection", "", "connection parameters") flags.StringVar(&BaseOptions.Connection, "connection", "", "connection parameters")
flags.StringVar(&baseOptions.CacheDir, "cachedir", defaultCacheDir, "cache directory") flags.StringVar(&BaseOptions.CacheDir, "cachedir", defaultCacheDir, "cache directory")
flags.StringVar(&baseOptions.MappingFile, "mapping", "", "mapping file") flags.StringVar(&BaseOptions.MappingFile, "mapping", "", "mapping file")
flags.IntVar(&baseOptions.Srid, "srid", defaultSrid, "srs id") flags.IntVar(&BaseOptions.Srid, "srid", defaultSrid, "srs id")
flags.StringVar(&baseOptions.LimitTo, "limitto", "", "limit to geometries") flags.StringVar(&BaseOptions.LimitTo, "limitto", "", "limit to geometries")
flags.StringVar(&baseOptions.ConfigFile, "config", "", "config (json)") flags.StringVar(&BaseOptions.ConfigFile, "config", "", "config (json)")
} }
func addImportFlags(flags *flag.FlagSet, options *_ImportOptions) { func UsageImport() {
flags.StringVar(&options.Cpuprofile, "cpuprofile", "", "filename of cpu profile output") fmt.Fprintf(os.Stderr, "Usage: %s %s [args]\n\n", os.Args[0], os.Args[1])
flags.StringVar(&options.Httpprofile, "httpprofile", "", "bind address for profile server") ImportFlags.PrintDefaults()
flags.StringVar(&options.Memprofile, "memprofile", "", "dir name of mem profile output and interval (fname:interval)") os.Exit(2)
flags.BoolVar(&options.Overwritecache, "overwritecache", false, "overwritecache")
flags.BoolVar(&options.Appendcache, "appendcache", false, "append cache")
flags.StringVar(&options.Read, "read", "", "read")
flags.BoolVar(&options.Write, "write", false, "write")
flags.BoolVar(&options.Optimize, "optimize", false, "optimize")
flags.BoolVar(&options.Diff, "diff", false, "enable diff support")
flags.BoolVar(&options.DeployProduction, "deployproduction", false, "deploy production")
flags.BoolVar(&options.RevertDeploy, "revertdeploy", false, "revert deploy to production")
flags.BoolVar(&options.RemoveBackup, "removebackup", false, "remove backups from deploy")
flags.BoolVar(&options.Quiet, "quiet", false, "quiet log output")
} }
func addDiffImportFlags(flags *flag.FlagSet, options *_DiffImportOptions) { func UsageDiff() {
// no options yet fmt.Fprintf(os.Stderr, "Usage: %s %s [args] [.osc.gz, ...]\n\n", os.Args[0], os.Args[1])
DiffFlags.PrintDefaults()
os.Exit(2)
} }
func init() { func init() {
addBaseFlags(ImportFlags, &ImportOptions.Base) ImportFlags.Usage = UsageImport
addImportFlags(ImportFlags, &ImportOptions) DiffFlags.Usage = UsageDiff
addBaseFlags(DiffImportFlags, &DiffImportOptions.Base)
addDiffImportFlags(DiffImportFlags, &DiffImportOptions) addBaseFlags(DiffFlags)
addBaseFlags(ImportFlags)
ImportFlags.StringVar(&ImportOptions.Cpuprofile, "cpuprofile", "", "filename of cpu profile output")
ImportFlags.StringVar(&ImportOptions.Httpprofile, "httpprofile", "", "bind address for profile server")
ImportFlags.StringVar(&ImportOptions.Memprofile, "memprofile", "", "dir name of mem profile output and interval (fname:interval)")
ImportFlags.BoolVar(&ImportOptions.Overwritecache, "overwritecache", false, "overwritecache")
ImportFlags.BoolVar(&ImportOptions.Appendcache, "appendcache", false, "append cache")
ImportFlags.StringVar(&ImportOptions.Read, "read", "", "read")
ImportFlags.BoolVar(&ImportOptions.Write, "write", false, "write")
ImportFlags.BoolVar(&ImportOptions.Optimize, "optimize", false, "optimize")
ImportFlags.BoolVar(&ImportOptions.Diff, "diff", false, "enable diff support")
ImportFlags.BoolVar(&ImportOptions.DeployProduction, "deployproduction", false, "deploy production")
ImportFlags.BoolVar(&ImportOptions.RevertDeploy, "revertdeploy", false, "revert deploy to production")
ImportFlags.BoolVar(&ImportOptions.RemoveBackup, "removebackup", false, "remove backups from deploy")
ImportFlags.BoolVar(&ImportOptions.Quiet, "quiet", false, "quiet log output")
} }
// var ( func ParseImport(args []string) {
// connection = flag.String("connection", "", "connection parameters") if len(args) == 0 {
// cachedir = flag.String("cachedir", defaultCacheDir, "cache directory") UsageImport()
// mappingFile = flag.String("mapping", "", "mapping file") }
// srid = flag.Int("srid", defaultSrid, "srs id")
// limitTo = flag.String("limitto", "", "limit to geometries")
// configFile = flag.String("config", "", "config (json)")
// )
func ParseImport(args []string) []error {
err := ImportFlags.Parse(args) err := ImportFlags.Parse(args)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
errs := updateBaseOpts(&ImportOptions.Base) err = BaseOptions.updateFromConfig()
if errs != nil { if err != nil {
return errs log.Fatal(err)
}
errs := BaseOptions.check()
if len(errs) != 0 {
reportErrors(errs)
UsageImport()
} }
errs = checkOptions(&ImportOptions.Base)
return errs
} }
func updateBaseOpts(opts *ImportBaseOptions) []error { func ParseDiffImport(args []string) {
if len(args) == 0 {
conf := &Config{ UsageDiff()
CacheDir: defaultCacheDir,
Srid: defaultSrid,
} }
err := DiffFlags.Parse(args)
if opts.ConfigFile != "" {
f, err := os.Open(opts.ConfigFile)
if err != nil {
return []error{err}
}
decoder := json.NewDecoder(f)
err = decoder.Decode(&conf)
if err != nil {
return []error{err}
}
}
if opts.Connection == "" {
opts.Connection = conf.Connection
}
if conf.Srid == 0 {
conf.Srid = defaultSrid
}
if opts.Srid != defaultSrid {
opts.Srid = conf.Srid
}
if opts.MappingFile == "" {
opts.MappingFile = conf.MappingFile
}
if opts.LimitTo == "" {
opts.LimitTo = conf.LimitTo
}
if opts.LimitToCacheBuffer == 0.0 {
opts.LimitToCacheBuffer = conf.LimitToCacheBuffer
}
if opts.CacheDir == defaultCacheDir {
opts.CacheDir = conf.CacheDir
}
return nil
}
func ParseDiffImport(args []string) []error {
err := DiffImportFlags.Parse(args)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
errs := updateBaseOpts(&DiffImportOptions.Base) err = BaseOptions.updateFromConfig()
if errs != nil { if err != nil {
return errs log.Fatal(err)
} }
errs = checkOptions(&DiffImportOptions.Base) errs := BaseOptions.check()
if len(errs) != 0 {
return errs reportErrors(errs)
UsageDiff()
}
} }
func checkOptions(opts *ImportBaseOptions) []error { func reportErrors(errs []error) {
errs := []error{} fmt.Println("errors in config/options:")
if opts.Srid != 3857 { for _, err := range errs {
errs = append(errs, errors.New("srid!=3857 not implemented")) fmt.Printf("\t%s\n", err)
} }
if opts.MappingFile == "" { os.Exit(1)
errs = append(errs, errors.New("missing mapping"))
}
if opts.Connection == "" {
errs = append(errs, errors.New("missing connection"))
}
return errs
} }

View File

@ -26,7 +26,7 @@ func Update(oscFile string, geometryLimiter *limit.Limiter, force bool) {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
lastState, err := diffstate.ParseLastState(config.DiffImportOptions.Base.CacheDir) lastState, err := diffstate.ParseLastState(config.BaseOptions.CacheDir)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -42,28 +42,28 @@ func Update(oscFile string, geometryLimiter *limit.Limiter, force bool) {
elems, errc := parser.Parse(oscFile) elems, errc := parser.Parse(oscFile)
osmCache := cache.NewOSMCache(config.DiffImportOptions.Base.CacheDir) osmCache := cache.NewOSMCache(config.BaseOptions.CacheDir)
err = osmCache.Open() err = osmCache.Open()
if err != nil { if err != nil {
log.Fatal("osm cache: ", err) log.Fatal("osm cache: ", err)
} }
diffCache := cache.NewDiffCache(config.DiffImportOptions.Base.CacheDir) diffCache := cache.NewDiffCache(config.BaseOptions.CacheDir)
err = diffCache.Open() err = diffCache.Open()
if err != nil { if err != nil {
log.Fatal("diff cache: ", err) log.Fatal("diff cache: ", err)
} }
tagmapping, err := mapping.NewMapping(config.DiffImportOptions.Base.MappingFile) tagmapping, err := mapping.NewMapping(config.BaseOptions.MappingFile)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
connType := database.ConnectionType(config.DiffImportOptions.Base.Connection) connType := database.ConnectionType(config.BaseOptions.Connection)
dbConf := database.Config{ dbConf := database.Config{
Type: connType, Type: connType,
ConnectionParams: config.DiffImportOptions.Base.Connection, ConnectionParams: config.BaseOptions.Connection,
Srid: config.DiffImportOptions.Base.Srid, Srid: config.BaseOptions.Srid,
} }
db, err := database.Open(dbConf, tagmapping) db, err := database.Open(dbConf, tagmapping)
if err != nil { if err != nil {
@ -105,19 +105,19 @@ func Update(oscFile string, geometryLimiter *limit.Limiter, force bool) {
nodes := make(chan *element.Node) nodes := make(chan *element.Node)
relWriter := writer.NewRelationWriter(osmCache, diffCache, relations, relWriter := writer.NewRelationWriter(osmCache, diffCache, relations,
db, polygonsTagMatcher, progress, config.DiffImportOptions.Base.Srid) db, polygonsTagMatcher, progress, config.BaseOptions.Srid)
relWriter.SetLimiter(geometryLimiter) relWriter.SetLimiter(geometryLimiter)
relWriter.SetExpireTiles(expiredTiles) relWriter.SetExpireTiles(expiredTiles)
relWriter.Start() relWriter.Start()
wayWriter := writer.NewWayWriter(osmCache, diffCache, ways, db, wayWriter := writer.NewWayWriter(osmCache, diffCache, ways, db,
lineStringsTagMatcher, polygonsTagMatcher, progress, config.DiffImportOptions.Base.Srid) lineStringsTagMatcher, polygonsTagMatcher, progress, config.BaseOptions.Srid)
wayWriter.SetLimiter(geometryLimiter) wayWriter.SetLimiter(geometryLimiter)
wayWriter.SetExpireTiles(expiredTiles) wayWriter.SetExpireTiles(expiredTiles)
wayWriter.Start() wayWriter.Start()
nodeWriter := writer.NewNodeWriter(osmCache, nodes, db, nodeWriter := writer.NewNodeWriter(osmCache, nodes, db,
pointsTagMatcher, progress, config.DiffImportOptions.Base.Srid) pointsTagMatcher, progress, config.BaseOptions.Srid)
nodeWriter.SetLimiter(geometryLimiter) nodeWriter.SetLimiter(geometryLimiter)
nodeWriter.Start() nodeWriter.Start()
@ -283,7 +283,7 @@ For:
progress.Stop() progress.Stop()
if state != nil { if state != nil {
err = diffstate.WriteLastState(config.DiffImportOptions.Base.CacheDir, state) err = diffstate.WriteLastState(config.BaseOptions.CacheDir, state)
if err != nil { if err != nil {
log.Warn(err) // warn only log.Warn(err) // warn only
} }

View File

@ -28,15 +28,6 @@ import (
var log = logging.NewLogger("") var log = logging.NewLogger("")
func reportErrors(errs []error) {
fmt.Println("errors in config/options:")
for _, err := range errs {
fmt.Printf("\t%s\n", err)
}
logging.Shutdown()
os.Exit(1)
}
func printCmds() { func printCmds() {
fmt.Fprintf(os.Stderr, "Usage: %s COMMAND [args]\n\n", os.Args[0]) fmt.Fprintf(os.Stderr, "Usage: %s COMMAND [args]\n\n", os.Args[0])
fmt.Println("Available commands:") fmt.Println("Available commands:")
@ -60,27 +51,18 @@ func main() {
switch os.Args[1] { switch os.Args[1] {
case "import": case "import":
errs := config.ParseImport(os.Args[2:]) config.ParseImport(os.Args[2:])
if len(errs) > 0 {
config.ImportFlags.PrintDefaults()
reportErrors(errs)
break
}
mainimport() mainimport()
case "diff": case "diff":
errs := config.ParseDiffImport(os.Args[2:]) config.ParseDiffImport(os.Args[2:])
if len(errs) > 0 {
config.DiffImportFlags.PrintDefaults()
reportErrors(errs)
break
}
var geometryLimiter *limit.Limiter var geometryLimiter *limit.Limiter
if config.DiffImportOptions.Base.LimitTo != "" { if config.BaseOptions.LimitTo != "" {
var err error var err error
step := log.StartStep("Reading limitto geometries") step := log.StartStep("Reading limitto geometries")
geometryLimiter, err = limit.NewFromOgrSourceWithBuffered( geometryLimiter, err = limit.NewFromOgrSourceWithBuffered(
config.DiffImportOptions.Base.LimitTo, config.BaseOptions.LimitTo,
config.DiffImportOptions.Base.LimitToCacheBuffer, config.BaseOptions.LimitToCacheBuffer,
) )
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -88,7 +70,7 @@ func main() {
log.StopStep(step) log.StopStep(step)
} }
for _, oscFile := range config.DiffImportFlags.Args() { for _, oscFile := range config.DiffFlags.Args() {
diff.Update(oscFile, geometryLimiter, false) diff.Update(oscFile, geometryLimiter, false)
} }
case "query-cache": case "query-cache":
@ -145,17 +127,17 @@ func mainimport() {
} }
var geometryLimiter *limit.Limiter var geometryLimiter *limit.Limiter
if config.ImportOptions.Write && config.ImportOptions.Base.LimitTo != "" { if config.ImportOptions.Write && config.BaseOptions.LimitTo != "" {
var err error var err error
step := log.StartStep("Reading limitto geometries") step := log.StartStep("Reading limitto geometries")
geometryLimiter, err = limit.NewFromOgrSource(config.ImportOptions.Base.LimitTo) geometryLimiter, err = limit.NewFromOgrSource(config.BaseOptions.LimitTo)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
log.StopStep(step) log.StopStep(step)
} }
tagmapping, err := mapping.NewMapping(config.ImportOptions.Base.MappingFile) tagmapping, err := mapping.NewMapping(config.BaseOptions.MappingFile)
if err != nil { if err != nil {
log.Fatal("mapping file: ", err) log.Fatal("mapping file: ", err)
} }
@ -163,11 +145,14 @@ func mainimport() {
var db database.DB var db database.DB
if config.ImportOptions.Write || config.ImportOptions.DeployProduction || config.ImportOptions.RevertDeploy || config.ImportOptions.RemoveBackup || config.ImportOptions.Optimize { if config.ImportOptions.Write || config.ImportOptions.DeployProduction || config.ImportOptions.RevertDeploy || config.ImportOptions.RemoveBackup || config.ImportOptions.Optimize {
connType := database.ConnectionType(config.ImportOptions.Base.Connection) if config.BaseOptions.Connection == "" {
log.Fatal("missing connection option")
}
connType := database.ConnectionType(config.BaseOptions.Connection)
conf := database.Config{ conf := database.Config{
Type: connType, Type: connType,
ConnectionParams: config.ImportOptions.Base.Connection, ConnectionParams: config.BaseOptions.Connection,
Srid: config.ImportOptions.Base.Srid, Srid: config.BaseOptions.Srid,
} }
db, err = database.Open(conf, tagmapping) db, err = database.Open(conf, tagmapping)
if err != nil { if err != nil {
@ -175,11 +160,11 @@ func mainimport() {
} }
} }
osmCache := cache.NewOSMCache(config.ImportOptions.Base.CacheDir) osmCache := cache.NewOSMCache(config.BaseOptions.CacheDir)
if config.ImportOptions.Read != "" && osmCache.Exists() { if config.ImportOptions.Read != "" && osmCache.Exists() {
if config.ImportOptions.Overwritecache { if config.ImportOptions.Overwritecache {
log.Printf("removing existing cache %s", config.ImportOptions.Base.CacheDir) log.Printf("removing existing cache %s", config.BaseOptions.CacheDir)
err := osmCache.Remove() err := osmCache.Remove()
if err != nil { if err != nil {
log.Fatal("unable to remove cache:", err) log.Fatal("unable to remove cache:", err)
@ -215,7 +200,7 @@ func mainimport() {
if config.ImportOptions.Diff { if config.ImportOptions.Diff {
diffstate := state.FromPbf(pbfFile) diffstate := state.FromPbf(pbfFile)
if diffstate != nil { if diffstate != nil {
diffstate.WriteToFile(path.Join(config.ImportOptions.Base.CacheDir, "last.state.txt")) diffstate.WriteToFile(path.Join(config.BaseOptions.CacheDir, "last.state.txt"))
} }
} }
} }
@ -242,7 +227,7 @@ func mainimport() {
var diffCache *cache.DiffCache var diffCache *cache.DiffCache
if config.ImportOptions.Diff { if config.ImportOptions.Diff {
diffCache = cache.NewDiffCache(config.ImportOptions.Base.CacheDir) diffCache = cache.NewDiffCache(config.BaseOptions.CacheDir)
if err = diffCache.Remove(); err != nil { if err = diffCache.Remove(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -262,7 +247,7 @@ func mainimport() {
relations := osmCache.Relations.Iter() relations := osmCache.Relations.Iter()
relWriter := writer.NewRelationWriter(osmCache, diffCache, relations, relWriter := writer.NewRelationWriter(osmCache, diffCache, relations,
db, polygonsTagMatcher, progress, config.ImportOptions.Base.Srid) db, polygonsTagMatcher, progress, config.BaseOptions.Srid)
relWriter.SetLimiter(geometryLimiter) relWriter.SetLimiter(geometryLimiter)
relWriter.Start() relWriter.Start()
@ -272,7 +257,7 @@ func mainimport() {
ways := osmCache.Ways.Iter() ways := osmCache.Ways.Iter()
wayWriter := writer.NewWayWriter(osmCache, diffCache, ways, db, wayWriter := writer.NewWayWriter(osmCache, diffCache, ways, db,
lineStringsTagMatcher, polygonsTagMatcher, progress, config.ImportOptions.Base.Srid) lineStringsTagMatcher, polygonsTagMatcher, progress, config.BaseOptions.Srid)
wayWriter.SetLimiter(geometryLimiter) wayWriter.SetLimiter(geometryLimiter)
wayWriter.Start() wayWriter.Start()
@ -282,7 +267,7 @@ func mainimport() {
nodes := osmCache.Nodes.Iter() nodes := osmCache.Nodes.Iter()
nodeWriter := writer.NewNodeWriter(osmCache, nodes, db, nodeWriter := writer.NewNodeWriter(osmCache, nodes, db,
pointsTagMatcher, progress, config.ImportOptions.Base.Srid) pointsTagMatcher, progress, config.BaseOptions.Srid)
nodeWriter.SetLimiter(geometryLimiter) nodeWriter.SetLimiter(geometryLimiter)
nodeWriter.Start() nodeWriter.Start()