Skip to content

Method: gitCommand()

1: /*
2: * #%L
3: * *********************************************************************************************************************
4: *
5: * NorthernWind - lightweight CMS
6: * http://northernwind.tidalwave.it - git clone https://bitbucket.org/tidalwave/northernwind-src.git
7: * %%
8: * Copyright (C) 2011 - 2023 Tidalwave s.a.s. (http://tidalwave.it)
9: * %%
10: * *********************************************************************************************************************
11: *
12: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
13: * the License. You may obtain a copy of the License at
14: *
15: * http://www.apache.org/licenses/LICENSE-2.0
16: *
17: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
18: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
19: * specific language governing permissions and limitations under the License.
20: *
21: * *********************************************************************************************************************
22: *
23: *
24: * *********************************************************************************************************************
25: * #L%
26: */
27: package it.tidalwave.northernwind.frontend.filesystem.git.impl;
28:
29: import javax.annotation.Nonnull;
30: import java.util.List;
31: import java.util.Optional;
32: import java.io.IOException;
33: import java.nio.file.Files;
34: import java.nio.file.Path;
35: import java.net.URI;
36: import it.tidalwave.util.ProcessExecutor;
37: import it.tidalwave.util.ProcessExecutorException;
38: import it.tidalwave.northernwind.frontend.filesystem.scm.spi.ScmWorkingDirectorySupport;
39: import it.tidalwave.northernwind.frontend.filesystem.scm.spi.Tag;
40: import lombok.extern.slf4j.Slf4j;
41:
42: /***********************************************************************************************************************
43: *
44: * A Git implementation of {@link it.tidalwave.northernwind.frontend.filesystem.scm.spi.ScmWorkingDirectory}.
45: *
46: * @author Fabrizio Giudici
47: *
48: **********************************************************************************************************************/
49: @Slf4j
50: public class GitWorkingDirectory extends ScmWorkingDirectorySupport
51: {
52: private static final String GIT = "git";
53:
54: /*******************************************************************************************************************
55: *
56: * Creates a new instance for the given folder.
57: *
58: * @param folder the folder
59: *
60: ******************************************************************************************************************/
61: public GitWorkingDirectory (@Nonnull final Path folder)
62: {
63: super(".git", folder);
64: }
65:
66: /*******************************************************************************************************************
67: *
68: * {@inheritDoc}
69: *
70: ******************************************************************************************************************/
71: @Override @Nonnull
72: public Optional<Tag> getCurrentTag()
73: throws InterruptedException, IOException
74: {
75: try
76: {
77: final var executor =
78: gitCommand().withArguments("describe", "--tags", "--candidates=0").start().waitForCompletion();
79: return executor.getStdout().waitForCompleted().getContent().stream().findFirst().map(Tag::new);
80: }
81: catch (ProcessExecutorException e)
82: {
83: if ((e.getExitCode() == 128) &&
84: e.getStderr().stream().anyMatch(s -> s.contains("fatal: no tag exactly matches ")))
85: {
86: return Optional.empty();
87: }
88:
89: throw e;
90: }
91: }
92:
93: /*******************************************************************************************************************
94: *
95: * {@inheritDoc}
96: *
97: ******************************************************************************************************************/
98: @Nonnull
99: public List<String> listTags()
100: throws InterruptedException, IOException
101: {
102: return gitCommand().withArguments("tag", "-l", "--sort=v:refname")
103: .start()
104: .waitForCompletion()
105: .getStdout()
106: .waitForCompleted()
107: .filteredBy("([^ ]*) *.*$");
108: }
109:
110: /*******************************************************************************************************************
111: *
112: * {@inheritDoc}
113: *
114: ******************************************************************************************************************/
115: public void cloneFrom (@Nonnull final URI uri)
116: throws InterruptedException, IOException
117: {
118: Files.createDirectories(folder);
119: gitCommand().withArguments("clone", "--no-checkout", uri.toASCIIString(), ".").start().waitForCompletion();
120: }
121:
122: /*******************************************************************************************************************
123: *
124: * {@inheritDoc}
125: *
126: ******************************************************************************************************************/
127: @Override
128: public void checkOut (@Nonnull final Tag tag)
129: throws InterruptedException, IOException
130: {
131: try
132: {
133: gitCommand().withArguments("checkout", tag.getName()).start().waitForCompletion();
134: }
135: catch (ProcessExecutorException e)
136: {
137: if ((e.getExitCode() == 1) &&
138: (e.getStderr().stream().anyMatch(s -> s.contains("did not match any file(s) known to git"))))
139: {
140: throw new IllegalArgumentException("Invalid tag: " + tag.getName());
141: }
142:
143: throw e;
144: }
145: }
146:
147: /*******************************************************************************************************************
148: *
149: * {@inheritDoc}
150: *
151: ******************************************************************************************************************/
152: @Override
153: public void fetchChangesets()
154: throws InterruptedException, IOException
155: {
156: gitCommand().withArguments("fetch", "--all").start().waitForCompletion();
157: }
158:
159: /*******************************************************************************************************************
160: *
161: * Creates an executor for git.
162: *
163: * @return the executor
164: * @throws IOException in case of error
165: *
166: ******************************************************************************************************************/
167: @Nonnull
168: private ProcessExecutor gitCommand()
169: throws IOException
170: {
171: return ProcessExecutor.forExecutable(GIT).withWorkingDirectory(folder);
172: }
173: }