github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/deploy/main.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"archive/zip"
     6  	"bytes"
     7  	"compress/gzip"
     8  	"encoding/json"
     9  	"flag"
    10  	"io"
    11  	"io/ioutil"
    12  	"log"
    13  	"os"
    14  	"path/filepath"
    15  	"runtime"
    16  	"strings"
    17  
    18  	"github.com/benoitkugler/goACVE/deploy/upload"
    19  
    20  	"github.com/benoitkugler/goACVE/client/version"
    21  
    22  	"github.com/benoitkugler/goACVE/server/core/apiserver"
    23  	"github.com/benoitkugler/goACVE/server/core/utils"
    24  	"github.com/benoitkugler/goACVE/deploy/store"
    25  )
    26  
    27  type fullArchive interface {
    28  	addFile(info os.FileInfo, sourcePath string)
    29  	close() []byte
    30  }
    31  
    32  type zipArchive struct {
    33  	buffer  *bytes.Buffer
    34  	archive *zip.Writer
    35  }
    36  
    37  func (z zipArchive) addFile(info os.FileInfo, sourcePath string) {
    38  	if info.IsDir() {
    39  		return
    40  	}
    41  	wr, err := z.archive.Create(sourcePath)
    42  	if err != nil {
    43  		log.Fatal(err)
    44  	}
    45  	f, err := os.Open(sourcePath)
    46  	defer f.Close()
    47  	if err != nil {
    48  		log.Fatal(err)
    49  	}
    50  	if _, err := io.Copy(wr, f); err != nil {
    51  		log.Fatal(err)
    52  	}
    53  }
    54  
    55  func (z zipArchive) close() []byte {
    56  	if err := z.archive.Close(); err != nil {
    57  		log.Fatal(err)
    58  	}
    59  	return z.buffer.Bytes()
    60  }
    61  
    62  type tarArchive struct {
    63  	buffer     *bytes.Buffer
    64  	compressed *gzip.Writer
    65  	archive    *tar.Writer
    66  	full       bool // for full logiciel
    67  }
    68  
    69  func newTarArchive() tarArchive {
    70  	buf := new(bytes.Buffer)
    71  	compressed, err := gzip.NewWriterLevel(buf, gzip.BestCompression)
    72  	if err != nil {
    73  		log.Fatal(err)
    74  	}
    75  	tw := tar.NewWriter(compressed)
    76  	return tarArchive{buffer: buf, archive: tw, compressed: compressed}
    77  }
    78  
    79  func (t tarArchive) addFile(info os.FileInfo, sourcePath string) {
    80  	archive := t.archive
    81  
    82  	var (
    83  		link string
    84  		err  error
    85  	)
    86  	if info.Mode()&os.ModeSymlink == os.ModeSymlink {
    87  		if link, err = os.Readlink(sourcePath); err != nil {
    88  			log.Fatal(err)
    89  		}
    90  	}
    91  
    92  	hdr, err := tar.FileInfoHeader(info, link)
    93  	if err != nil {
    94  		log.Fatal(err)
    95  	}
    96  
    97  	if t.full {
    98  		hdr.Name = sourcePath // pack complet
    99  	} else {
   100  		if hdr.Name+"/" == store.DarwinApp {
   101  			return
   102  		}
   103  		hdr.Name = strings.TrimPrefix(sourcePath, store.DarwinApp) // pour darwin, on se place à l'intérieur de l'app..
   104  	}
   105  
   106  	if err := archive.WriteHeader(hdr); err != nil {
   107  		log.Fatal(err)
   108  	}
   109  
   110  	if !info.Mode().IsRegular() { //nothing more to do for non-regular
   111  		return
   112  	}
   113  
   114  	f, err := os.Open(sourcePath)
   115  	defer f.Close()
   116  	if err != nil {
   117  		log.Fatal(err)
   118  	}
   119  	if _, err := io.Copy(archive, f); err != nil {
   120  		log.Fatal(err)
   121  	}
   122  }
   123  
   124  func (t tarArchive) close() []byte {
   125  	if err := t.archive.Close(); err != nil {
   126  		log.Fatal(err)
   127  	}
   128  	if err := t.compressed.Close(); err != nil {
   129  		log.Fatal(err)
   130  	}
   131  	return t.buffer.Bytes()
   132  }
   133  
   134  // On suppose qu'on a déjà build avec qt deploy
   135  // et copié les ressources.
   136  func main() {
   137  	noUpload := flag.Bool("noup", false, "disable uploading to the server")
   138  	noPack := flag.Bool("nopack", false, "disable packing")
   139  	flag.Parse()
   140  
   141  	if !*noPack {
   142  		Pack()
   143  	}
   144  
   145  	if !*noUpload {
   146  		Upload()
   147  	}
   148  }
   149  
   150  func Pack() {
   151  	newVersion := version.VERSION
   152  	log.Printf("Utilitaire de déployement pour la version %s", newVersion)
   153  	storePaths := store.GetPaths(runtime.GOOS)
   154  
   155  	checkLogicielDir()
   156  	oldVersion := readVersion(storePaths.Versions)
   157  
   158  	currentDir, err := os.Getwd()
   159  	if err != nil {
   160  		log.Fatal(err)
   161  	}
   162  	root := "client/deploy/" + runtime.GOOS
   163  	log.Println("Moving to", root)
   164  	if err := os.Chdir(root); err != nil {
   165  		log.Fatal(err)
   166  	}
   167  
   168  	log.Println("Packing datas...")
   169  	client, fullArch, nbFiles := parcourtFolder()
   170  
   171  	log.Println("Going back to", currentDir)
   172  	if err := os.Chdir(currentDir); err != nil {
   173  		log.Fatal(err)
   174  	}
   175  
   176  	log.Println("Saving full archive...")
   177  	if err = ioutil.WriteFile(storePaths.Full, fullArch, 0666); err != nil {
   178  		log.Fatal(err)
   179  	}
   180  	log.Println("UP -> Logiciel copié dans", storePaths.Full)
   181  
   182  	if newVersion == oldVersion.Version {
   183  		log.Fatal("La version du client n'a pas été mise à jour !")
   184  	}
   185  	log.Println("Mise à jour du client...")
   186  
   187  	oldVersion.Version = newVersion
   188  	hash, err := utils.HashBytes(client)
   189  	if err != nil {
   190  		log.Fatal(err)
   191  	}
   192  	oldVersion.Hash = hash
   193  	oldVersion.NbFiles = nbFiles
   194  	if err = ioutil.WriteFile(storePaths.Client, client, 0666); err != nil {
   195  		log.Fatal(err)
   196  	}
   197  	log.Println("UP -> Client copié dans", storePaths.Client)
   198  
   199  	b, err := json.MarshalIndent(oldVersion, " ", " ")
   200  	if err != nil {
   201  		log.Fatal(err)
   202  	}
   203  	if err := ioutil.WriteFile(storePaths.Versions, b, 0666); err != nil {
   204  		log.Fatal(err)
   205  	}
   206  	log.Println("UP -> Versions copiées dans", storePaths.Versions)
   207  }
   208  
   209  func Upload() {
   210  	storePaths := store.GetPaths(runtime.GOOS)
   211  	toUpload := []upload.Up{
   212  		upload.NewUp(storePaths.Full),
   213  		upload.NewUp(storePaths.Client),
   214  		upload.NewUp(storePaths.Versions),
   215  	}
   216  	s := upload.OpenFTP()
   217  	if err := upload.Upload(s, toUpload); err != nil {
   218  		log.Fatal(err)
   219  	}
   220  	log.Println("Upload done.")
   221  }
   222  
   223  func readVersion(path string) apiserver.VersionInfos {
   224  	b, _ := ioutil.ReadFile(path)
   225  	var v apiserver.VersionInfos
   226  	err := json.Unmarshal(b, &v)
   227  	if err != nil {
   228  		v.Version = "0.0.0"
   229  		log.Println("Fichier de version introuvable (ancienne version => 0.0.0)")
   230  	}
   231  	return v
   232  }
   233  
   234  func checkLogicielDir() {
   235  	path := filepath.Join(store.BasePathExport, runtime.GOOS)
   236  	_, err := os.Stat(path)
   237  	if err == nil {
   238  		return
   239  	}
   240  	if err = os.Mkdir(path, 0777); err != nil {
   241  		log.Fatalf("Impossible de créer le dossier d'export : %s", err)
   242  	}
   243  }
   244  
   245  func initFullArchive() fullArchive {
   246  	var fullArch fullArchive
   247  	buf := new(bytes.Buffer)
   248  	if runtime.GOOS == "windows" {
   249  		fullArch = zipArchive{buffer: buf, archive: zip.NewWriter(buf)}
   250  	} else {
   251  		t := newTarArchive()
   252  		t.full = true
   253  		fullArch = t
   254  	}
   255  	return fullArch
   256  }
   257  
   258  func parcourtFolder() ([]byte, []byte, int) {
   259  	nbFiles := 0
   260  	client := newTarArchive()
   261  	fullArch := initFullArchive()
   262  	walkF := func(filePath string, info os.FileInfo, err error) error {
   263  		if filePath == "." {
   264  			return nil
   265  		}
   266  		if err != nil {
   267  			log.Fatal(err)
   268  		}
   269  		nbFiles += 1
   270  		client.addFile(info, filePath)
   271  		fullArch.addFile(info, filePath)
   272  		return nil
   273  	}
   274  	err := filepath.Walk(".", walkF)
   275  	if err != nil {
   276  		log.Fatal(err)
   277  	}
   278  	return client.close(), fullArch.close(), nbFiles
   279  }