1 // -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // Multi-Phasic Applications: SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // ---------------------------------------------------------------------------
10 package cc
.squirreljme
.cicd
;
13 import java
.io
.IOException
;
14 import java
.nio
.file
.Files
;
15 import java
.nio
.file
.Path
;
16 import java
.nio
.file
.Paths
;
17 import java
.nio
.file
.StandardOpenOption
;
18 import java
.util
.ArrayList
;
19 import java
.util
.Arrays
;
20 import java
.util
.List
;
21 import java
.util
.regex
.Pattern
;
24 * Access to the Fossil SCM command line interface.
28 public class FossilCommand
30 /** Retry this many times. */
31 private static final int RETRY_COUNT
=
34 /** Time to wait before a retry. */
35 private static final int RETRY_DELAY
=
38 /** The executable path. */
39 protected final Path exe
;
42 * Initializes the command executor.
44 * @param __exe The executable to use.
45 * @throws NullPointerException On null arguments.
48 public FossilCommand(Path __exe
)
49 throws NullPointerException
52 throw new NullPointerException("NARG");
58 * Adds a file to the un-versioned space.
60 * @param __path The file to add.
61 * @param __target The target destination.
62 * @throws IOException On read/write errors.
63 * @throws NullPointerException On null arguments.
66 public void add(Path __path
, String __target
)
67 throws IOException
, NullPointerException
69 if (__path
== null || __target
== null)
70 throw new NullPointerException("NARG");
72 this.exec("uv", "add",
73 __path
.toAbsolutePath().toString(), "--as", __target
);
77 * Adds a file to the un-versioned space.
79 * @param __rawData The raw file data to add.
80 * @param __target The target destination.
81 * @throws IOException On read/write errors.
82 * @throws NullPointerException On null arguments.
85 public void add(byte[] __rawData
, String __target
)
86 throws IOException
, NullPointerException
88 if (__rawData
== null || __target
== null)
89 throw new NullPointerException("NARG");
94 // Setup temporary file
95 temp
= Files
.createTempFile("squirreljme", ".bin");
97 // Write everything there
98 Files
.write(temp
, __rawData
,
99 StandardOpenOption
.WRITE
,
100 StandardOpenOption
.TRUNCATE_EXISTING
,
101 StandardOpenOption
.CREATE
);
104 this.add(temp
.toAbsolutePath(), __target
);
113 catch (IOException __ignored
)
120 * Executes the fossil command.
122 * @param __args The arguments to use.
123 * @throws IOException On read/write errors.
124 * @throws NullPointerException On null arguments.
127 public void exec(String
... __args
)
128 throws IOException
, NullPointerException
131 throw new NullPointerException("NARG");
133 // Add in all arguments
134 List
<String
> args
= new ArrayList
<>();
135 args
.add(this.exe
.toAbsolutePath().toString());
136 args
.addAll(Arrays
.asList(__args
));
138 // Run multiple times, in the event the database is locked...
139 List
<IOException
> fails
= new ArrayList
<>();
140 for (int i
= 0; i
< FossilCommand
.RETRY_COUNT
; i
++)
144 ProcessBuilder builder
= new ProcessBuilder(args
);
145 builder
.redirectOutput(ProcessBuilder
.Redirect
.INHERIT
);
146 builder
.redirectError(ProcessBuilder
.Redirect
.INHERIT
);
148 // Start and wait for it to complete
149 Process process
= builder
.start();
151 // Wait for completion, if successful then stop
152 int exit
= process
.waitFor();
157 fails
.add(new IOException("Exited with " + exit
));
159 // Wait a bit before running it again
160 Thread
.sleep(FossilCommand
.RETRY_DELAY
);
162 catch (InterruptedException __e
)
164 throw new IOException("Interrupted", __e
);
168 IOException toss
= new IOException("Failed to run: " + args
);
169 for (IOException fail
: fails
)
170 toss
.addSuppressed(fail
);
175 * Finds the Fossil command.
177 * @return The resultant command or {@code null} if there is none.
180 public static FossilCommand
instance()
184 if (System
.getProperty("os.name").toLowerCase().contains("windows"))
185 exeName
= "fossil.exe";
190 String paths
= System
.getenv("PATH");
192 for (String path
: paths
.split(Pattern
.quote(File
.pathSeparator
)))
194 Path maybe
= Paths
.get(path
, exeName
);
195 if (Files
.exists(maybe
) && Files
.isExecutable(maybe
))
196 return new FossilCommand(maybe
);