aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.md1
-rw-r--r--logger/logger.go290
-rw-r--r--main.go30
3 files changed, 316 insertions, 5 deletions
diff --git a/TODO.md b/TODO.md
index 9dbecc4..64f4269 100644
--- a/TODO.md
+++ b/TODO.md
@@ -32,6 +32,7 @@ priority 2
- [ ] maybe use an LRU cache instead of the current FIFO one.
- [x] remove `LoadedChunk` and only use `StoredChunk` instead now that the cache
is implemented
+- [ ] store file list compressed
reunion 7/09
------------
diff --git a/logger/logger.go b/logger/logger.go
new file mode 100644
index 0000000..c47d268
--- /dev/null
+++ b/logger/logger.go
@@ -0,0 +1,290 @@
+// Package logger offers simple logging
+package logger
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "runtime/debug"
+ "sync"
+)
+
+type severity int
+
+type logger interface {
+ Output(calldepth int, s string) error
+ SetFlags(flag int)
+}
+
+// Severity levels.
+const (
+ sInfo severity = iota
+ sWarning
+ sError
+ sFatal
+)
+
+// Severity tags.
+const (
+ tagInfo = "[INFO] "
+ tagWarning = "[WARN] "
+ tagError = "[ERROR] "
+ tagFatal = "[FATAL] "
+)
+
+const (
+ flags = log.Lmsgprefix | log.LstdFlags | log.Lshortfile
+)
+
+var (
+ logLock sync.Mutex
+ defaultLogger *Logger
+)
+
+// initialize resets defaultLogger. Which allows tests to reset environment.
+func initialize() {
+ defaultLogger = &Logger{
+ loggers: []logger{
+ log.New(os.Stderr, tagInfo, flags),
+ log.New(os.Stderr, tagWarning, flags),
+ log.New(os.Stderr, tagError, flags),
+ log.New(os.Stderr, tagFatal, flags),
+ },
+ level: 3,
+ }
+}
+
+func init() {
+ initialize()
+}
+
+// Init sets up logging and should be called before log functions, usually in
+// the caller's main(). Default log functions can be called before Init(), but
+// every severity will be logged.
+// The first call to Init populates the default logger and returns the
+// generated logger, subsequent calls to Init will only return the generated
+// logger.
+func Init(level int) *Logger {
+
+ loggers := []logger{
+ log.New(os.Stderr, tagInfo, flags),
+ log.New(os.Stderr, tagWarning, flags),
+ log.New(os.Stderr, tagError, flags),
+ log.New(os.Stderr, tagFatal, flags),
+ }
+ l := Logger{loggers: loggers, level: level, initialized: true}
+
+ logLock.Lock()
+ defer logLock.Unlock()
+ if !defaultLogger.initialized {
+ defaultLogger = &l
+ }
+
+ return &l
+}
+
+// A Logger represents an active logging object. Multiple loggers can be used
+// simultaneously even if they are using the same writers.
+type Logger struct {
+ loggers []logger
+ level int
+ initialized bool
+}
+
+func (l *Logger) output(s severity, depth int, txt string) {
+ if s < sFatal-severity(l.level) {
+ return
+ }
+ logLock.Lock()
+ defer logLock.Unlock()
+ if int(s) >= len(l.loggers) {
+ panic(fmt.Sprintln("unrecognized severity:", s))
+ }
+ l.loggers[s].Output(3+depth, txt)
+}
+
+// SetFlags sets the output flags for the logger.
+func (l *Logger) SetFlags(flag int) {
+ for _, logger := range l.loggers {
+ logger.SetFlags(flag)
+ }
+}
+
+// Info logs with the Info severity.
+// Arguments are handled in the manner of fmt.Print.
+func (l *Logger) Info(v ...interface{}) {
+ l.output(sInfo, 0, fmt.Sprint(v...))
+}
+
+// InfoDepth acts as Info but uses depth to determine which call frame to log.
+// InfoDepth(0, "msg") is the same as Info("msg").
+func (l *Logger) InfoDepth(depth int, v ...interface{}) {
+ l.output(sInfo, depth, fmt.Sprint(v...))
+}
+
+// Infoln logs with the Info severity.
+// Arguments are handled in the manner of fmt.Println.
+func (l *Logger) Infoln(v ...interface{}) {
+ l.output(sInfo, 0, fmt.Sprintln(v...))
+}
+
+// Infof logs with the Info severity.
+// Arguments are handled in the manner of fmt.Printf.
+func (l *Logger) Infof(format string, v ...interface{}) {
+ l.output(sInfo, 0, fmt.Sprintf(format, v...))
+}
+
+// Warning logs with the Warning severity.
+// Arguments are handled in the manner of fmt.Print.
+func (l *Logger) Warning(v ...interface{}) {
+ l.output(sWarning, 0, fmt.Sprint(v...))
+}
+
+// WarningDepth acts as Warning but uses depth to determine which call frame to log.
+// WarningDepth(0, "msg") is the same as Warning("msg").
+func (l *Logger) WarningDepth(depth int, v ...interface{}) {
+ l.output(sWarning, depth, fmt.Sprint(v...))
+}
+
+// Warningln logs with the Warning severity.
+// Arguments are handled in the manner of fmt.Println.
+func (l *Logger) Warningln(v ...interface{}) {
+ l.output(sWarning, 0, fmt.Sprintln(v...))
+}
+
+// Warningf logs with the Warning severity.
+// Arguments are handled in the manner of fmt.Printf.
+func (l *Logger) Warningf(format string, v ...interface{}) {
+ l.output(sWarning, 0, fmt.Sprintf(format, v...))
+}
+
+// Error logs with the ERROR severity.
+// Arguments are handled in the manner of fmt.Print.
+func (l *Logger) Error(v ...interface{}) {
+ l.output(sError, 0, fmt.Sprint(v...))
+}
+
+// ErrorDepth acts as Error but uses depth to determine which call frame to log.
+// ErrorDepth(0, "msg") is the same as Error("msg").
+func (l *Logger) ErrorDepth(depth int, v ...interface{}) {
+ l.output(sError, depth, fmt.Sprint(v...))
+}
+
+// Errorln logs with the ERROR severity.
+// Arguments are handled in the manner of fmt.Println.
+func (l *Logger) Errorln(v ...interface{}) {
+ l.output(sError, 0, fmt.Sprintln(v...))
+}
+
+// Errorf logs with the Error severity.
+// Arguments are handled in the manner of fmt.Printf.
+func (l *Logger) Errorf(format string, v ...interface{}) {
+ l.output(sError, 0, fmt.Sprintf(format, v...))
+}
+
+// Fatal logs with the Fatal severity, and ends with os.Exit(1).
+// Arguments are handled in the manner of fmt.Print.
+func (l *Logger) Fatal(v ...interface{}) {
+ l.output(sFatal, 0, fmt.Sprint(v...))
+ os.Exit(1)
+}
+
+// Fatalln logs with the Fatal severity, and ends with os.Exit(1).
+// Arguments are handled in the manner of fmt.Println.
+func (l *Logger) Fatalln(v ...interface{}) {
+ l.output(sFatal, 0, fmt.Sprintln(v...))
+ os.Exit(1)
+}
+
+// Fatalf logs with the Fatal severity, and ends with os.Exit(1).
+// Arguments are handled in the manner of fmt.Printf.
+func (l *Logger) Fatalf(format string, v ...interface{}) {
+ l.output(sFatal, 0, fmt.Sprintf(format, v...))
+ os.Exit(1)
+}
+
+// SetFlags sets the output flags for the logger.
+func SetFlags(flag int) {
+ defaultLogger.SetFlags(flag)
+}
+
+// Info uses the default logger and logs with the Info severity.
+// Arguments are handled in the manner of fmt.Print.
+func Info(v ...interface{}) {
+ defaultLogger.output(sInfo, 0, fmt.Sprint(v...))
+}
+
+// Infoln uses the default logger and logs with the Info severity.
+// Arguments are handled in the manner of fmt.Println.
+func Infoln(v ...interface{}) {
+ defaultLogger.output(sInfo, 0, fmt.Sprintln(v...))
+}
+
+// Infof uses the default logger and logs with the Info severity.
+// Arguments are handled in the manner of fmt.Printf.
+func Infof(format string, v ...interface{}) {
+ defaultLogger.output(sInfo, 0, fmt.Sprintf(format, v...))
+}
+
+// Warning uses the default logger and logs with the Warning severity.
+// Arguments are handled in the manner of fmt.Print.
+func Warning(v ...interface{}) {
+ defaultLogger.output(sWarning, 0, fmt.Sprint(v...))
+}
+
+// Warningln uses the default logger and logs with the Warning severity.
+// Arguments are handled in the manner of fmt.Println.
+func Warningln(v ...interface{}) {
+ defaultLogger.output(sWarning, 0, fmt.Sprintln(v...))
+}
+
+// Warningf uses the default logger and logs with the Warning severity.
+// Arguments are handled in the manner of fmt.Printf.
+func Warningf(format string, v ...interface{}) {
+ defaultLogger.output(sWarning, 0, fmt.Sprintf(format, v...))
+}
+
+// Error uses the default logger and logs with the Error severity.
+// Arguments are handled in the manner of fmt.Print.
+func Error(v ...interface{}) {
+ defaultLogger.output(sError, 0, fmt.Sprint(v...))
+}
+
+// Errorln uses the default logger and logs with the Error severity.
+// Arguments are handled in the manner of fmt.Println.
+func Errorln(v ...interface{}) {
+ defaultLogger.output(sError, 0, fmt.Sprintln(v...))
+}
+
+// Errorf uses the default logger and logs with the Error severity.
+// Arguments are handled in the manner of fmt.Printf.
+func Errorf(format string, v ...interface{}) {
+ defaultLogger.output(sError, 0, fmt.Sprintf(format, v...))
+}
+
+// Fatal uses the default logger, logs with the Fatal severity,
+// and ends with os.Exit(1).
+// Arguments are handled in the manner of fmt.Print.
+func Fatal(v ...interface{}) {
+ defaultLogger.output(sFatal, 0, fmt.Sprint(v...))
+ debug.PrintStack()
+ os.Exit(1)
+}
+
+// Fatalln uses the default logger, logs with the Fatal severity,
+// and ends with os.Exit(1).
+// Arguments are handled in the manner of fmt.Println.
+func Fatalln(v ...interface{}) {
+ defaultLogger.output(sFatal, 0, fmt.Sprintln(v...))
+ debug.PrintStack()
+ os.Exit(1)
+}
+
+// Fatalf uses the default logger, logs with the Fatal severity,
+// and ends with os.Exit(1).
+// Arguments are handled in the manner of fmt.Printf.
+func Fatalf(format string, v ...interface{}) {
+ defaultLogger.output(sFatal, 0, fmt.Sprintf(format, v...))
+ debug.PrintStack()
+ os.Exit(1)
+}
diff --git a/main.go b/main.go
index 691ff25..b813954 100644
--- a/main.go
+++ b/main.go
@@ -1,19 +1,39 @@
package main
import (
+ "flag"
"fmt"
"os"
+
+ "github.com/n-peugnet/dna-backup/logger"
)
-func main() {
+const (
+ usage = "usage: dna-backup [<options>] [--] <source> <dest>\n\noptions:\n"
+)
+
+var (
+ logLevel int
+)
- if len(os.Args) != 3 {
- fmt.Println("usage: dna-backup <source> <dest>")
+func init() {
+ flag.IntVar(&logLevel, "v", 1, "log verbosity level (0-3)")
+}
+
+func main() {
+ flag.Usage = func() {
+ fmt.Fprintf(flag.CommandLine.Output(), usage)
+ flag.PrintDefaults()
+ }
+ flag.Parse()
+ logger.Init(logLevel)
+ if len(flag.Args()) != 2 {
+ flag.Usage()
os.Exit(1)
}
- source := os.Args[1]
- dest := os.Args[2]
+ source := os.Args[0]
+ dest := os.Args[1]
repo := NewRepo(dest)
repo.Commit(source)
}