()
| 88 | var localClient *tailscale.LocalClient |
| 89 | |
| 90 | func Run() error { |
| 91 | flag.Parse() |
| 92 | |
| 93 | hostinfo.SetApp("golink") |
| 94 | |
| 95 | // if resolving from backup, set sqlitefile and snapshot flags to |
| 96 | // restore links into an in-memory sqlite database. |
| 97 | if *resolveFromBackup != "" { |
| 98 | *sqlitefile = ":memory:" |
| 99 | snapshot = resolveFromBackup |
| 100 | if flag.NArg() != 1 { |
| 101 | log.Fatal("--resolve-from-backup also requires a link to be resolved") |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | if *sqlitefile == "" { |
| 106 | if devMode() { |
| 107 | tmpdir, err := os.MkdirTemp("", "golink_dev_*") |
| 108 | if err != nil { |
| 109 | return err |
| 110 | } |
| 111 | *sqlitefile = filepath.Join(tmpdir, "golink.db") |
| 112 | log.Printf("Dev mode temp db: %s", *sqlitefile) |
| 113 | } else { |
| 114 | return errors.New("--sqlitedb is required") |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | var err error |
| 119 | if db, err = NewSQLiteDB(*sqlitefile); err != nil { |
| 120 | return fmt.Errorf("NewSQLiteDB(%q): %w", *sqlitefile, err) |
| 121 | } |
| 122 | |
| 123 | if *snapshot != "" { |
| 124 | if LastSnapshot != nil { |
| 125 | log.Printf("LastSnapshot already set; ignoring --snapshot") |
| 126 | } else { |
| 127 | var err error |
| 128 | LastSnapshot, err = os.ReadFile(*snapshot) |
| 129 | if err != nil { |
| 130 | log.Fatalf("error reading snapshot file %q: %v", *snapshot, err) |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | if err := restoreLastSnapshot(); err != nil { |
| 135 | log.Printf("restoring snapshot: %v", err) |
| 136 | } |
| 137 | if err := initStats(); err != nil { |
| 138 | log.Printf("initializing stats: %v", err) |
| 139 | } |
| 140 | |
| 141 | // if link specified on command line, resolve and exit |
| 142 | if flag.NArg() > 0 { |
| 143 | u, err := url.Parse(flag.Arg(0)) |
| 144 | if err != nil { |
| 145 | log.Fatal(err) |
| 146 | } |
| 147 | dst, err := resolveLink(u) |
no test coverage detected