Skip to content

Commit

Permalink
git add forapp
Browse files Browse the repository at this point in the history
  • Loading branch information
mjanson committed Mar 13, 2024
1 parent 60b471c commit 67dcd37
Show file tree
Hide file tree
Showing 8 changed files with 903 additions and 15 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@

3. 等待编译完成,点击任务进入详情页
4. 在详情页下载插件压缩包![image](https://user-images.githubusercontent.com/1214708/153843272-81843b45-6dc8-4945-871f-a9a467f63c33.png)

## ForkApp

1. ./forkapp forkapp -from ../applications/luci-app-plex -to ../applications/luci-app-demo
2. ./forkapp upload -ip 192.168.100.1 -pwd "password" -from ../applications/luci-app-demo -to /root/
3. ./forkapp upload -ip 192.168.100.1 -pwd "password" -from ../applications/luci-app-demo -to /root/ -script ../tools/simple-install.sh -install
15 changes: 0 additions & 15 deletions applications/luci-app-ubuntu/simple-install.sh

This file was deleted.

126 changes: 126 additions & 0 deletions forkapp/copydir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package main

import (
"fmt"
"io"
"os"
"path/filepath"
"syscall"
)

type ChangePathFunc func(srcFile, dstFile string) string
type CopyFunc func(srcFile, dstFile string, overwrite bool) error

func CopyDirectory(scrDir, dest string, overwrite bool, changePathFn ChangePathFunc, cpFn CopyFunc) error {
entries, err := os.ReadDir(scrDir)
if err != nil {
return err
}
for _, entry := range entries {
sourcePath := filepath.Join(scrDir, entry.Name())
fileInfo, err := os.Stat(sourcePath)
if err != nil {
return err
}

var statOk bool
stat, ok := fileInfo.Sys().(*syscall.Stat_t)
if ok {
statOk = true
}

destPath := filepath.Join(dest, entry.Name())
destPath = changePathFn(sourcePath, destPath)

switch fileInfo.Mode() & os.ModeType {
case os.ModeDir:
if err = CreateIfNotExists(destPath, 0755); err != nil {
return err
}
if err = CopyDirectory(sourcePath, destPath, overwrite, changePathFn, cpFn); err != nil {
return err
}
case os.ModeSymlink:
if err = CopySymLink(sourcePath, destPath); err != nil {
return err
}
default:
if err = cpFn(sourcePath, destPath, overwrite); err != nil {
return err
}
}

if statOk {
if err := os.Lchown(destPath, int(stat.Uid), int(stat.Gid)); err != nil {
return err
}
}

fInfo, err := entry.Info()
if err != nil {
return err
}

isSymlink := fInfo.Mode()&os.ModeSymlink != 0
if !isSymlink {
if err := os.Chmod(destPath, fInfo.Mode()); err != nil {
return err
}
}
}
return nil
}

func Copy(srcFile, dstFile string, overwrite bool) error {
if !overwrite && Exists(dstFile) {
return nil
}
out, err := os.Create(dstFile)
if err != nil {
return err
}

defer out.Close()

in, err := os.Open(srcFile)
if err != nil {
return err
}

defer in.Close()

_, err = io.Copy(out, in)
if err != nil {
return err
}

return nil
}

func Exists(filePath string) bool {
if _, err := os.Stat(filePath); os.IsNotExist(err) {
return false
}

return true
}

func CreateIfNotExists(dir string, perm os.FileMode) error {
if Exists(dir) {
return nil
}

if err := os.MkdirAll(dir, perm); err != nil {
return fmt.Errorf("failed to create directory: '%s', error: '%s'", dir, err.Error())
}

return nil
}

func CopySymLink(source, dest string) error {
link, err := os.Readlink(source)
if err != nil {
return err
}
return os.Symlink(link, dest)
}
214 changes: 214 additions & 0 deletions forkapp/forkapp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package main

import (
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"path"
"path/filepath"
"strings"

"github.com/urfave/cli"
)

func doForkApp(fromPath, toPath, fromApp, toApp string, replaces []string, force bool) error {
p := len("luci-app-")
fromApp = fromApp[p:]
toApp = toApp[p:]
if !Exists(toPath) {
os.Mkdir(toPath, 0755)
}
toLen := len(toPath)
changePathFn := func(src, dst string) string {
return dst[:toLen] + strings.ReplaceAll(dst[toLen:], fromApp, toApp)
}
cpFn := func(srcFile, dstFile string, overwrite bool) error {
if !overwrite && Exists(dstFile) {
return nil
}
out, err := os.Create(dstFile)
if err != nil {
return err
}
defer out.Close()

b, err := ioutil.ReadFile(srcFile)
if err != nil {
return err
}
rlt := strings.ReplaceAll(string(b), fromApp, toApp)
for _, repl := range replaces {
ss := strings.Split(repl, "/")
if len(ss) == 2 {
rlt = strings.ReplaceAll(rlt, ss[0], ss[1])
}
}
_, err = out.WriteString(rlt)
if err != nil {
fmt.Println(dstFile, "failed")
} else {
fmt.Println(dstFile, "ok")
}
return err
}
return CopyDirectory(fromPath, toPath, force, changePathFn, cpFn)
}

func uploadOrInstall(c *cli.Context) error {
fromPath := c.String("from")
toPath := c.String("to")
if fromPath == "" {
return errors.New("invalid fromPath")
}
if toPath == "" {
return errors.New("invalid toPath")
}
if c.String("ip") == "" {
return errors.New("invalid ip")
}
pwd := c.String("pwd")
if pwd == "" {
pwd = "password"
}
port := c.String("port")
if port == "" {
port = "22"
}
if !Exists(fromPath) {
return errors.New("fromPath not found")
}
install := c.Bool("install")
sshConn, err := NewSSHClient(c.String("ip"), port, "root", pwd)
if err != nil {
return err
}
if b, err := SshDirExists(sshConn, toPath); err != nil {
return err
} else if !b {
return errors.New(fmt.Sprintf("to: %s not found", toPath))
}
defer sshConn.Close()
scriptPath := c.String("script")
err = SshCopyDirectory(sshConn, fromPath, toPath, scriptPath)
if err != nil {
return err
}
if install {
targetScript := path.Join(toPath, filepath.Base(fromPath), filepath.Base(scriptPath))
if b, err := SshFileExists(sshConn, targetScript); err != nil || !b {
fmt.Println("Path:", targetScript, "not found")
return nil
}
cmd := fmt.Sprintf("cd \"%s\" ./%s", path.Join(toPath, filepath.Base(fromPath)), filepath.Base(scriptPath))
_, err = SshRunCmd(sshConn, cmd)
if err != nil {
fmt.Println("Run", cmd, "failed")
}
}
return err
}

func main() {
var cliApp *cli.App
cliApp = &cli.App{
Name: "forkApp",
Usage: "fork a luci app",
Action: func(c *cli.Context) error {
cli.ShowAppHelp(c)
return nil
},
Commands: []cli.Command{
{
Name: "fork",
Aliases: []string{"forkApp", "forkapp"},
Flags: []cli.Flag{
cli.StringFlag{
Name: "from",
Usage: "-from ../luci-app-plex",
},
cli.StringFlag{
Name: "to",
Usage: "-to luci-app-ittools",
},
cli.BoolFlag{
Name: "force",
Usage: "-force true",
},
cli.StringSliceFlag{
Name: "replace",
Usage: "-replace Plex/ITTools",
},
},
Action: func(c *cli.Context) error {
fromPath := c.String("from")
toPath := c.String("to")
if fromPath == "" {
return errors.New("invalid fromPath")
}
if toPath == "" {
return errors.New("invalid toPath")
}
if !Exists(fromPath) {
return errors.New("fromPath not found")
}
fromApp := filepath.Base(fromPath)
if !strings.HasPrefix(fromApp, "luci-app-") {
return errors.New("dir name should be luci-app-xxx")
}
toApp := filepath.Base(toPath)
if !strings.HasPrefix(toApp, "luci-app-") {
return errors.New("dir name should be luci-app-xxx")
}
if !Exists(filepath.Dir(toPath)) {
return errors.New(fmt.Sprintf("toPath: %s not found", filepath.Dir(toPath)))
}
return doForkApp(fromPath, toPath, fromApp, toApp, c.StringSlice("replace"), c.Bool("force"))
},
},
{
Name: "upload",
Aliases: []string{"u"},
Flags: []cli.Flag{
cli.StringSliceFlag{
Name: "from",
Usage: "../luci-app-plex",
},
cli.StringSliceFlag{
Name: "to",
Usage: "/root",
},
cli.StringFlag{
Name: "ip",
Usage: "-ip 192.168.100.1",
},
cli.StringFlag{
Name: "port",
Usage: "-port 22",
},
cli.StringFlag{
Name: "pwd",
Usage: "-pwd password",
},
cli.BoolFlag{
Name: "install",
Usage: "-install true",
},
cli.StringFlag{
Name: "script",
Usage: "-script ../tools/simple-instal.sh",
},
},
Action: func(c *cli.Context) error {
return uploadOrInstall(c)
},
},
},
}

err := cliApp.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
Loading

0 comments on commit 67dcd37

Please sign in to comment.