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 package com.jcabi.heroku.maven.plugin;
31
32 import com.jcabi.aspects.Immutable;
33 import com.jcabi.aspects.RetryOnFailure;
34 import com.jcabi.log.Logger;
35 import com.jcabi.log.VerboseProcess;
36 import java.io.File;
37 import java.io.IOException;
38 import java.util.ArrayList;
39 import java.util.List;
40 import javax.validation.constraints.NotNull;
41 import lombok.EqualsAndHashCode;
42 import lombok.ToString;
43 import org.apache.commons.io.FileUtils;
44 import org.apache.commons.lang3.StringUtils;
45
46
47
48
49
50
51
52
53
54 @Immutable
55 @ToString
56 @EqualsAndHashCode(of = "script")
57 final class Git {
58
59
60
61
62 @SuppressWarnings("PMD.AvoidUsingOctalValues")
63 private static final int PERMS = 0600;
64
65
66
67
68 private static final String SSH = "/usr/bin/ssh";
69
70
71
72
73 private final transient String script;
74
75
76
77
78
79
80
81 public Git(@NotNull final File key,
82 @NotNull final File temp) throws IOException {
83 if (!new File(Git.SSH).exists()) {
84 throw new IllegalStateException(
85 String.format("SSH is not installed at '%s'", Git.SSH)
86 );
87 }
88 final File kfile = new File(temp, "heroku.pem");
89 FileUtils.copyFile(key, kfile);
90 this.chmod(kfile, Git.PERMS);
91 final File file = new File(temp, "git-ssh.sh");
92 this.script = file.getAbsolutePath();
93 FileUtils.writeStringToFile(
94 new File(this.script),
95 String.format(
96
97 "set -x && %s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i '%s' $@",
98 Git.SSH,
99 kfile.getAbsolutePath()
100 )
101 );
102 file.setExecutable(true);
103 }
104
105
106
107
108
109
110
111
112 @RetryOnFailure(delay = 3000, attempts = 2)
113 public String exec(@NotNull final File dir, @NotNull final String... args) {
114 final List<String> commands = new ArrayList<String>(args.length + 1);
115 commands.add("git");
116 for (final String arg : args) {
117 commands.add(arg);
118 }
119 Logger.info(this, "%s:...", StringUtils.join(commands, " "));
120 final ProcessBuilder builder = new ProcessBuilder(commands);
121 builder.directory(dir);
122 builder.environment().put("GIT_SSH", this.script);
123 return new VerboseProcess(builder).stdout();
124 }
125
126
127
128
129
130
131
132
133
134 private void chmod(final File file, final int mode) throws IOException {
135 new VerboseProcess(
136 new ProcessBuilder(
137 "chmod",
138 String.format("%04o", mode),
139 file.getAbsolutePath()
140 )
141 ).stdout();
142 Logger.debug(
143 this,
144 "chmod(%s, %3o): succeeded",
145 file,
146 mode
147 );
148 }
149
150 }