annotate cmd/gemma/main.go @ 5490:5f47eeea988d logging

Use own logging package.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 20 Sep 2021 17:45:39 +0200
parents fdbc28a71691
children 0cd4ff1066fe
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1017
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
1 // This is Free Software under GNU Affero General Public License v >= 3.0
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
2 // without warranty, see README.md and license for details.
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
3 //
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
4 // SPDX-License-Identifier: AGPL-3.0-or-later
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
5 // License-Filename: LICENSES/AGPL-3.0.txt
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
6 //
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
7 // Copyright (C) 2018 by via donau
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
8 // – Österreichische Wasserstraßen-Gesellschaft mbH
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
9 // Software engineering by Intevation GmbH
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
10 //
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
11 // Author(s):
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de>
a244b18cb916 Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1000
diff changeset
13
4399
349e409fbbb1 server, docs: add overview comment for cmds
Bernhard Reiter <bernhard@intevation.de>
parents: 4168
diff changeset
14 // Command gemma starts the middleware server
349e409fbbb1 server, docs: add overview comment for cmds
Bernhard Reiter <bernhard@intevation.de>
parents: 4168
diff changeset
15 // for waterway monitoring and management.
248
21cf31a7d9e1 main.go of gemma lost version tracking.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
16 package main
21cf31a7d9e1 main.go of gemma lost version tracking.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
17
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
18 import (
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
19 "context"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
20 "fmt"
5490
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
21 lg "log"
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
22 "net/http"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
23 "os"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
24 "os/signal"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
25 "path/filepath"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
26 "syscall"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
27
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
28 "github.com/gorilla/mux"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
29 "github.com/rs/cors"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
30 "github.com/spf13/cobra"
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
31
414
c1047fd04a3a Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 386
diff changeset
32 "gemma.intevation.de/gemma/pkg/auth"
c1047fd04a3a Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 386
diff changeset
33 "gemma.intevation.de/gemma/pkg/config"
c1047fd04a3a Moved project specific Go packages to new pkg folder.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 386
diff changeset
34 "gemma.intevation.de/gemma/pkg/controllers"
868
aa8f30c1ed27 Moved GeoServer configuration to own package.
Sascha L. Teichmann <teichmann@intevation.de>
parents: 867
diff changeset
35 "gemma.intevation.de/gemma/pkg/geoserver"
3246
64324aaeb1fb Made logging of waht is registered to the scheduler and the import queue more deterministic.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 3244
diff changeset
36 "gemma.intevation.de/gemma/pkg/imports"
5490
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
37 "gemma.intevation.de/gemma/pkg/log"
5283
fdbc28a71691 Made setting of No Sniff headers for served files a reusable middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 4829
diff changeset
38 "gemma.intevation.de/gemma/pkg/middleware"
3246
64324aaeb1fb Made logging of waht is registered to the scheduler and the import queue more deterministic.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 3244
diff changeset
39 "gemma.intevation.de/gemma/pkg/scheduler"
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
40 )
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
41
493
8a0737aa6ab6 The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 414
diff changeset
42 func prepareSessionStore() {
8a0737aa6ab6 The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 414
diff changeset
43 // Install session store
8a0737aa6ab6 The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 414
diff changeset
44 ss, err := auth.NewSessionStore(config.SessionStore())
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
45 if err != nil {
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
46 log.Fatalf("Error with session store: %v\n", err)
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
47 }
493
8a0737aa6ab6 The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 414
diff changeset
48 auth.Sessions = ss
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
49 }
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
50
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
51 func start(cmd *cobra.Command, args []string) {
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
52
1000
14425e35e3c2 Wait with start of import queue until configuration is fully loaded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 978
diff changeset
53 config.Ready()
14425e35e3c2 Wait with start of import queue until configuration is fully loaded.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 978
diff changeset
54
5490
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
55 if lf := config.LogFile(); lf != "" {
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
56 log.SetupLog(lf, 0666)
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
57 defer log.ShutdownLog()
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
58 }
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
59
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
60 log.SetLogLevel(config.LogLevel())
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
61
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
62 web, err := filepath.Abs(config.Web())
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
63 if err != nil {
5490
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
64 log.Fatalf("%v\n", err)
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
65 }
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
66
493
8a0737aa6ab6 The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 414
diff changeset
67 prepareSessionStore()
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
68
386
999f4f83a072 Configure GeoServer via REST-API. TODO: Configure layers.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 332
diff changeset
69 // Do GeoServer setup in background.
890
0a563fef64a9 Reconfiguring GeoServer is now queued async.
Sascha L. Teichmann <teichmann@intevation.de>
parents: 868
diff changeset
70 geoserver.Reconfigure(geoserver.PrepareGeoServer)
386
999f4f83a072 Configure GeoServer via REST-API. TODO: Configure layers.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 332
diff changeset
71
4160
7cccf7fef3e8 Made 'golint' and 'staticcheck' happy with auth package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 3972
diff changeset
72 // Log what's registered to the import queue and scheduler.
3246
64324aaeb1fb Made logging of waht is registered to the scheduler and the import queue more deterministic.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 3244
diff changeset
73 imports.LogImportKindNames()
64324aaeb1fb Made logging of waht is registered to the scheduler and the import queue more deterministic.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 3244
diff changeset
74 scheduler.LogActionNames()
64324aaeb1fb Made logging of waht is registered to the scheduler and the import queue more deterministic.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 3244
diff changeset
75
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
76 m := mux.NewRouter()
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
77 controllers.BindRoutes(m)
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
78
5283
fdbc28a71691 Made setting of No Sniff headers for served files a reusable middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 4829
diff changeset
79 dir := middleware.NoSniff(http.FileServer(http.Dir(web)))
4829
f4ec3558460e Set some nosniff http headers.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 4399
diff changeset
80
5283
fdbc28a71691 Made setting of No Sniff headers for served files a reusable middleware.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 4829
diff changeset
81 m.PathPrefix("/").Handler(dir)
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
82
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
83 addr := fmt.Sprintf("%s:%d", config.WebHost(), config.WebPort())
5490
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
84 log.Infof("listen on %s\n", addr)
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
85
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
86 var h http.Handler
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
87
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
88 if al := config.AllowedOrigins(); len(al) > 0 {
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
89 c := cors.New(cors.Options{
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
90 AllowedOrigins: al,
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
91 Debug: true,
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
92 })
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
93 h = c.Handler(m)
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
94 } else {
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
95 h = m
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
96 }
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
97
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
98 server := http.Server{Addr: addr, Handler: h}
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
99
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
100 done := make(chan error)
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
101
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
102 go func() {
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
103 defer close(done)
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
104 done <- server.ListenAndServe()
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
105 }()
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
106
3972
72473ebd9d64 Bufferd kill signal channel to not miss signals if recieving code is not ready.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 3246
diff changeset
107 sigChan := make(chan os.Signal, 1)
4168
3ef3f8a99d5e Don't trap SIGKILL. This is handled by the OS. Found by staticcheck.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 4160
diff changeset
108 signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
109
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
110 select {
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
111 case err := <-done:
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
112 if err != nil && err != http.ErrServerClosed {
5490
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
113 log.Fatalf("%v\n", err)
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
114 }
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
115 case <-sigChan:
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
116 }
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
117
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
118 server.Shutdown(context.Background())
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
119
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
120 <-done
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
121
493
8a0737aa6ab6 The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 414
diff changeset
122 if err := auth.Sessions.Shutdown(); err != nil {
5490
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
123 log.Fatalf("%v\n", err)
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
124 }
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
125 }
248
21cf31a7d9e1 main.go of gemma lost version tracking.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
126
21cf31a7d9e1 main.go of gemma lost version tracking.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
127 func main() {
332
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
128 config.RootCmd.Run = start
394fafeb4052 Use viper as config storage (I don't like it).
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 248
diff changeset
129 if err := config.RootCmd.Execute(); err != nil {
5490
5f47eeea988d Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 5283
diff changeset
130 lg.Fatalln(err)
248
21cf31a7d9e1 main.go of gemma lost version tracking.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
131 }
21cf31a7d9e1 main.go of gemma lost version tracking.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
132 }