Skip to content

Method: fetchChangesets()

1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * NorthernWind - lightweight CMS
5: * http://tidalwave.it/projects/northernwind
6: *
7: * Copyright (C) 2011 - 2025 Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/northernwind-src
22: * git clone https://github.com/tidalwave-it/northernwind-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.northernwind.frontend.filesystem.hg.impl;
27:
28: import javax.annotation.Nonnull;
29: import java.util.List;
30: import java.util.NoSuchElementException;
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: import static java.util.stream.Collectors.*;
42:
43: /***************************************************************************************************************************************************************
44: *
45: * A Mercurial implementation of {@link it.tidalwave.northernwind.frontend.filesystem.scm.spi.ScmWorkingDirectory}.
46: *
47: * @author Fabrizio Giudici
48: *
49: **************************************************************************************************************************************************************/
50: @Slf4j
51: public class MercurialWorkingDirectory extends ScmWorkingDirectorySupport
52: {
53: private static final String HG = "hg";
54:
55: /***********************************************************************************************************************************************************
56: * Creates a new instance for the given folder.
57: *
58: * @param folder the folder
59: **********************************************************************************************************************************************************/
60: public MercurialWorkingDirectory (@Nonnull final Path folder)
61: {
62: super(".hg", folder);
63: }
64:
65: /***********************************************************************************************************************************************************
66: * {@inheritDoc}
67: **********************************************************************************************************************************************************/
68: @Override @Nonnull
69: public Optional<Tag> getCurrentTag()
70: throws InterruptedException, IOException
71: {
72: try
73: {
74: final var executor = hgCommand().withArgument("id").start().waitForCompletion();
75: final var scanner = executor.getStdout().waitForCompleted().filteredAndSplitBy("(.*)", " ");
76: scanner.next();
77: return Optional.of(new Tag(scanner.next()));
78: }
79: catch (NoSuchElementException e)
80: {
81: return Optional.empty();
82: }
83: }
84:
85: /***********************************************************************************************************************************************************
86: * {@inheritDoc}
87: **********************************************************************************************************************************************************/
88: @Nonnull
89: public List<String> listTags()
90: throws InterruptedException, IOException
91: {
92: return hgCommand().withArgument("tags")
93: .start()
94: .waitForCompletion()
95: .getStdout()
96: .waitForCompleted()
97: .filteredBy("([^ ]*) *.*$")
98: .stream()
99: .filter(s -> !"tip".equals(s))
100: .collect(collectingAndThen(toList(), ScmWorkingDirectorySupport::reversed));
101: }
102:
103: /***********************************************************************************************************************************************************
104: * {@inheritDoc}
105: **********************************************************************************************************************************************************/
106: public void cloneFrom (@Nonnull final URI uri)
107: throws InterruptedException, IOException
108: {
109: Files.createDirectories(folder);
110: hgCommand().withArguments("clone", "--noupdate", uri.toASCIIString(), ".").start().waitForCompletion();
111: }
112:
113: /***********************************************************************************************************************************************************
114: * {@inheritDoc}
115: **********************************************************************************************************************************************************/
116: @Override
117: public void checkOut (@Nonnull final Tag tag)
118: throws InterruptedException, IOException
119: {
120: try
121: {
122: hgCommand().withArguments("update", "-C", tag.getName()).start().waitForCompletion();
123: }
124: catch (ProcessExecutorException e)
125: {
126: if ((e.getExitCode() == 255) &&
127: (e.getStderr().stream().anyMatch(s -> s.contains("abort: unknown revision"))))
128: {
129: throw new IllegalArgumentException("Invalid tag: " + tag.getName());
130: }
131:
132: throw e;
133: }
134: }
135:
136: /***********************************************************************************************************************************************************
137: * {@inheritDoc}
138: **********************************************************************************************************************************************************/
139: @Override
140: public void fetchChangesets()
141: throws InterruptedException, IOException
142: {
143: hgCommand().withArgument("pull").start().waitForCompletion();
144: }
145:
146: /***********************************************************************************************************************************************************
147: * Creates an executor for Mercurial.
148: *
149: * @return the executor
150: * @throws IOException in case of error
151: **********************************************************************************************************************************************************/
152: @Nonnull
153: private ProcessExecutor hgCommand()
154: throws IOException
155: {
156: return ProcessExecutor.forExecutable(HG).withWorkingDirectory(folder);
157: }
158: }