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"
"errors"
"flag"
"fmt"
"log"
"os"
)
@ -21,9 +22,9 @@ const defaultSrid = 3857
const defaultCacheDir = "/tmp/goposm"
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
CacheDir string
MappingFile string
@ -33,8 +34,60 @@ type ImportBaseOptions struct {
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 {
Base ImportBaseOptions
Cpuprofile string
Httpprofile string
Memprofile string
@ -50,141 +103,95 @@ type _ImportOptions struct {
Quiet bool
}
type _DiffImportOptions struct {
Base ImportBaseOptions
}
var BaseOptions = _BaseOptions{}
var ImportOptions = _ImportOptions{}
var DiffImportOptions = _DiffImportOptions{}
func addBaseFlags(flags *flag.FlagSet, baseOptions *ImportBaseOptions) {
flags.StringVar(&baseOptions.Connection, "connection", "", "connection parameters")
flags.StringVar(&baseOptions.CacheDir, "cachedir", defaultCacheDir, "cache directory")
flags.StringVar(&baseOptions.MappingFile, "mapping", "", "mapping file")
flags.IntVar(&baseOptions.Srid, "srid", defaultSrid, "srs id")
flags.StringVar(&baseOptions.LimitTo, "limitto", "", "limit to geometries")
flags.StringVar(&baseOptions.ConfigFile, "config", "", "config (json)")
func addBaseFlags(flags *flag.FlagSet) {
flags.StringVar(&BaseOptions.Connection, "connection", "", "connection parameters")
flags.StringVar(&BaseOptions.CacheDir, "cachedir", defaultCacheDir, "cache directory")
flags.StringVar(&BaseOptions.MappingFile, "mapping", "", "mapping file")
flags.IntVar(&BaseOptions.Srid, "srid", defaultSrid, "srs id")
flags.StringVar(&BaseOptions.LimitTo, "limitto", "", "limit to geometries")
flags.StringVar(&BaseOptions.ConfigFile, "config", "", "config (json)")
}
func addImportFlags(flags *flag.FlagSet, options *_ImportOptions) {
flags.StringVar(&options.Cpuprofile, "cpuprofile", "", "filename of cpu profile output")
flags.StringVar(&options.Httpprofile, "httpprofile", "", "bind address for profile server")
flags.StringVar(&options.Memprofile, "memprofile", "", "dir name of mem profile output and interval (fname:interval)")
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 UsageImport() {
fmt.Fprintf(os.Stderr, "Usage: %s %s [args]\n\n", os.Args[0], os.Args[1])
ImportFlags.PrintDefaults()
os.Exit(2)
}
func addDiffImportFlags(flags *flag.FlagSet, options *_DiffImportOptions) {
// no options yet
func UsageDiff() {
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() {
addBaseFlags(ImportFlags, &ImportOptions.Base)
addImportFlags(ImportFlags, &ImportOptions)
addBaseFlags(DiffImportFlags, &DiffImportOptions.Base)
addDiffImportFlags(DiffImportFlags, &DiffImportOptions)
ImportFlags.Usage = UsageImport
DiffFlags.Usage = UsageDiff
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 (
// connection = flag.String("connection", "", "connection parameters")
// cachedir = flag.String("cachedir", defaultCacheDir, "cache directory")
// 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 {
func ParseImport(args []string) {
if len(args) == 0 {
UsageImport()
}
err := ImportFlags.Parse(args)
if err != nil {
log.Fatal(err)
}
errs := updateBaseOpts(&ImportOptions.Base)
if errs != nil {
return errs
err = BaseOptions.updateFromConfig()
if err != nil {
log.Fatal(err)
}
errs := BaseOptions.check()
if len(errs) != 0 {
reportErrors(errs)
UsageImport()
}
errs = checkOptions(&ImportOptions.Base)
return errs
}
func updateBaseOpts(opts *ImportBaseOptions) []error {
conf := &Config{
CacheDir: defaultCacheDir,
Srid: defaultSrid,
func ParseDiffImport(args []string) {
if len(args) == 0 {
UsageDiff()
}
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)
err := DiffFlags.Parse(args)
if err != nil {
log.Fatal(err)
}
errs := updateBaseOpts(&DiffImportOptions.Base)
if errs != nil {
return errs
err = BaseOptions.updateFromConfig()
if err != nil {
log.Fatal(err)
}
errs = checkOptions(&DiffImportOptions.Base)
return errs
errs := BaseOptions.check()
if len(errs) != 0 {
reportErrors(errs)
UsageDiff()
}
}
func checkOptions(opts *ImportBaseOptions) []error {
errs := []error{}
if opts.Srid != 3857 {
errs = append(errs, errors.New("srid!=3857 not implemented"))
func reportErrors(errs []error) {
fmt.Println("errors in config/options:")
for _, err := range errs {
fmt.Printf("\t%s\n", err)
}
if opts.MappingFile == "" {
errs = append(errs, errors.New("missing mapping"))
}
if opts.Connection == "" {
errs = append(errs, errors.New("missing connection"))
}
return errs
os.Exit(1)
}

View File

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

View File

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