From f9939bc286765276d50f543bd76823ad3aacccb8 Mon Sep 17 00:00:00 2001 From: Faissal Elamraoui Date: Sun, 19 Mar 2017 23:41:36 +0100 Subject: [PATCH] Add support for Delve This adds support for debugging tool Delve. The command dlv starts a debugging REPL that allows the user to debug his application using Delve tool. Resolves #365. --- cmd/bee.go | 3 +- cmd/commands/dlv/dlv.go | 109 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 cmd/commands/dlv/dlv.go diff --git a/cmd/bee.go b/cmd/bee.go index 702340e..8cf15aa 100644 --- a/cmd/bee.go +++ b/cmd/bee.go @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations // under the License. -// Bee is a tool for developing applications based on beego framework. +// Package cmd ... package cmd import ( @@ -20,6 +20,7 @@ import ( _ "github.com/beego/bee/cmd/commands/api" _ "github.com/beego/bee/cmd/commands/bale" _ "github.com/beego/bee/cmd/commands/beefix" + _ "github.com/beego/bee/cmd/commands/dlv" _ "github.com/beego/bee/cmd/commands/dockerize" _ "github.com/beego/bee/cmd/commands/generate" _ "github.com/beego/bee/cmd/commands/hprose" diff --git a/cmd/commands/dlv/dlv.go b/cmd/commands/dlv/dlv.go new file mode 100644 index 0000000..dbd7080 --- /dev/null +++ b/cmd/commands/dlv/dlv.go @@ -0,0 +1,109 @@ +// Copyright 2017 bee authors +// +// Licensed under the Apache License, Version 2.0 (the "License"): you may +// not use this file except in compliance with the License. You may obtain +// a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations +// under the License. + +// Package dlv ... +package dlv + +import ( + "flag" + "fmt" + "os/exec" + + "github.com/beego/bee/cmd/commands" + "github.com/beego/bee/cmd/commands/version" + beeLogger "github.com/beego/bee/logger" + "github.com/derekparker/delve/pkg/terminal" + "github.com/derekparker/delve/service" + "github.com/derekparker/delve/service/rpc2" + + dlvConfig "github.com/derekparker/delve/pkg/config" +) + +var cmdDlv = &commands.Command{ + CustomFlags: true, + UsageLine: "dlv [-package=\"\"] [-port=8181]", + Short: "Start a debugging session using Delve", + Long: `dlv command start a debugging session using debugging tool Delve. + + To debug your application using Delve, use: {{"$ bee dlv" | bold}} + + For more information on Delve: https://github.com/derekparker/delve +`, + PreRun: func(cmd *commands.Command, args []string) { version.ShowShortVersionBanner() }, + Run: runDlv, +} + +var ( + packageName string + port string +) + +func init() { + fs := flag.NewFlagSet("dlv", flag.ContinueOnError) + fs.StringVar(&port, "port", "8181", "Port to listen to for clients") + fs.StringVar(&packageName, "package", "", "The package to debug (Must have a main package)") + cmdDlv.Flag = *fs + commands.AvailableCommands = append(commands.AvailableCommands, cmdDlv) +} + +func runDlv(cmd *commands.Command, args []string) int { + if err := cmd.Flag.Parse(args); err != nil { + beeLogger.Log.Fatalf("Error parsing flags: %v", err.Error()) + } + addr := fmt.Sprintf("127.0.0.1:%s", port) + + startChan := make(chan bool) + defer close(startChan) + + go runDelve(addr, startChan) + + if started := <-startChan; started { + beeLogger.Log.Info("Starting Delve Debugger...") + status, err := startRepl(addr) + if err != nil { + beeLogger.Log.Fatal(err.Error()) + } + return status + } + return 0 +} + +// runDelve runs the Delve debugger in API mode +func runDelve(addr string, c chan bool) { + args := []string{ + "debug", + "--headless", + "--accept-multiclient=true", + "--api-version=2", + fmt.Sprintf("--listen=%s", addr), + } + if err := exec.Command("dlv", args...).Start(); err == nil { + c <- true + } +} + +// startRepl starts the Delve REPL +func startRepl(addr string) (int, error) { + var client service.Client + client = rpc2.NewClient(addr) + term := terminal.New(client, dlvConfig.LoadConfig()) + + status, err := term.Run() + if err != nil { + return status, err + } + defer term.Close() + + return 0, nil +}