mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-21 01:26:48 +00:00
Import/Export backend
This commit is contained in:
35
internal/cmd/args.go
Normal file
35
internal/cmd/args.go
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2020 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// filterProcessSerialNumberFromArgs removes additional flag from MacOS. More info ProcessSerialNumber
|
||||
// http://mirror.informatimago.com/next/developer.apple.com/documentation/Carbon/Reference/Process_Manager/prmref_main/data_type_5.html#//apple_ref/doc/uid/TP30000208/C001951
|
||||
func filterProcessSerialNumberFromArgs() {
|
||||
tmp := os.Args[:0]
|
||||
for _, arg := range os.Args {
|
||||
if !strings.Contains(arg, "-psn_") {
|
||||
tmp = append(tmp, arg)
|
||||
}
|
||||
}
|
||||
os.Args = tmp
|
||||
}
|
||||
86
internal/cmd/main.go
Normal file
86
internal/cmd/main.go
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright (c) 2020 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/pkg/constants"
|
||||
"github.com/getsentry/raven-go"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
log = logrus.WithField("pkg", "cmd") //nolint[gochecknoglobals]
|
||||
|
||||
baseFlags = []cli.Flag{ //nolint[gochecknoglobals]
|
||||
cli.StringFlag{
|
||||
Name: "log-level, l",
|
||||
Usage: "Set the log level (one of panic, fatal, error, warn, info, debug, debug-client, debug-server)"},
|
||||
cli.BoolFlag{
|
||||
Name: "cli, c",
|
||||
Usage: "Use command line interface"},
|
||||
cli.StringFlag{
|
||||
Name: "version-json, g",
|
||||
Usage: "Generate json version file"},
|
||||
cli.BoolFlag{
|
||||
Name: "mem-prof, m",
|
||||
Usage: "Generate memory profile"},
|
||||
cli.BoolFlag{
|
||||
Name: "cpu-prof, p",
|
||||
Usage: "Generate CPU profile"},
|
||||
}
|
||||
)
|
||||
|
||||
// Main sets up Sentry, filters out unwanted args, creates app and runs it.
|
||||
func Main(appName, usage string, extraFlags []cli.Flag, run func(*cli.Context) error) {
|
||||
if err := raven.SetDSN(constants.DSNSentry); err != nil {
|
||||
log.WithError(err).Errorln("Can not setup sentry DSN")
|
||||
}
|
||||
raven.SetRelease(constants.Revision)
|
||||
|
||||
filterProcessSerialNumberFromArgs()
|
||||
filterRestartNumberFromArgs()
|
||||
|
||||
app := newApp(appName, usage, extraFlags, run)
|
||||
|
||||
logrus.SetLevel(logrus.InfoLevel)
|
||||
log.WithField("version", constants.Version).
|
||||
WithField("revision", constants.Revision).
|
||||
WithField("build", constants.BuildTime).
|
||||
WithField("runtime", runtime.GOOS).
|
||||
WithField("args", os.Args).
|
||||
WithField("appName", app.Name).
|
||||
Info("Run app")
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
log.Error("Program exited with error: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func newApp(appName, usage string, extraFlags []cli.Flag, run func(*cli.Context) error) *cli.App {
|
||||
app := cli.NewApp()
|
||||
app.Name = appName
|
||||
app.Usage = usage
|
||||
app.Version = constants.BuildVersion
|
||||
app.Flags = append(baseFlags, extraFlags...) //nolint[gocritic]
|
||||
app.Action = run
|
||||
return app
|
||||
}
|
||||
43
internal/cmd/memory_profile.go
Normal file
43
internal/cmd/memory_profile.go
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2020 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
)
|
||||
|
||||
// MakeMemoryProfile generates memory pprof.
|
||||
func MakeMemoryProfile() {
|
||||
name := "./mem.pprof"
|
||||
f, err := os.Create(name)
|
||||
if err != nil {
|
||||
log.Error("Could not create memory profile: ", err)
|
||||
}
|
||||
if abs, err := filepath.Abs(name); err == nil {
|
||||
name = abs
|
||||
}
|
||||
log.Info("Writing memory profile to ", name)
|
||||
runtime.GC() // get up-to-date statistics
|
||||
if err := pprof.WriteHeapProfile(f); err != nil {
|
||||
log.Error("Could not write memory profile: ", err)
|
||||
}
|
||||
_ = f.Close()
|
||||
}
|
||||
108
internal/cmd/restart.go
Normal file
108
internal/cmd/restart.go
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2020 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ProtonMail/proton-bridge/internal/frontend"
|
||||
"github.com/ProtonMail/proton-bridge/pkg/config"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
// After how many crashes app gives up starting.
|
||||
maxAllowedCrashes = 10
|
||||
)
|
||||
|
||||
var (
|
||||
// How many crashes happened so far in a row.
|
||||
// It will be filled from args by `filterRestartNumberFromArgs`.
|
||||
// Every call of `HandlePanic` will increase this number.
|
||||
// Then it will be passed as argument to the next try by `RestartApp`.
|
||||
numberOfCrashes = 0 //nolint[gochecknoglobals]
|
||||
)
|
||||
|
||||
// filterRestartNumberFromArgs removes flag with a number how many restart we already did.
|
||||
// See restartApp how that number is used.
|
||||
func filterRestartNumberFromArgs() {
|
||||
tmp := os.Args[:0]
|
||||
for i, arg := range os.Args {
|
||||
if !strings.HasPrefix(arg, "--restart_") {
|
||||
tmp = append(tmp, arg)
|
||||
continue
|
||||
}
|
||||
var err error
|
||||
numberOfCrashes, err = strconv.Atoi(os.Args[i][10:])
|
||||
if err != nil {
|
||||
numberOfCrashes = maxAllowedCrashes
|
||||
}
|
||||
}
|
||||
os.Args = tmp
|
||||
}
|
||||
|
||||
// DisableRestart disables restart once `RestartApp` is called.
|
||||
func DisableRestart() {
|
||||
numberOfCrashes = maxAllowedCrashes
|
||||
}
|
||||
|
||||
// RestartApp starts a new instance in background.
|
||||
func RestartApp() {
|
||||
if numberOfCrashes >= maxAllowedCrashes {
|
||||
log.Error("Too many crashes")
|
||||
return
|
||||
}
|
||||
if exeFile, err := os.Executable(); err == nil {
|
||||
arguments := append(os.Args[1:], fmt.Sprintf("--restart_%d", numberOfCrashes))
|
||||
cmd := exec.Command(exeFile, arguments...) //nolint[gosec]
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdin = os.Stdin
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Error("Restart failed: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PanicHandler defines HandlePanic which can be used anywhere in defer.
|
||||
type PanicHandler struct {
|
||||
AppName string
|
||||
Config *config.Config
|
||||
Err *error // Pointer to error of cli action.
|
||||
}
|
||||
|
||||
// HandlePanic should be called in defer to ensure restart of app after error.
|
||||
func (ph *PanicHandler) HandlePanic() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
|
||||
config.HandlePanic(ph.Config, fmt.Sprintf("Recover: %v", r))
|
||||
frontend.HandlePanic(ph.AppName)
|
||||
|
||||
*ph.Err = cli.NewExitError("Panic and restart", 255)
|
||||
numberOfCrashes++
|
||||
log.Error("Restarting after panic")
|
||||
RestartApp()
|
||||
os.Exit(255)
|
||||
}
|
||||
32
internal/cmd/version_file.go
Normal file
32
internal/cmd/version_file.go
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2020 Proton Technologies AG
|
||||
//
|
||||
// This file is part of ProtonMail Bridge.
|
||||
//
|
||||
// ProtonMail Bridge is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// ProtonMail Bridge is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with ProtonMail Bridge. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import "github.com/ProtonMail/proton-bridge/pkg/updates"
|
||||
|
||||
// GenerateVersionFiles writes a JSON file with details about current build.
|
||||
// Those files are used for upgrading the app.
|
||||
func GenerateVersionFiles(updates *updates.Updates, dir string) {
|
||||
log.Info("Generating version files")
|
||||
for _, goos := range []string{"windows", "darwin", "linux"} {
|
||||
log.Debug("Generating JSON for ", goos)
|
||||
if err := updates.CreateJSONAndSign(dir, goos); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user