summaryrefslogtreecommitdiff
path: root/build/src/com/intellij/internalUtilities/ant/NsiFiles.java
blob: b19062870eb17d0d28252e0a348ec7bf96f12e1f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
package com.intellij.internalUtilities.ant;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.FileSet;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

/**
 * Ant task to facilitate building NSIS installer.
 *
 * @author  max
 * @since Jan 11, 2005
 */
@SuppressWarnings("UnusedDeclaration")
public class NsiFiles extends MatchingTask {
  private File myInstFile;
  private File myUnInstFile;
  private File myBaseDir;
  private final List<FileSet> myFileSets = new ArrayList<FileSet>();
  private final Map<String, List<String>> myDirToFiles = new LinkedHashMap<String, List<String>>();
  private final Map<String, String> myAbsoluteToRelative = new HashMap<String, String>();

  /**
   * The file to create; required
   * @param nsiFile new file to generate file install list to.
   */
  public void setInstFile(File nsiFile) {
    myInstFile = nsiFile;
  }

  /**
   * The file to create; required
   * @param nsiFile new file to generate file uninstall list to.
   */
  public void setUninstFile(File nsiFile) {
    myUnInstFile = nsiFile;
  }

  /**
   * ;optional
   * @param fileSet to be included in processing
   */
  public void addFileSet(FileSet fileSet) {
    myFileSets.add(fileSet);
  }

  /**
   * ;optional
   * @param baseDir of the files to be processed.
   */
  public void setBaseDir(File baseDir) {
    myBaseDir = baseDir;
  }

  public void execute() throws BuildException {
    if (myInstFile == null) throw new BuildException("Specify required isntFile attribute.");
    if (myUnInstFile == null) throw new BuildException("Specify required unisntFile attribute.");

    if (myBaseDir == null && myFileSets.size() == 0) {
        throw new BuildException("basedir attribute must be set, "
                                 + "or at least "
                                 + "one fileset must be given!");
    }

    try {
      if (myBaseDir != null) {
        FileSet fs = (FileSet) getImplicitFileSet().clone();
        fs.setDir(myBaseDir);
        processFileSet(fs);
      }

      for (FileSet fileSet : myFileSets) {
        processFileSet(fileSet);
      }

      generateInstFile();
      generateUninstFile();
    }
    catch (IOException e) {
      throw new BuildException(e);
    }
    finally {
      cleanup();
    }
  }

  private void generateUninstFile() throws IOException {
    BufferedWriter uninstWriter = new BufferedWriter(new FileWriter(myUnInstFile));
    try {
      List<String> allFiles = new ArrayList<String>();
      final Collection<List<String>> lists = myDirToFiles.values();
      for (final List<String> list : lists) {
        allFiles.addAll(list);
      }

      Collections.sort(allFiles);
      for (String file : allFiles) {
        uninstWriter.newLine();
        final String relPath = myAbsoluteToRelative.get(file);
        uninstWriter.write("Delete \"$INSTDIR\\" + relPath + "\"");
        if (relPath.endsWith(".py")) {
          uninstWriter.newLine();
          uninstWriter.write("Delete \"$INSTDIR\\" + relPath + "c\"");  // .pyc
        }
      }

      uninstWriter.newLine();
      List<String> dirs = new ArrayList<String>(myDirToFiles.keySet());
      Collections.sort(dirs);
      for (int i = dirs.size() - 1; i >= 0; i--) {
        final String dir = dirs.get(i);
        if (dir.length() == 0) continue;
        uninstWriter.newLine();
        uninstWriter.write("RmDir /r \"$INSTDIR\\" + dir + "\\__pycache__\"");
        uninstWriter.newLine();
        uninstWriter.write("RmDir \"$INSTDIR\\" + dir + "\"");
      }
      uninstWriter.newLine();
      uninstWriter.write("RmDir \"$INSTDIR\"");
    }
    finally{
      uninstWriter.close();
    }
  }

  private void generateInstFile() throws IOException {
    BufferedWriter instWriter = new BufferedWriter(new FileWriter(myInstFile));
    try {
      Collection<String> dirs = myDirToFiles.keySet();
      for (String dir : dirs) {
        final List<String> files = myDirToFiles.get(dir);
        if (files.size() == 0) continue;
        instWriter.newLine();
        instWriter.newLine();
        if (dir.length() > 0) {
          instWriter.write("SetOutPath $INSTDIR\\" + dir);
        }
        else {
          instWriter.write("SetOutPath $INSTDIR");
        }

        for (String file : files) {
          instWriter.newLine();
          instWriter.write("File \"" + file + "\"");
        }
      }
    }
    finally {
      instWriter.close();
    }
  }

  private void processFileSet(final FileSet fileSet) throws IOException {
    final DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
    final String[] files = scanner.getIncludedFiles();
    String base = fileSet.getDir(getProject()).getCanonicalPath() + "\\";
    for (String file : files) {
      String lastDir = "";
      getDirFileList(lastDir);
      int idx = -1;
      do {
        idx = file.indexOf('\\', idx + 1);
        if (idx == -1) break;
        lastDir = file.substring(0, idx);
        getDirFileList(lastDir);
      }
      while (true);

      List<String> fileList = getDirFileList(lastDir);
      final String absolute = base + file;
      fileList.add(absolute);
      myAbsoluteToRelative.put(absolute, file);
    }
  }

  private List<String> getDirFileList(final String dir) {
    List<String> fileList = myDirToFiles.get(dir);
    if (fileList == null) {
      fileList = new ArrayList<String>();
      myDirToFiles.put(dir, fileList);
    }
    return fileList;
  }

  private void cleanup() {
    myBaseDir = null;
    myInstFile = null;
    myFileSets.clear();
    myDirToFiles.clear();
    myAbsoluteToRelative.clear();
  }
}