Ejemplo n.º 1
0
func main() {
	op := optionparser.NewOptionParser()
	op.On("--address IPADDRESS", "Address to be used for the server mode. Defaults to 127.0.0.1", options)
	op.On("--autoopen", "Open the PDF file (MacOS X and Linux only)", options)
	op.On("-c NAME", "--config", "Read the config file with the given NAME. Default: 'publisher.cfg'", &configfilename)
	op.On("--credits", "Show credits and exit", showCredits)
	op.On("--no-cutmarks", "Display cutmarks in the document", layoutoptions)
	op.On("--data NAME", "Name of the XML data file. Defaults to 'data.xml'. Use '-' for STDIN", options)
	op.On("--dummy", "Don't read a data file, use '<data />' as input", options)
	op.On("-x", "--extra-dir DIR", "Additional directory for file search", extradir)
	op.On("--extra-xml NAME", "Add this file to the layout file", extraXML)
	op.On("--filter FILTER", "Run XPROC filter before publishing starts", options)
	op.On("--grid", "Display background grid. Disable with --no-grid", options)
	op.On("--ignore-case", "Ignore case when accessing files (on a case-insensitive file system)", options)
	op.On("--no-local", "Add local directory to the search path. Default is true", &add_local_path)
	op.On("--layout NAME", "Name of the layout file. Defaults to 'layout.xml'", options)
	op.On("--jobname NAME", "The name of the resulting PDF file (without extension), default is 'publisher'", options)
	op.On("--mainlanguage NAME", "The document's main language in locale format, for example 'en' or 'en_US'.", &mainlanguage)
	op.On("--outputdir=DIR", "Copy PDF and protocol to this directory", options)
	op.On("--port PORT", "Port to be used for the server mode. Defaults to 5266", options)
	op.On("--profile", "Run publisher with profiling on (internal use)", options)
	op.On("--quiet", "Run publisher in silent mode", options)
	op.On("--runs NUM", "Number of publishing runs ", options)
	op.On("--startpage NUM", "The first page number", layoutoptions)
	op.On("--show-gridallocation", "Show the allocated grid cells", layoutoptions)
	op.On("--systemfonts", "Use system fonts (not Win XP)", &useSystemFonts)
	op.On("--tempdir=DIR", "Use this directory instead of the system temporary directory", options)
	op.On("--trace", "Show debug messages and some tracing PDF output", layoutoptions)
	op.On("--timeout SEC", "Exit after SEC seconds", options)
	op.On("-v", "--var VAR=VALUE", "Set a variable for the publishing run", setVariable)
	op.On("--varsfile NAME", "Set variables for the publishing run from key=value... file", options)
	op.On("--verbose", "Print a bit of debugging output", options)
	op.On("--version", "Show version information", versioninfo)
	op.On("--wd DIR", "Change working directory", options)
	op.On("--xml", "Output as (pseudo-)XML (for list-fonts)", options)

	op.Command("clean", "Remove publisher generated files")
	op.Command("compare", "Compare files for quality assurance")
	op.Command("doc", "Open documentation")
	op.Command("list-fonts", "List installed fonts (use together with --xml for copy/paste)")
	op.Command("run", "Start publishing (default)")
	op.Command("server", "Run as http-api server on localhost port 5266 (configure with --address and --port)")
	op.Command("watch", "Start watchdog / hotfolder")
	err := op.Parse()
	if err != nil {
		log.Fatal("Parse error: ", err)
	}

	var command string
	switch len(op.Extra) {
	case 0:
		// no command given, run is the default command
		command = "run"
	case 1:
		// great
		command = op.Extra[0]
	default:
		// more than one command given, what should I do?
		command = op.Extra[0]
	}

	cfg, err = configurator.ReadFiles(filepath.Join(homedir, ".publisher.cfg"), "/etc/speedata/publisher.cfg")
	if err != nil {
		log.Fatal(err)
	}

	// When the user requests another working directory, we should
	// change into the given wd first, before reading the local
	// options
	wdIsSet := false
	if wd := getOption("wd"); wd != "" {
		wdIsSet = true
		err := os.Chdir(wd)
		if err != nil {
			log.Fatal(err)
		}
		log.Printf("Working directory now: %s", wd)
		pwd = wd
	}

	cfg.ReadFile(filepath.Join(pwd, configfilename))

	// ... but if the local config file has a wd=... option, we should honor this
	// and also honor the settings in that publisher.cfg file
	if !wdIsSet {
		if wd := getOption("wd"); wd != "" {
			err := os.Chdir(wd)
			if err != nil {
				log.Fatal(err)
			}
			log.Printf("Working directory now: %s", wd)
			pwd = wd
			cfg.ReadFile(filepath.Join(pwd, configfilename))
		}
	}

	if add_local_path {
		extra_dir = append(extra_dir, pwd)
	}
	if useSystemFonts {
		// FontFolder() is system dependent and defined in extra files
		ff, err := FontFolder()
		if err != nil {
			log.Fatal(err)
		}
		defaults["fontpath"] = ff
	}
	os.Setenv("SP_MAINLANGUAGE", mainlanguage)
	os.Setenv("SP_FONT_PATH", getOption("fontpath"))
	os.Setenv("SP_PATH_REWRITE", getOption("pathrewrite"))
	os.Setenv("IMGCACHE", getOption("imagecache"))

	if ed := cfg.String("DEFAULT", "extra-dir"); ed != "" {
		abspath, err := filepath.Abs(ed)
		if err != nil {
			log.Fatal("Cannot find directory", ed)
		}
		extra_dir = append(extra_dir, abspath)
	}
	os.Setenv("SD_EXTRA_DIRS", strings.Join(extra_dir, string(filepath.ListSeparator)))

	if extraxmloption := getOption("extraxml"); extraxmloption != "" {
		for _, xmlfile := range strings.Split(extraxmloption, ",") {
			extraxml = append(extraxml, xmlfile)
		}
	}

	os.Setenv("SD_EXTRA_XML", strings.Join(extraxml, ","))
	verbose := false
	if getOption("verbose") != "" {
		verbose = true
		os.Setenv("SP_VERBOSITY", "1")
		fmt.Println("SD_EXTRA_DIRS:", os.Getenv("SD_EXTRA_DIRS"))
		fmt.Println("SD_EXTRA_XML:", os.Getenv("SD_EXTRA_XML"))
	}

	if getOption("ignore-case") == "true" {
		os.Setenv("SP_IGNORECASE", "1")
		if verbose {
			fmt.Println("Ignore case for file system access")
		}
	}

	var exitstatus int
	if getOption("profile") != "" {
		fmt.Println("Profiling publisher run. Removing lprof_* now.")
		os.Setenv("SD_PROFILER", "true")
		files, err := filepath.Glob("lprof_*")
		if err != nil {
			log.Fatal(err)
		}
		for _, filename := range files {
			err = os.Remove(filename)
			if err != nil {
				log.Fatal(err)
			}
		}
	}

	if seconds := getOption("timeout"); seconds != "" {
		num, err := strconv.Atoi(seconds)
		if err != nil {
			log.Fatal(err)
		}
		log.Printf("Setting timeout to %d seconds", num)
		go timeoutCatcher(num)
	}

	// There is no need for the internal daemon when we do the other commands
	switch command {
	case "run", "server":
		daemon = comm.NewServer()
	}

	switch command {
	case "run":
		jobname := getOption("jobname")
		finishedfilename := fmt.Sprintf("%s.finished", jobname)
		os.Remove(finishedfilename)
		if filter := getOption("filter"); filter != "" {
			if filepath.Ext(filter) != ".xpl" {
				filter = filter + ".xpl"
			}
			log.Println("Run filter: ", filter)
			os.Setenv("CLASSPATH", libdir+"/calabash.jar:"+libdir+"/saxon9he.jar")
			cmdline := "java com.xmlcalabash.drivers.Main " + filter
			run(cmdline)
		}
		exitstatus = runPublisher()
		// profiler requested?
		if getOption("profile") != "" {
			fmt.Println("Run 'summary.lua' on resulting lprof_* file.")
			files, err := filepath.Glob("lprof_*")
			if err != nil {
				log.Fatal(err)
			}
			if len(files) != 1 {
				log.Println("Profiling not done, expecting exactly one file matching lprof_*.")
			} else {
				cmdline := fmt.Sprintf(`"%s" --luaonly "%s/lua/summary.lua"  -v %s`, getExecutablePath(), srcdir, files[0])
				run(cmdline)
			}

		}
		ioutil.WriteFile(finishedfilename, []byte("finished\n"), 0600)

		// open PDF if necessary
		if getOption("autoopen") == "true" {
			openFile(jobname + ".pdf")
		}
	case "compare":
		if len(op.Extra) > 1 {
			dir := op.Extra[1]
			fi, err := os.Stat(dir)
			if err != nil {
				log.Fatal(err)
			}
			if !fi.IsDir() {
				log.Fatalf("%q must be a directory", dir)
			}
			absDir, err := filepath.Abs(dir)
			if err != nil {
				log.Fatal(err)
			}
			sp.DoCompare(absDir)
		} else {
			log.Println("Please give one directory")
		}
	case "clean":
		jobname := getOption("jobname")
		files, err := filepath.Glob(jobname + "*")
		if err != nil {
			log.Fatal(err)
		}
		for _, v := range files {
			switch filepath.Ext(v) {
			case ".vars", ".log", ".protocol", ".dataxml", ".status", ".finished":
				log.Printf("Removing %s", v)
				err = os.Remove(v)
				if err != nil {
					log.Println(err)
				}
			}
			if v == jobname+"-aux.xml" {
				log.Printf("Removing %s", v)
				err = os.Remove(v)
				if err != nil {
					log.Println(err)
				}
			}
		}
	case "doc":
		openFile(path_to_documentation)
		os.Exit(0)
	case "list-fonts":
		var xml string
		if getOption("xml") == "true" {
			xml = "xml"
		}

		cmdline := fmt.Sprintf(`"%s" --luaonly "%s/lua/sdscripts.lua" "%s" list-fonts %s`, getExecutablePath(), srcdir, inifile, xml)
		run(cmdline)
	case "watch":
		watch_dir := getOptionSection("hotfolder", "hotfolder")
		events := getOptionSection("events", "hotfolder")
		var hotfolder_events []hotfolder.Event

		for _, v := range strings.Split(events, ";") {
			pattern_command := strings.Split(v, ":")
			if len(pattern_command) < 2 {
				log.Fatal("Something is wrong with the configuration file. hotfolder section correct?")
			}
			hotfolder_event := new(hotfolder.Event)
			hotfolder_event.Pattern = regexp.MustCompile(pattern_command[0])
			hotfolder_event.Command = &pattern_command[1]
			hotfolder_events = append(hotfolder_events, *hotfolder_event)
		}

		if watch_dir != "" {
			hotfolder.Watch(watch_dir, hotfolder_events)
		} else {
			log.Fatal("Problem with watch dir in section [hotfolder].")
		}
	case "server":
		runServer(getOption("port"), getOption("address"), getOption("tempdir"))
	default:
		log.Fatal("unknown command:", command)
	}
	if daemon != nil {
		daemon.Close()
	}
	showDuration()
	os.Exit(exitstatus)
}
Ejemplo n.º 2
0
func main() {
	cfg := config.NewConfig(basedir)

	var commandlinebasedir string
	op := optionparser.NewOptionParser()
	op.On("--basedir DIR", "Base dir", &commandlinebasedir)
	op.Command("build", "Build go binary")
	op.Command("dashdoc", "Generate speedata Publisher documentation (for dash)")
	op.Command("doc", "Generate speedata Publisher documentation")
	op.Command("dist", "Generate zip files and windows installers")
	op.Command("mkreadme", "Make readme for installation/distribution")
	op.Command("sourcedoc", "Generate the source documentation")
	op.Command("translate", "Translate layout")
	err := op.Parse()
	if err != nil {
		log.Fatal(err)
	}

	var command string
	if len(op.Extra) > 0 {
		command = op.Extra[0]
	} else {
		op.Help()
		os.Exit(-1)
	}

	if commandlinebasedir != "" {
		cfg.SetBasedir(commandlinebasedir)
	}

	switch command {
	case "build":
		err := buildsp.BuildGo(cfg, filepath.Join(basedir, "bin"), "", "", "local")
		if err != nil {
			os.Exit(-1)
		}
	case "doc":
		err = makedoc(cfg)
		if err != nil {
			log.Fatal(err)
		}
	case "dashdoc":
		err = dashdoc.DoThings(cfg)
		if err != nil {
			log.Fatal(err)
		}
	case "genschema":
		err = genluatranslations.DoThings(basedir)
		if err != nil {
			log.Fatal(err)
		}
		err = genschema.DoThings(basedir)
		if err != nil {
			log.Fatal(err)
		}
	case "dist":
		fmt.Println("Generate ZIP files and windows installer")
		os.RemoveAll(cfg.Builddir)
		makedoc(cfg)
		destdir := filepath.Join(cfg.Builddir, "speedata-publisher")
		var srcbindir string
		if srcbindir = os.Getenv("LUATEX_BIN"); srcbindir == "" || !fileutils.IsDir(srcbindir) {
			fmt.Println("Error: environment variable LUATEX_BIN not set or does not point to a directory")
			os.Exit(-1)
		}
		t := texttemplate.Must(texttemplate.ParseFiles(filepath.Join(cfg.Srcdir, "other", "nsitemplate.txt")))

		for i := 1; i < len(op.Extra); i++ {
			os_arch := strings.Split(op.Extra[i], "/")
			platform := os_arch[0]
			arch := os_arch[1]
			fmt.Println(platform, arch)
			d := filepath.Join(srcbindir, platform, arch, "default")
			if !fileutils.IsDir(d) {
				fmt.Println("Does not exist:", d, "... skipping")
			} else {
				bindir, err := filepath.EvalSymlinks(d)
				if err != nil {
					log.Fatal(err)
				}
				err = dirstructure.MkBuilddir(cfg, bindir)
				if err != nil {
					log.Fatal(err)
				}
				err = buildsp.BuildGo(cfg, filepath.Join(cfg.Builddir, "speedata-publisher", "bin"), platform, arch, "directory")
				if err != nil {
					os.Exit(-1)
				}

				os.Chdir(cfg.Builddir)
				zipname := fmt.Sprintf("speedata-publisher-%s-%s-%s.zip", platform, arch, cfg.Publisherversion)
				os.Remove(zipname)
				exec.Command("zip", "-rq", zipname, "speedata-publisher").Run()

				if platform == "windows" {
					exename := fmt.Sprintf("speedata-publisher-%s-%s-%s-installer.exe", platform, arch, cfg.Publisherversion)
					os.Remove(exename)
					data := struct {
						Exename   string
						Sourcedir string
						Arch      string
					}{
						Exename:   exename,
						Sourcedir: destdir,
						Arch:      arch,
					}
					f, err := os.Create("installer.nsi")
					if err != nil {
						log.Fatal(err)
					}
					t.Execute(f, data)
					out, err := exec.Command("makensis", "installer.nsi").Output()
					if err != nil {
						fmt.Println(string(out))
						log.Fatal(err)
					}
					f.Close()
				}
			}
		}
		if false {

		}
	case "mkreadme":
		if len(op.Extra) < 3 {
			fmt.Println("Not enough arguments, use `mkreadme <os> <destdir>'.")
			fmt.Println("Where <os> is one of 'linux', 'darwin' or 'windows'.")
			os.Exit(-1)
		}
		t := template.Must(template.ParseFiles("doc/installation.txt"))
		data := struct {
			Os string
		}{
			op.Extra[1],
		}

		w, err := os.OpenFile(filepath.Join(op.Extra[2], "installation.txt"), os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
		if err != nil {
			fmt.Println(err)
			os.Exit(-1)
		}

		err = t.Execute(w, data)
		if err != nil {
			fmt.Println(err)
			os.Exit(-1)
		}

	case "sourcedoc":
		// 1 = srcpath, 2 = outpath, 3 = assets, 4 = images
		err := sourcedoc.GenSourcedoc(filepath.Join(cfg.Srcdir, "lua"), filepath.Join(cfg.Builddir, "sourcedoc"), filepath.Join(cfg.Basedir(), "doc", "sourcedoc", "assets"), filepath.Join(cfg.Basedir(), "doc", "sourcedoc", "img"))
		if err != nil {
			log.Fatal(err)
		}
	case "translate":
		if len(op.Extra) > 1 {
			if len(op.Extra) > 2 {
				err = translatelayout.Translate(basedir, op.Extra[1], op.Extra[2])
				if err != nil {
					log.Fatal(err)
				}
			} else {
				err = translatelayout.Translate(basedir, op.Extra[1], "")
				if err != nil {
					log.Fatal(err)
				}
			}
		} else {
			fmt.Println("translate needs the input and output filename: sphelper translate infile.xml [outfile.xml]")
			os.Exit(-1)
		}
	default:
		op.Help()
		os.Exit(-1)
	}
}