|
5 | 5 | package main
|
6 | 6 |
|
7 | 7 | import (
|
| 8 | + "archive/zip" |
8 | 9 | "bytes"
|
9 | 10 | "context"
|
10 | 11 | "encoding/json"
|
11 | 12 | "errors"
|
12 | 13 | "fmt"
|
| 14 | + "io" |
13 | 15 | "io/ioutil"
|
14 | 16 | "net"
|
15 | 17 | "net/http"
|
@@ -67,6 +69,7 @@ type LaunchContext struct {
|
67 | 69 | configDir string
|
68 | 70 | systemDir string
|
69 | 71 | projectConfigDir string
|
| 72 | + projectSystemDir string |
70 | 73 | projectContextDir string
|
71 | 74 | riderSolutionFile string
|
72 | 75 |
|
@@ -418,14 +421,19 @@ func launch(launchCtx *LaunchContext) {
|
418 | 421 | launchCtx.riderSolutionFile = riderSolutionFile
|
419 | 422 | launchCtx.projectContextDir = resolveProjectContextDir(launchCtx)
|
420 | 423 | launchCtx.projectConfigDir = fmt.Sprintf("%s/RemoteDev-%s/%s", launchCtx.configDir, launchCtx.info.ProductCode, strings.ReplaceAll(launchCtx.projectContextDir, "/", "_"))
|
| 424 | + launchCtx.projectSystemDir = fmt.Sprintf("%s/RemoteDev-%s/%s", launchCtx.systemDir, launchCtx.info.ProductCode, strings.ReplaceAll(launchCtx.projectContextDir, "/", "_")) |
421 | 425 | launchCtx.env = resolveLaunchContextEnv(launchCtx.configDir, launchCtx.systemDir)
|
422 | 426 |
|
423 |
| - // sync initial options |
424 |
| - err = syncOptions(launchCtx) |
| 427 | + err = syncInitialContent(launchCtx, Options) |
425 | 428 | if err != nil {
|
426 | 429 | log.WithError(err).Error("failed to sync initial options")
|
427 | 430 | }
|
428 | 431 |
|
| 432 | + err = syncInitialContent(launchCtx, Plugins) |
| 433 | + if err != nil { |
| 434 | + log.WithError(err).Error("failed to sync initial plugins") |
| 435 | + } |
| 436 | + |
429 | 437 | // install project plugins
|
430 | 438 | version_2022_1, _ := version.NewVersion("2022.1")
|
431 | 439 | if version_2022_1.LessThanOrEqual(launchCtx.backendVersion) {
|
@@ -710,53 +718,149 @@ func resolveProductInfo(backendDir string) (*ProductInfo, error) {
|
710 | 718 | return &info, err
|
711 | 719 | }
|
712 | 720 |
|
713 |
| -func syncOptions(launchCtx *LaunchContext) error { |
714 |
| - userHomeDir, err := os.UserHomeDir() |
| 721 | +type SyncTarget string |
| 722 | + |
| 723 | +const ( |
| 724 | + Options SyncTarget = "options" |
| 725 | + Plugins SyncTarget = "plugins" |
| 726 | +) |
| 727 | + |
| 728 | +func syncInitialContent(launchCtx *LaunchContext, target SyncTarget) error { |
| 729 | + destDir, err := ensureSyncDest(launchCtx, target) |
| 730 | + if !os.IsNotExist(err) { |
| 731 | + // already synced skipping, i.e. restart of jb backend |
| 732 | + return nil |
| 733 | + } |
| 734 | + if err != nil { |
| 735 | + return err |
| 736 | + } |
| 737 | + |
| 738 | + srcDirs, err := collectSyncSources(launchCtx, target) |
715 | 739 | if err != nil {
|
716 | 740 | return err
|
717 | 741 | }
|
| 742 | + if len(srcDirs) == 0 { |
| 743 | + // nothing to sync |
| 744 | + return nil |
| 745 | + } |
| 746 | + |
| 747 | + for _, srcDir := range srcDirs { |
| 748 | + if target == Plugins { |
| 749 | + files, err := ioutil.ReadDir(srcDir) |
| 750 | + if err != nil { |
| 751 | + return err |
| 752 | + } |
| 753 | + |
| 754 | + for _, file := range files { |
| 755 | + if file.IsDir() { |
| 756 | + cp := exec.Command("cp", "-rf", filepath.Join(srcDir, file.Name()), destDir) |
| 757 | + err = cp.Run() |
| 758 | + if err != nil { |
| 759 | + return err |
| 760 | + } |
| 761 | + } else if filepath.Ext(file.Name()) == ".zip" { |
| 762 | + folderName := strings.TrimSuffix(file.Name(), ".zip") |
| 763 | + targetFolder := filepath.Join(destDir, folderName) |
| 764 | + err = unzipArchive(filepath.Join(srcDir, file.Name()), targetFolder) |
| 765 | + if err != nil { |
| 766 | + return err |
| 767 | + } |
| 768 | + } |
| 769 | + } |
| 770 | + } else { |
| 771 | + cp := exec.Command("cp", "-rf", srcDir+"/.", destDir) |
| 772 | + err = cp.Run() |
| 773 | + if err != nil { |
| 774 | + return err |
| 775 | + } |
| 776 | + } |
| 777 | + } |
| 778 | + return nil |
| 779 | +} |
| 780 | + |
| 781 | +func ensureSyncDest(launchCtx *LaunchContext, target SyncTarget) (string, error) { |
| 782 | + projectDestDir := launchCtx.projectConfigDir |
| 783 | + if target == Plugins { |
| 784 | + projectDestDir = launchCtx.projectSystemDir |
| 785 | + } |
| 786 | + destDir := fmt.Sprintf("%s/%s", projectDestDir, target) |
| 787 | + _, err := os.Stat(destDir) |
| 788 | + if err != nil { |
| 789 | + return "", err |
| 790 | + } |
| 791 | + err = os.MkdirAll(destDir, os.ModePerm) |
| 792 | + if err != nil { |
| 793 | + return "", err |
| 794 | + } |
| 795 | + return destDir, nil |
| 796 | +} |
| 797 | + |
| 798 | +func collectSyncSources(launchCtx *LaunchContext, target SyncTarget) ([]string, error) { |
| 799 | + userHomeDir, err := os.UserHomeDir() |
| 800 | + if err != nil { |
| 801 | + return nil, err |
| 802 | + } |
718 | 803 | var srcDirs []string
|
719 | 804 | for _, srcDir := range []string{
|
720 |
| - fmt.Sprintf("%s/.gitpod/jetbrains/options", userHomeDir), |
721 |
| - fmt.Sprintf("%s/.gitpod/jetbrains/%s/options", userHomeDir, launchCtx.alias), |
722 |
| - fmt.Sprintf("%s/.gitpod/jetbrains/options", launchCtx.projectDir), |
723 |
| - fmt.Sprintf("%s/.gitpod/jetbrains/%s/options", launchCtx.projectDir, launchCtx.alias), |
| 805 | + fmt.Sprintf("%s/.gitpod/jetbrains/%s", userHomeDir, target), |
| 806 | + fmt.Sprintf("%s/.gitpod/jetbrains/%s/%s", userHomeDir, launchCtx.alias, target), |
| 807 | + fmt.Sprintf("%s/.gitpod/jetbrains/%s", launchCtx.projectDir, target), |
| 808 | + fmt.Sprintf("%s/.gitpod/jetbrains/%s/%s", launchCtx.projectDir, launchCtx.alias, target), |
724 | 809 | } {
|
725 | 810 | srcStat, err := os.Stat(srcDir)
|
726 | 811 | if os.IsNotExist(err) {
|
727 | 812 | // nothing to sync
|
728 | 813 | continue
|
729 | 814 | }
|
730 | 815 | if err != nil {
|
731 |
| - return err |
| 816 | + return nil, err |
732 | 817 | }
|
733 | 818 | if !srcStat.IsDir() {
|
734 |
| - return fmt.Errorf("%s is not a directory", srcDir) |
| 819 | + return nil, fmt.Errorf("%s is not a directory", srcDir) |
735 | 820 | }
|
736 | 821 | srcDirs = append(srcDirs, srcDir)
|
737 | 822 | }
|
738 |
| - if len(srcDirs) == 0 { |
739 |
| - // nothing to sync |
740 |
| - return nil |
741 |
| - } |
| 823 | + return srcDirs, nil |
| 824 | +} |
742 | 825 |
|
743 |
| - destDir := fmt.Sprintf("%s/options", launchCtx.projectConfigDir) |
744 |
| - _, err = os.Stat(destDir) |
745 |
| - if !os.IsNotExist(err) { |
746 |
| - // already synced skipping, i.e. restart of jb backend |
747 |
| - return nil |
748 |
| - } |
749 |
| - err = os.MkdirAll(destDir, os.ModePerm) |
| 826 | +func unzipArchive(src, dest string) error { |
| 827 | + r, err := zip.OpenReader(src) |
750 | 828 | if err != nil {
|
751 | 829 | return err
|
752 | 830 | }
|
| 831 | + defer r.Close() |
753 | 832 |
|
754 |
| - for _, srcDir := range srcDirs { |
755 |
| - cp := exec.Command("cp", "-rf", srcDir+"/.", destDir) |
756 |
| - err = cp.Run() |
| 833 | + for _, f := range r.File { |
| 834 | + rc, err := f.Open() |
757 | 835 | if err != nil {
|
758 | 836 | return err
|
759 | 837 | }
|
| 838 | + defer rc.Close() |
| 839 | + |
| 840 | + fpath := filepath.Join(dest, f.Name) |
| 841 | + if f.FileInfo().IsDir() { |
| 842 | + err := os.MkdirAll(fpath, os.ModePerm) |
| 843 | + if err != nil { |
| 844 | + return err |
| 845 | + } |
| 846 | + } else { |
| 847 | + fdir := filepath.Dir(fpath) |
| 848 | + err := os.MkdirAll(fdir, os.ModePerm) |
| 849 | + if err != nil { |
| 850 | + return err |
| 851 | + } |
| 852 | + |
| 853 | + outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode()) |
| 854 | + if err != nil { |
| 855 | + return err |
| 856 | + } |
| 857 | + defer outFile.Close() |
| 858 | + |
| 859 | + _, err = io.Copy(outFile, rc) |
| 860 | + if err != nil { |
| 861 | + return err |
| 862 | + } |
| 863 | + } |
760 | 864 | }
|
761 | 865 | return nil
|
762 | 866 | }
|
|
0 commit comments