diff --git a/pom.xml b/pom.xml
index a28c40d0180fadfe40c6165e7866693670bb254f..f8e4177c664e864f9c5875e0cbc2d82dfd9d1d20 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.light
GitManagerClientFx
- 1.0-SNAPSHOT
+ 1.0
21
diff --git a/src/main/java/com/light/GitManagerApp.java b/src/main/java/com/light/GitManagerApp.java
index b341d43dda339ed59a6023e6ebd507bfa3bb260e..6a75c62aed29ae077fa1718923bcdef99200c8c5 100644
--- a/src/main/java/com/light/GitManagerApp.java
+++ b/src/main/java/com/light/GitManagerApp.java
@@ -58,6 +58,9 @@ public class GitManagerApp extends Application {
.ifPresentOrElse(theme -> Application.setUserAgentStylesheet(theme.getUserAgentStylesheet()),
() -> Application.setUserAgentStylesheet(THEME_LIST.getFirst().getUserAgentStylesheet())
);
+
+ // 查询所有项目数据
+ H2PoolUtils.queryGitProjects();
});
}
@@ -92,6 +95,7 @@ public class GitManagerApp extends Application {
stage.setScene(scene);
stage.show();
scene.getStylesheets().add(STYLE_SHEET);
+ FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.put("scene", scene);
LOGGER.info("项目启动完成,耗时 {} ms", System.currentTimeMillis() - startTime);
}
diff --git a/src/main/java/com/light/component/AuthenticationPane.java b/src/main/java/com/light/component/AuthenticationPane.java
index 31170934a31798adaa86eb2ae7076f7ce609e1c4..b1372b00648bd54dcbd8ba4d113ee060e80a947a 100644
--- a/src/main/java/com/light/component/AuthenticationPane.java
+++ b/src/main/java/com/light/component/AuthenticationPane.java
@@ -1,31 +1,53 @@
package com.light.component;
import com.light.enums.Level;
+import com.light.exception.AuthException;
+import com.light.exception.H2Exception;
+import com.light.exception.JGitException;
+import com.light.exception.TimeOutException;
import com.light.layout.ModalDialog;
import com.light.model.GitAuthInfo;
+import com.light.model.GitProject;
import com.light.thread.AsyncTask;
-import com.light.util.H2PoolUtils;
-import com.light.util.JGitUtils;
-import com.light.util.NoticeUtils;
+import com.light.util.*;
+import javafx.application.Platform;
+import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Insets;
+import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jgit.transport.CredentialsProvider;
import java.io.File;
+import java.util.Date;
public class AuthenticationPane extends ModalDialog {
- public AuthenticationPane(String repoType, String remoteUrl, File file) {
+ /**
+ * 没有权限
+ *
+ * @param clone
+ * @param index 只有克隆时使用
+ * @param remoteUrl
+ * @param file
+ */
+ public AuthenticationPane(boolean clone, int index, String remoteUrl, File file) {
+ this(clone, index, remoteUrl, file, null, null, null);
+ }
+
+ public AuthenticationPane(boolean clone, int index, String remoteUrl, File file, SimpleDoubleProperty rate, GitProject project, Button updateButton) {
super();
+ String repoType = JGitUtils.getType(remoteUrl);
header.setTitle(repoType);
- content.setBody(createContent(repoType, remoteUrl, file));
+ content.setBody(createContent(clone, index, repoType, remoteUrl, file, rate, project, updateButton));
content.setFooter(null);
+// FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.put("authDialogShowing", true);
}
- private VBox createContent(String repoType, String remoteUrl, File file) {
+ private VBox createContent(boolean clone, int index, String repoType, String remoteUrl, File file, SimpleDoubleProperty rate, GitProject project, Button updateButton) {
var usernameField = new TextField();
usernameField.setPromptText("手机/邮箱/用户名");
usernameField.setMaxWidth(300);
@@ -45,17 +67,66 @@ public class AuthenticationPane extends ModalDialog {
NoticeUtils.show(null, "用户名密码不能为空", Level.WARN);
return;
}
- GitAuthInfo authInfo = new GitAuthInfo(0, repoType, username, username, "");
+ GitAuthInfo authInfo = new GitAuthInfo(0, repoType, username, password, "");
// 入库
- int num = H2PoolUtils.insertAuthInfo(authInfo);
+ int num = 0;
+ try {
+ GitAuthInfo existsAuthInfo = H2PoolUtils.queryAuthInfo(repoType);
+ if (existsAuthInfo != null) {
+ // 克隆或者下载时权限异常会执行这段代码
+ num = H2PoolUtils.updateAuthInfo(repoType, username, password);
+ } else {
+ num = H2PoolUtils.insertAuthInfo(authInfo);
+ }
+ } catch (H2Exception e) {
+ NoticeUtils.show(null, e.getMessage(), Level.WARN);
+ return;
+ }
if (num > 0) {
- AsyncTask.runOnce("克隆项目", () -> {
- JGitUtils.AUTH_INFO_MAP.put(repoType, authInfo);
- JGitUtils.cloneRepo(remoteUrl, file, authInfo);
- });
+ JGitUtils.AUTH_INFO_MAP.put(repoType, authInfo);
+ if (clone) {
+ if (-1 != index) {
+ // 克隆项目时没有权限会执行这段代码
+ DownloadHBox downloadHBox = (DownloadHBox) FxApplicationContextUtils.DOWNLOAD_LIST.get(index);
+ downloadHBox.cloneRepo(JGitUtils.createCredential(username, password), false);
+ } else {
+ // 第一次克隆
+ FxApplicationContextUtils.DOWNLOAD_LIST.add(new DownloadHBox(remoteUrl, file, authInfo, FxApplicationContextUtils.DOWNLOAD_LIST.size()));
+ }
+ } else {
+ // 更新
+ if (null != project) {
+ // 更新更新数量+1
+ FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.incrementAndGet()));
+ AsyncTask.runOnce("更新项目", () -> {
+ try {
+ CredentialsProvider provider = JGitUtils.createCredential(username, password);
+ boolean pull = JGitUtils.pull(remoteUrl, file, provider, rate);
+ if (pull) {
+ project.updateTime().set(DateUtils.formatDateTime(new Date()));
+ H2PoolUtils.updateGitProject(project);
+ project.selected().set(false);
+ }
+ } catch (AuthException e) {
+ // 弹出输入权限界面
+ if (!(Boolean) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("authDialogShowing")) {
+ AuthenticationPane authPane = new AuthenticationPane(false, -1, remoteUrl, file, rate, project, updateButton);
+ Platform.runLater(() -> authPane.show((Scene) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("scene")));
+ }
+ } catch (TimeOutException | JGitException e) {
+
+ }
+ // 更新更新数量-1
+ FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.decrementAndGet()));
+ updateButton.setDisable(false);
+ });
+ }
+ }
+ // 关闭界面
+ close();
+ FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.put("authDialogShowing", false);
}
});
-
return root;
}
}
diff --git a/src/main/java/com/light/component/CustomProgressMonitor.java b/src/main/java/com/light/component/CustomProgressMonitor.java
new file mode 100644
index 0000000000000000000000000000000000000000..e403099cdda87a2cf36ca7fb3ab861359e6af8c4
--- /dev/null
+++ b/src/main/java/com/light/component/CustomProgressMonitor.java
@@ -0,0 +1,52 @@
+package com.light.component;
+
+import javafx.beans.property.SimpleDoubleProperty;
+import javafx.scene.control.ProgressBar;
+import org.eclipse.jgit.lib.BatchingProgressMonitor;
+
+import java.time.Duration;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class CustomProgressMonitor extends BatchingProgressMonitor {
+
+ private final ProgressBar progressBar;
+
+ private final AtomicInteger progress;
+ private final AtomicInteger total;
+
+ private final SimpleDoubleProperty rate;
+
+ public CustomProgressMonitor(ProgressBar progressBar, SimpleDoubleProperty rate) {
+ this.progressBar = progressBar;
+ this.rate = rate;
+ progress = new AtomicInteger(0);
+ total = new AtomicInteger(100);
+ }
+
+ @Override
+ protected void onUpdate(String taskName, int workCurr, Duration duration) {
+
+ }
+
+ @Override
+ protected void onEndTask(String taskName, int workCurr, Duration duration) {
+
+ }
+
+ @Override
+ protected void onUpdate(String taskName, int workCurr, int workTotal, int percentDone, Duration duration) {
+ if (progressBar != null) {
+ progressBar.setProgress((double) (progress.get() + percentDone) / total.get());
+ }
+ if (null != rate) {
+ rate.set((double) (progress.get() + percentDone) / total.get());
+ }
+ }
+
+ @Override
+ protected void onEndTask(String taskName, int workCurr, int workTotal, int percentDone, Duration duration) {
+ progress.addAndGet(percentDone);
+ total.addAndGet(percentDone);
+// System.out.println("taskName: " + taskName + " workCurr: " + workCurr + " workTotal: " + workTotal + " percentDone: " + percentDone);
+ }
+}
diff --git a/src/main/java/com/light/component/DownAndUpdatePane.java b/src/main/java/com/light/component/DownAndUpdatePane.java
new file mode 100644
index 0000000000000000000000000000000000000000..54672bf47675faf3e8cdd4913be49ad84db2d71b
--- /dev/null
+++ b/src/main/java/com/light/component/DownAndUpdatePane.java
@@ -0,0 +1,22 @@
+package com.light.component;
+
+import com.light.layout.ModalDialog;
+import javafx.collections.ObservableList;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.HBox;
+
+public class DownAndUpdatePane extends ModalDialog {
+
+ public DownAndUpdatePane(String title, ObservableList list) {
+ super();
+ header.setTitle(title);
+ content.setBody(createContent(list));
+ content.setFooter(null);
+ }
+
+ private HBox createContent(ObservableList list) {
+ ListView listView = new ListView<>(list);
+ listView.getStyleClass().add("du-list");
+ return new HBox(listView);
+ }
+}
diff --git a/src/main/java/com/light/component/DownloadHBox.java b/src/main/java/com/light/component/DownloadHBox.java
new file mode 100644
index 0000000000000000000000000000000000000000..4d58311fcee2739c2de49f6a2be6980e32f51b81
--- /dev/null
+++ b/src/main/java/com/light/component/DownloadHBox.java
@@ -0,0 +1,162 @@
+package com.light.component;
+
+import atlantafx.base.theme.Styles;
+import com.light.exception.AuthException;
+import com.light.exception.JGitException;
+import com.light.exception.TimeOutException;
+import com.light.model.GitAuthInfo;
+import com.light.model.GitProject;
+import com.light.thread.AsyncTask;
+import com.light.util.DateUtils;
+import com.light.util.FxApplicationContextUtils;
+import com.light.util.H2PoolUtils;
+import com.light.util.JGitUtils;
+import javafx.application.Platform;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleDoubleProperty;
+import javafx.beans.property.SimpleIntegerProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.geometry.Pos;
+import javafx.scene.Scene;
+import javafx.scene.control.Button;
+import javafx.scene.control.Label;
+import javafx.scene.control.ProgressBar;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.VBox;
+import org.eclipse.jgit.transport.CredentialsProvider;
+import org.kordamp.ikonli.bootstrapicons.BootstrapIcons;
+import org.kordamp.ikonli.javafx.FontIcon;
+
+import java.io.File;
+import java.util.Date;
+
+import static com.light.util.JGitUtils.getAuthor;
+import static com.light.util.JGitUtils.getRepoName;
+
+public class DownloadHBox extends HBox {
+ private final String remoteUrl;
+ private final File localRepoFile;
+ private final Button retryButton;
+ private final ProgressBar progressBar = new ProgressBar(0.0);
+ private final CustomProgressMonitor customProgressMonitor = new CustomProgressMonitor(progressBar, null);
+ private final int index;
+
+ private CredentialsProvider provider;
+
+ /**
+ * 构造方法
+ *
+ * @param remoteUrl 远程仓库路径
+ * @param localRepoFile 本地克隆地址
+ * @param authInfo 权限
+ * @param index 在下载列表中的位置
+ */
+ public DownloadHBox(String remoteUrl, File localRepoFile, GitAuthInfo authInfo, int index) {
+ super(10);
+ setAlignment(Pos.CENTER);
+
+ this.remoteUrl = remoteUrl;
+ this.localRepoFile = localRepoFile;
+ this.index = index;
+
+ var label = new Label(getRepoName(remoteUrl));
+
+ progressBar.setMaxWidth(300);
+ var vbox = new VBox(10, label, progressBar);
+
+ retryButton = new Button(null, new FontIcon(BootstrapIcons.PLAY));
+ retryButton.getStyleClass().addAll(Styles.BUTTON_ICON, Styles.FLAT, Styles.ACCENT);
+ retryButton.setVisible(false);
+
+ Button removeButton = new Button(null, new FontIcon(BootstrapIcons.X));
+ removeButton.getStyleClass().addAll(Styles.BUTTON_ICON, Styles.FLAT, Styles.ACCENT);
+ getChildren().addAll(vbox, retryButton, removeButton);
+ HBox.setHgrow(vbox, Priority.ALWAYS);
+
+ // 监控器和权限
+ provider = JGitUtils.createCredential(authInfo.username(), authInfo.password());
+
+ retryButton.setOnMouseClicked(event -> cloneRepo(provider, true));
+ removeButton.setOnMouseClicked(event -> FxApplicationContextUtils.DOWNLOAD_LIST.remove(this));
+ // 更新下载数量+1
+ FxApplicationContextUtils.DOWNLOAD_PROPERTY.set(String.valueOf(FxApplicationContextUtils.DOWNLOAD_NUMBER.incrementAndGet()));
+ cloneRepo(provider, false);
+ }
+
+ /**
+ * 克隆项目
+ *
+ * @param provider 权限
+ * @param retry 重试标识
+ */
+ public void cloneRepo(CredentialsProvider provider, boolean retry) {
+ this.provider = provider;
+ AsyncTask.runOnce("克隆项目", () -> {
+ if (retry) {
+ deleteFiles(localRepoFile);
+ retryButton.setVisible(false);
+ }
+
+ String branch = "";
+ try {
+ // 开始下载
+ branch = JGitUtils.cloneRepo(remoteUrl, localRepoFile, provider, customProgressMonitor);
+ } catch (AuthException e) {
+ // 弹出输入权限界面
+ if (!(Boolean) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("authDialogShowing")) {
+ AuthenticationPane authPane = new AuthenticationPane(true, index, remoteUrl, localRepoFile);
+ Platform.runLater(() -> authPane.show((Scene) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("scene")));
+ }
+ retryButton.setVisible(true);
+ return;
+ } catch (TimeOutException | JGitException e) {
+ retryButton.setVisible(true);
+ return;
+ }
+
+ // 下载完成入库
+ String name = getRepoName(remoteUrl);
+ String author = getAuthor(remoteUrl);
+ String local = localRepoFile.getAbsolutePath();
+ GitProject newProject = new GitProject(new SimpleIntegerProperty(0),
+ new SimpleStringProperty(name),
+ new SimpleStringProperty(author),
+ new SimpleStringProperty(branch),
+ DateUtils.formatDateTime(new Date()),
+ new SimpleStringProperty(DateUtils.formatDateTime(new Date())),
+ remoteUrl,
+ new SimpleStringProperty(local),
+ new SimpleStringProperty(),
+ new SimpleStringProperty(),
+ new SimpleIntegerProperty(0),
+ new SimpleDoubleProperty(0.0),
+ new SimpleBooleanProperty(false)
+ );
+ H2PoolUtils.insertProjectInfo(newProject);
+ FxApplicationContextUtils.GIT_PROJECT_OBSERVABLE_LIST.add(newProject);
+ // 更新下载数量-1
+ FxApplicationContextUtils.DOWNLOAD_PROPERTY.set(String.valueOf(FxApplicationContextUtils.DOWNLOAD_NUMBER.decrementAndGet()));
+ });
+ }
+
+ private void deleteFiles(File folder) {
+ if (folder.exists()) {
+ // 获取文件夹中的所有文件和子文件夹
+ File[] files = folder.listFiles();
+
+ if (files != null) {
+ for (File file : files) {
+ // 如果是文件,则直接删除
+ if (file.isFile()) {
+ file.delete();
+ }
+ // 如果是文件夹,则递归调用deleteFiles方法删除文件夹下的文件
+ else if (file.isDirectory()) {
+ deleteFiles(file);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/light/component/NoticePane.java b/src/main/java/com/light/component/NoticePane.java
new file mode 100644
index 0000000000000000000000000000000000000000..25bfa3ae94bc81b0694951eb4495d58949abc1bb
--- /dev/null
+++ b/src/main/java/com/light/component/NoticePane.java
@@ -0,0 +1,26 @@
+package com.light.component;
+
+import com.light.layout.ModalDialog;
+import javafx.collections.ObservableList;
+import javafx.scene.control.ListView;
+import javafx.scene.layout.HBox;
+
+public class NoticePane extends ModalDialog {
+
+ public NoticePane(String title, ObservableList list) {
+ super();
+ header.setTitle(title);
+ content.setBody(createContent(list));
+ content.setFooter(null);
+ }
+
+ private HBox createContent(ObservableList list) {
+ ListView listView = new ListView<>(list);
+ listView.getStyleClass().add("du-list");
+ listView.setMaxWidth(800);
+ listView.setMinWidth(550);
+ return new HBox(listView);
+ }
+
+
+}
diff --git a/src/main/java/com/light/component/OperationTableCell.java b/src/main/java/com/light/component/OperationTableCell.java
index 7b5e7fa439be0cd23cc473e95175cc1aaa32ca5f..a383e447344f354f9f5ee77c3f186b51661b73e9 100644
--- a/src/main/java/com/light/component/OperationTableCell.java
+++ b/src/main/java/com/light/component/OperationTableCell.java
@@ -1,15 +1,29 @@
package com.light.component;
import atlantafx.base.theme.Styles;
+import com.light.exception.AuthException;
+import com.light.exception.JGitException;
+import com.light.exception.TimeOutException;
+import com.light.model.GitAuthInfo;
import com.light.model.GitProject;
+import com.light.thread.AsyncTask;
+import com.light.util.DateUtils;
import com.light.util.FxApplicationContextUtils;
+import com.light.util.H2PoolUtils;
+import com.light.util.JGitUtils;
+import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.geometry.Pos;
+import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.layout.HBox;
import javafx.util.Callback;
+import org.eclipse.jgit.transport.CredentialsProvider;
+
+import java.io.File;
+import java.util.Date;
/**
* 操作列 - 按钮
@@ -51,11 +65,39 @@ public class OperationTableCell extends TableCell {
private void initEvent() {
// TODO Auto-generated method stub
updateButton.setOnMouseClicked(event -> {
- rate.set(0.0);
- FxApplicationContextUtils.UPDATE_PROPERTY.set(FxApplicationContextUtils.UPDATE_NUMBER.incrementAndGet() + "");
- for (int i = 0; i <= 100; i++) {
- double dRate = (double) i / 100;
- rate.set(dRate);
+ updateButton.setDisable(true);
+ GitProject project = getTableRow().getItem();
+ if (null != project) {
+ // 更新更新数量+1
+ FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.incrementAndGet()));
+ AsyncTask.runOnce("更新项目", () -> {
+ File localRepoFile = new File(project.local().get());
+ String remoteUrl = project.remote();
+ try {
+ GitAuthInfo existsAuthInfo = JGitUtils.isExistsAuthInfo(project.remote());
+ CredentialsProvider provider = null;
+ if (existsAuthInfo != null) {
+ provider = JGitUtils.createCredential(existsAuthInfo.username(), existsAuthInfo.password());
+ }
+ boolean pull = JGitUtils.pull(remoteUrl, localRepoFile, provider, rate);
+ if (pull) {
+ project.updateTime().set(DateUtils.formatDateTime(new Date()));
+ H2PoolUtils.updateGitProject(project);
+ project.selected().set(false);
+ }
+ } catch (AuthException e) {
+ // 弹出输入权限界面
+ if (!(Boolean) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("authDialogShowing")) {
+ AuthenticationPane authPane = new AuthenticationPane(false, -1, remoteUrl, localRepoFile, rate, project, updateButton);
+ Platform.runLater(() -> authPane.show((Scene) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("scene")));
+ }
+ } catch (TimeOutException | JGitException e) {
+
+ }
+ // 更新更新数量-1
+ FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.decrementAndGet()));
+ updateButton.setDisable(false);
+ });
}
});
}
diff --git a/src/main/java/com/light/exception/AuthException.java b/src/main/java/com/light/exception/AuthException.java
new file mode 100644
index 0000000000000000000000000000000000000000..f8365b1f35dfb0ff48b31c16f0c3e6caf2cf21df
--- /dev/null
+++ b/src/main/java/com/light/exception/AuthException.java
@@ -0,0 +1,23 @@
+package com.light.exception;
+
+public class AuthException extends RuntimeException{
+ public AuthException() {
+ super();
+ }
+
+ public AuthException(String message) {
+ super(message);
+ }
+
+ public AuthException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public AuthException(Throwable cause) {
+ super(cause);
+ }
+
+ protected AuthException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/src/main/java/com/light/exception/CustomException.java b/src/main/java/com/light/exception/CustomException.java
new file mode 100644
index 0000000000000000000000000000000000000000..4febef6388cbbfc3261a89bf9afc0dee6fd61802
--- /dev/null
+++ b/src/main/java/com/light/exception/CustomException.java
@@ -0,0 +1,24 @@
+package com.light.exception;
+
+public class CustomException extends Exception{
+
+ public CustomException() {
+ super();
+ }
+
+ public CustomException(String message) {
+ super(message);
+ }
+
+ public CustomException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CustomException(Throwable cause) {
+ super(cause);
+ }
+
+ protected CustomException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/src/main/java/com/light/exception/H2Exception.java b/src/main/java/com/light/exception/H2Exception.java
new file mode 100644
index 0000000000000000000000000000000000000000..72ab1ac8554519a4c30036954a453485091253d0
--- /dev/null
+++ b/src/main/java/com/light/exception/H2Exception.java
@@ -0,0 +1,23 @@
+package com.light.exception;
+
+public class H2Exception extends RuntimeException {
+ public H2Exception() {
+ super();
+ }
+
+ public H2Exception(String message) {
+ super(message);
+ }
+
+ public H2Exception(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public H2Exception(Throwable cause) {
+ super(cause);
+ }
+
+ protected H2Exception(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/src/main/java/com/light/exception/JGitException.java b/src/main/java/com/light/exception/JGitException.java
new file mode 100644
index 0000000000000000000000000000000000000000..1a1d4e786eb84907c837b3e4f1f3e54978b48f91
--- /dev/null
+++ b/src/main/java/com/light/exception/JGitException.java
@@ -0,0 +1,23 @@
+package com.light.exception;
+
+public class JGitException extends RuntimeException{
+ public JGitException() {
+ super();
+ }
+
+ public JGitException(String message) {
+ super(message);
+ }
+
+ public JGitException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public JGitException(Throwable cause) {
+ super(cause);
+ }
+
+ protected JGitException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/src/main/java/com/light/exception/TimeOutException.java b/src/main/java/com/light/exception/TimeOutException.java
new file mode 100644
index 0000000000000000000000000000000000000000..426c37b672df26e857620416f228f22e67ac5c8f
--- /dev/null
+++ b/src/main/java/com/light/exception/TimeOutException.java
@@ -0,0 +1,23 @@
+package com.light.exception;
+
+public class TimeOutException extends RuntimeException{
+ public TimeOutException() {
+ super();
+ }
+
+ public TimeOutException(String message) {
+ super(message);
+ }
+
+ public TimeOutException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TimeOutException(Throwable cause) {
+ super(cause);
+ }
+
+ protected TimeOutException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/src/main/java/com/light/layout/MenuPane.java b/src/main/java/com/light/layout/MenuPane.java
index 512fb33152ced9c9d44fd8a6a6566cbc0ac9c2f0..0bd572fb1efbf5adb099f764320e056f9fe4d4d1 100644
--- a/src/main/java/com/light/layout/MenuPane.java
+++ b/src/main/java/com/light/layout/MenuPane.java
@@ -1,6 +1,8 @@
package com.light.layout;
import atlantafx.base.theme.Styles;
+import com.light.component.DownAndUpdatePane;
+import com.light.component.NoticePane;
import com.light.theme.ThemeDialog;
import com.light.util.FxApplicationContextUtils;
import com.light.util.FxUtil;
@@ -8,6 +10,7 @@ import com.light.util.Lazy;
import com.light.view.HomeView;
import com.light.view.ManagerView;
import com.light.view.NotificationView;
+import javafx.collections.ListChangeListener;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
@@ -39,10 +42,10 @@ public class MenuPane extends StackPane {
// 底部导航栏
private final Label downloadLabel = new Label("正在下载", new FontIcon(BootstrapIcons.ARROW_DOWN));
- private final Text downloadLabelText = new Text(FxApplicationContextUtils.DOWNLOAD_PROPERTY.getValue().toString());
+ private final Text downloadLabelText = new Text(FxApplicationContextUtils.DOWNLOAD_PROPERTY.getValue());
private final HBox downloadBox = new HBox(10, downloadLabel, downloadLabelText);
private final Label updateLabel = new Label("正在更新", new FontIcon(BootstrapIcons.ARROW_DOWN));
- private final Text updateLabelText = new Text(FxApplicationContextUtils.UPDATE_PROPERTY.getValue().toString());
+ private final Text updateLabelText = new Text(FxApplicationContextUtils.UPDATE_PROPERTY.getValue());
private final HBox updateBox = new HBox(10, updateLabel, updateLabelText);
private final VBox bottomMenu = new VBox(downloadBox, updateBox);
@@ -107,5 +110,57 @@ public class MenuPane extends StackPane {
ThemeDialog themeDialog = (ThemeDialog) setting.getContent().get();
themeDialog.show(getScene());
});
+
+ // 通知
+ NoticePane noticePane = new NoticePane("消息", FxApplicationContextUtils.HISTORY_NOTICE_LIST);
+ notification.setOnMouseClicked(event -> {
+ noticePane.show(getScene());
+ });
+
+ DownAndUpdatePane downloadPane = new DownAndUpdatePane("下载", FxApplicationContextUtils.DOWNLOAD_LIST);
+ downloadLabel.setOnMouseClicked(event -> {
+ downloadPane.show(getScene());
+ });
+
+ /**
+ * 正在下载视图
+ * 项目名 进度条 暂停按钮 取消按钮
+ */
+ /*downloadLabel.setOnMouseClicked(event -> {
+ //纵向布局
+ VBox vBox = new VBox(10);
+ List hBoxList = new ArrayList<>();
+ for(int i=1; i<=10; i++){
+ //横向布局
+ HBox hBox = new HBox(15);
+ hBox.setAlignment(Pos.CENTER);
+ hBox.getStyleClass().add("menu");
+
+ //项目名
+ Label projectName = new Label("项目" + i);
+ projectName.setAlignment(Pos.CENTER_LEFT);
+ //进度条
+ ProgressBar bar = new ProgressBar(0);
+ bar.setProgress(0.8);
+
+ //暂停按钮
+ Button stopBtn = new Button("暂停");
+ stopBtn.setAlignment(Pos.CENTER_RIGHT);
+ stopBtn.setOnAction(ss -> {
+ if("暂停".equals(stopBtn.getText())){
+ stopBtn.setText("开始");
+ }else if("开始".equals(stopBtn.getText())){
+ stopBtn.setText("暂停");
+ }
+ });
+ //取消按钮
+ Button cannel = new Button("取消");
+ cannel.setAlignment(Pos.CENTER_RIGHT);
+ hBox.getChildren().addAll(projectName,bar,stopBtn,cannel);
+ hBoxList.add(hBox);
+ }
+ vBox.getChildren().addAll(hBoxList);
+ contentPane.setContent(vBox);
+ });*/
}
}
diff --git a/src/main/java/com/light/model/GitProject.java b/src/main/java/com/light/model/GitProject.java
index a5af28b4653a87a67f6c0d5c3ba48e9d55109288..169a15d3b2668613435545a4ffa91caed458c000 100644
--- a/src/main/java/com/light/model/GitProject.java
+++ b/src/main/java/com/light/model/GitProject.java
@@ -19,13 +19,4 @@ public record GitProject(SimpleIntegerProperty id,
SimpleIntegerProperty level,
SimpleDoubleProperty downloadRate,
SimpleBooleanProperty selected) {
-
- public void addSelectedListener() {
- downloadRate.addListener((observable, oldValue, newValue) -> {
- if (newValue != null && newValue.doubleValue() >= 1.0) {
- selected.set(false);
- FxApplicationContextUtils.UPDATE_PROPERTY.set(FxApplicationContextUtils.UPDATE_NUMBER.decrementAndGet() + "");
- }
- });
- }
}
diff --git a/src/main/java/com/light/util/FxApplicationContextUtils.java b/src/main/java/com/light/util/FxApplicationContextUtils.java
index 7afdffade5335feb48fe02d9945e0bcbe55bf798..0ff48b63a507fd9c7e17220cbd15e345e361564f 100644
--- a/src/main/java/com/light/util/FxApplicationContextUtils.java
+++ b/src/main/java/com/light/util/FxApplicationContextUtils.java
@@ -1,13 +1,17 @@
package com.light.util;
-import atlantafx.base.theme.*;
+import atlantafx.base.theme.Theme;
import com.light.model.GitProject;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
+import javafx.scene.layout.HBox;
+import javafx.scene.text.Text;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -15,24 +19,30 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public final class FxApplicationContextUtils {
+ /**
+ * 全局容器
+ */
+ public static final Map GLOBAL_CONTEXT_MAP = new ConcurrentHashMap<>();
+
/**
* 正在下载数量
*/
public static final AtomicInteger DOWNLOAD_NUMBER = new AtomicInteger(0);
public static final SimpleStringProperty DOWNLOAD_PROPERTY = new SimpleStringProperty(DOWNLOAD_NUMBER.toString());
+ public static final ObservableList DOWNLOAD_LIST = FXCollections.observableArrayList();
+
/**
* 正在更新数量
*/
public static final AtomicInteger UPDATE_NUMBER = new AtomicInteger(0);
public static final SimpleStringProperty UPDATE_PROPERTY = new SimpleStringProperty(UPDATE_NUMBER.toString());
-
/**
* git项目集合
*/
public static final ObservableList GIT_PROJECT_OBSERVABLE_LIST = FXCollections.observableArrayList();
/**
- * 当前主题民初
+ * 当前主题名称
*/
public static final SimpleStringProperty CURRENT_THEME_NAME = new SimpleStringProperty();
diff --git a/src/main/java/com/light/util/H2PoolUtils.java b/src/main/java/com/light/util/H2PoolUtils.java
index 2ee47914d1502a321601e4dd66a8bd08f4d93739..7f7485ebd1659cbc99b3ad78464bc531e75b8b3e 100644
--- a/src/main/java/com/light/util/H2PoolUtils.java
+++ b/src/main/java/com/light/util/H2PoolUtils.java
@@ -1,5 +1,6 @@
package com.light.util;
+import com.light.exception.H2Exception;
import com.light.model.GitAuthInfo;
import com.light.model.GitNotice;
import com.light.model.GitProject;
@@ -98,6 +99,7 @@ public class H2PoolUtils {
stmt.executeUpdate("drop table git_project_info if exists");
stmt.executeUpdate("drop table git_project_dict if exists");
stmt.executeUpdate("drop table git_project_notice_history if exists");
+ stmt.executeUpdate("drop table git_auth_info if exists");
// 初始化项目信息表
String createGitProjectInfoTable = """
create table git_project_info
@@ -202,7 +204,7 @@ public class H2PoolUtils {
return list;
}
- public static int insertAuthInfo(GitAuthInfo authInfo) {
+ public static int insertAuthInfo(GitAuthInfo authInfo) throws H2Exception {
try (Connection conn = getConnection()) {
String sql = "INSERT INTO git_auth_info(type, username, password, createtime) values(?,?,?,?)";
PreparedStatement statement = conn.prepareStatement(sql);
@@ -213,11 +215,11 @@ public class H2PoolUtils {
return statement.executeUpdate();
} catch (SQLException e) {
LOGGER.error("记录权限信息异常:{}", e.getMessage());
+ throw new H2Exception("记录权限信息异常");
}
- return 0;
}
- public static int updateAuthInfo(String type, String username, String password) {
+ public static int updateAuthInfo(String type, String username, String password) throws H2Exception {
try (Connection conn = getConnection()) {
String sql = "update git_auth_info set username = ?, password = ? where type = ?";
PreparedStatement statement = conn.prepareStatement(sql);
@@ -227,8 +229,8 @@ public class H2PoolUtils {
return statement.executeUpdate();
} catch (SQLException e) {
LOGGER.error("通过 {} 更新权限信息为 {} 失败:{}", type, username, e.getMessage());
+ throw new H2Exception("更新权限信息异常");
}
- return 0;
}
public static int deleteAuthInfo(String type) {
@@ -252,12 +254,19 @@ public class H2PoolUtils {
Date currentDate = new Date();
Connection conn = getConnection();
Statement stmt = conn.createStatement();
+ String dateTime = DateUtils.formatDateTime(currentDate);
String sql = "insert into git_project_dict(label, label_value, description, createtime, updatetime) values('GIT_DB_INIT','1','项目数据库初始化标识:0 未初始化,1 初始化', " +
- "'" + DateUtils.formatDateTime(currentDate) + "', '" + DateUtils.formatDateTime(currentDate) + "')";
+ "'" + dateTime + "', '" + dateTime + "')";
stmt.addBatch(sql);
String sql2 = "insert into git_project_dict(label, label_value, description, createtime, updatetime) values('GIT_CURRENT_THEME','Primer Light','项目当前主题', " +
- "'" + DateUtils.formatDateTime(currentDate) + "', '" + DateUtils.formatDateTime(currentDate) + "')";
+ "'" + dateTime + "', '" + dateTime + "')";
stmt.addBatch(sql2);
+ String sql3 = "insert into git_project_dict(label, label_value, description, createtime, updatetime) values('GIT_CURRENT_CLONE_DIR','D:','项目克隆路径', " +
+ "'" + dateTime + "', '" + dateTime + "')";
+ stmt.addBatch(sql3);
+ String sql4 = "insert into git_project_dict(label, label_value, description, createtime, updatetime) values('GIT_CURRENT_LOCAL_DIR','D:','本地项目路径', " +
+ "'" + dateTime + "', '" + dateTime + "')";
+ stmt.addBatch(sql4);
stmt.executeBatch();
LOGGER.info("h2 字典表数据初始化成功");
}
@@ -286,8 +295,8 @@ public class H2PoolUtils {
statement.setString(1, value);
statement.setString(2, label);
statement.executeUpdate();
- } catch (SQLException ignored) {
- LOGGER.error("通过 {} 更新数据为 {} 失败:{}", label, value, ignored.getMessage());
+ } catch (SQLException e) {
+ LOGGER.error("通过 {} 更新数据为 {} 失败:{}", label, value, e.getMessage());
}
LOGGER.info("通过 {} 更新数据为 {} 成功", label, value);
}
@@ -383,7 +392,6 @@ public class H2PoolUtils {
new SimpleDoubleProperty(0.0),
new SimpleBooleanProperty(false)
);
- gitProject.addSelectedListener();
FxApplicationContextUtils.GIT_PROJECT_OBSERVABLE_LIST.add(gitProject);
}
} catch (SQLException e) {
diff --git a/src/main/java/com/light/util/JGitUtils.java b/src/main/java/com/light/util/JGitUtils.java
index 10fdc1456953c28367494b3ba1f6914aef0cee72..8bd8502577d7a097e17d7dfc0a7f082ea65c0572 100644
--- a/src/main/java/com/light/util/JGitUtils.java
+++ b/src/main/java/com/light/util/JGitUtils.java
@@ -1,5 +1,9 @@
package com.light.util;
+import com.light.component.CustomProgressMonitor;
+import com.light.exception.AuthException;
+import com.light.exception.JGitException;
+import com.light.exception.TimeOutException;
import com.light.model.GitAuthInfo;
import com.light.model.GitProject;
import javafx.beans.property.SimpleBooleanProperty;
@@ -7,14 +11,14 @@ import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import org.eclipse.jgit.api.Git;
-import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.PullCommand;
+import org.eclipse.jgit.api.PullResult;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
-import java.io.IOException;
import java.util.*;
public class JGitUtils {
@@ -84,7 +88,7 @@ public class JGitUtils {
*/
public static String getAuthor(String remoteUrl) {
String author = remoteUrl.substring(0, remoteUrl.lastIndexOf("/"));
- return author = author.substring(author.lastIndexOf("/") + 1);
+ return author.substring(author.lastIndexOf("/") + 1);
}
/**
@@ -159,7 +163,6 @@ public class JGitUtils {
newProject = null;
} else {
// 不存在则继续新增,并设置id
- newProject.addSelectedListener();
H2PoolUtils.insertProjectInfo(newProject);
FxApplicationContextUtils.GIT_PROJECT_OBSERVABLE_LIST.add(newProject);
}
@@ -172,69 +175,47 @@ public class JGitUtils {
PROJECT_FILE.clear();
}
- public static void cloneRepo(String remoteUrl, File localRepoFile, GitAuthInfo authInfo) {
- // 更新下载数量
- FxApplicationContextUtils.DOWNLOAD_PROPERTY.set(String.valueOf(FxApplicationContextUtils.DOWNLOAD_NUMBER.incrementAndGet()));
-
- String name = getRepoName(remoteUrl);
- String author = getAuthor(remoteUrl);
- String local = localRepoFile.getAbsolutePath();
-
+ public static String cloneRepo(String remoteUrl, File localRepoFile, CredentialsProvider provider, CustomProgressMonitor monitor) throws JGitException, AuthException, TimeOutException {
try (Git git = Git.cloneRepository()
- .setCredentialsProvider(createCredential(authInfo.username(), authInfo.password()))
- .setURI(remoteUrl).setDirectory(localRepoFile).call()) {
- String branch = git.getRepository().getBranch();
- GitProject newProject = new GitProject(new SimpleIntegerProperty(0),
- new SimpleStringProperty(name),
- new SimpleStringProperty(author),
- new SimpleStringProperty(branch),
- DateUtils.formatDateTime(new Date()),
- new SimpleStringProperty(DateUtils.formatDateTime(new Date())),
- remoteUrl,
- new SimpleStringProperty(local),
- new SimpleStringProperty(),
- new SimpleStringProperty(),
- new SimpleIntegerProperty(0),
- new SimpleDoubleProperty(0.0),
- new SimpleBooleanProperty(false)
- );
- newProject.addSelectedListener();
- H2PoolUtils.insertProjectInfo(newProject);
- FxApplicationContextUtils.GIT_PROJECT_OBSERVABLE_LIST.add(newProject);
+ .setCredentialsProvider(provider)
+ .setURI(remoteUrl).setDirectory(localRepoFile).setProgressMonitor(monitor).call()) {
+ return git.getRepository().getBranch();
} catch (Exception e) {
- LOGGER.error("项目 {},作者 {} 克隆失败:{}", name, author, e.getMessage());
+ String message = e.getMessage();
+ LOGGER.error("项目 {} 克隆异常:{}", remoteUrl, message);
+ if (message.contains("authorized") || message.contains("Authentication")) {
+ // 权限异常
+ throw new AuthException();
+ } else if (message.contains("time out") || message.contains("timeout")) {
+ // 超时异常
+ throw new TimeOutException();
+ }
+ throw new JGitException();
}
- FxApplicationContextUtils.DOWNLOAD_PROPERTY.set(String.valueOf(FxApplicationContextUtils.DOWNLOAD_NUMBER.decrementAndGet()));
}
- /*private static void pull(String localDirPath, String remoteUrl) {
- Git git = null;
- try {
- System.out.println("remoteUrl: " + remoteUrl + " --- localPath: " + localDirPath + " --- 开始拉取数据");
- File localPath = new File(localDirPath);
- git = Git.open(localPath);
+ public static boolean pull(String remoteUrl, File localRepoFile, CredentialsProvider provider, SimpleDoubleProperty rate) throws JGitException, AuthException, TimeOutException {
+ try (Git git = Git.open(localRepoFile)) {
PullCommand pullCommand = git.pull();
- pullCommand.setTimeout(5);
- pullCommand.setCredentialsProvider(usernamePasswordCredentialsProvider);
- PullResult call = pullCommand.call();
- if (call.isSuccessful()) {
- System.out.println("remoteUrl: " + remoteUrl + " --- localPath: " + localDirPath + " --- 拉取成功 --- 合并数据: " + call.getMergeResult());
+ pullCommand.setTimeout(10);
+ if (provider != null) {
+ pullCommand.setCredentialsProvider(provider);
}
- } catch (IOException e) {
- githubMaxNum++;
- System.out.println("IO pull : " + e.getMessage());
- } catch (GitAPIException e) {
- githubMaxNum++;
- System.out.println("Git pull : " + e.getMessage());
- } finally {
- if (Objects.nonNull(git)) {
- git.close();
+ pullCommand.setProgressMonitor(new CustomProgressMonitor(null, rate));
+ PullResult call = pullCommand.call();
+ return call.isSuccessful();
+ } catch (Exception e) {
+ String message = e.getMessage();
+ LOGGER.error("项目 {} 更新异常:{}", remoteUrl, message);
+ FxApplicationContextUtils.HISTORY_NOTICE_LIST.add(e.getMessage());
+ if (message.contains("authorized") || message.contains("Authentication")) {
+ // 权限异常
+ throw new AuthException();
+ } else if (message.contains("time out") || message.contains("timeout")) {
+ // 超时异常
+ throw new TimeOutException();
}
+ throw new JGitException();
}
- }*/
-
- private static String getRemoteUrl(File localPath) throws IOException, GitAPIException {
- Git git = Git.open(localPath);
- return git.remoteList().call().get(0).getURIs().get(0).toString();
}
}
diff --git a/src/main/java/com/light/view/HomeView.java b/src/main/java/com/light/view/HomeView.java
index 8ac4400f68783e741bfdb0a96d8249b5a76b21f4..8e620893a31960e96c247d1f857eeba50c5322ec 100644
--- a/src/main/java/com/light/view/HomeView.java
+++ b/src/main/java/com/light/view/HomeView.java
@@ -2,9 +2,10 @@ package com.light.view;
import atlantafx.base.controls.CustomTextField;
import com.light.component.AuthenticationPane;
+import com.light.component.DownloadHBox;
import com.light.enums.Level;
import com.light.model.GitAuthInfo;
-import com.light.thread.AsyncTask;
+import com.light.util.FxApplicationContextUtils;
import com.light.util.H2PoolUtils;
import com.light.util.JGitUtils;
import javafx.beans.property.SimpleStringProperty;
@@ -21,14 +22,13 @@ import org.kordamp.ikonli.javafx.FontIcon;
import java.io.File;
import static com.light.util.NoticeUtils.show;
-import static com.light.view.ManagerView.INIT_DIR;
public class HomeView extends BorderPane {
private final DirectoryChooser dirChooser = new DirectoryChooser();
private final SimpleStringProperty targetFolderPath = new SimpleStringProperty();
- private final TextField downloadPath = new TextField();
- private final CustomTextField targetPath = new CustomTextField(targetFolderPath.get());
+ private final TextField clonePathField = new TextField();
+ private final CustomTextField targetPathField = new CustomTextField(targetFolderPath.get());
private final FontIcon right = new FontIcon(AntDesignIconsOutlined.FOLDER);
private final Button downloadButton = new Button("下载");
@@ -37,30 +37,31 @@ public class HomeView extends BorderPane {
VBox downloadVBox = new VBox(10);
downloadVBox.setAlignment(Pos.CENTER);
// 下载框
- downloadPath.setPromptText("请输入远程项目地址");
- downloadPath.setMaxWidth(600);
+ clonePathField.setPromptText("请输入远程项目地址");
+ clonePathField.setMaxWidth(600);
// 目的地框
- targetPath.setPromptText("请输入本地仓库地址");
- targetPath.setRight(right);
- targetPath.setMaxWidth(600);
+ targetPathField.setPromptText("请输入本地仓库地址");
+ targetPathField.setRight(right);
+ targetPathField.setMaxWidth(600);
// 下载按钮
downloadButton.setDisable(true);
- downloadVBox.getChildren().addAll(downloadPath, targetPath, downloadButton);
+ downloadVBox.getChildren().addAll(clonePathField, targetPathField, downloadButton);
this.setCenter(downloadVBox);
initEvent();
+ FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.put("authDialogShowing", false);
}
private void initEvent() {
downloadButton.setOnAction(btn -> {
try {
- String remoteUrl = downloadPath.getText();
- String localRepoFile = targetPath.getText();
+ String remoteUrl = clonePathField.getText();
+ String localRepoFile = targetPathField.getText();
if (StringUtils.isAnyBlank(remoteUrl, localRepoFile)) {
show(null, "请检查项目地址和仓库地址不能为空", Level.WARN);
} else {
// 检查仓库地址是不是为空
- File file = new File(targetPath.getText());
+ File file = new File(targetPathField.getText());
if (file.isFile() || (file.isDirectory() && file.listFiles().length > 0)) {
show(null, "仓库地址不为空", Level.WARN);
return;
@@ -70,21 +71,18 @@ public class HomeView extends BorderPane {
show(null, "项目已经存在", Level.WARN);
return;
}
- // 项目保存地址不存在则创建
- boolean newFolder = file.exists();
- if (!newFolder) {
- newFolder = file.mkdirs();
- }
- if (newFolder) {
- // 判断权限信息是否存在
- GitAuthInfo authInfo = JGitUtils.isExistsAuthInfo(remoteUrl);
- if (authInfo != null) {
- AsyncTask.runOnce("克隆项目", () -> JGitUtils.cloneRepo(remoteUrl, file, authInfo));
- } else {
- AuthenticationPane authPane = new AuthenticationPane(JGitUtils.getType(remoteUrl), remoteUrl, file);
- authPane.show(getScene());
- }
+ // 判断权限信息是否存在
+ GitAuthInfo authInfo = JGitUtils.isExistsAuthInfo(remoteUrl);
+ if (authInfo != null) {
+ FxApplicationContextUtils.DOWNLOAD_LIST.add(new DownloadHBox(remoteUrl, file, authInfo, FxApplicationContextUtils.DOWNLOAD_LIST.size()));
+ } else {
+ AuthenticationPane authPane = new AuthenticationPane(true, -1, remoteUrl, file);
+ authPane.show(getScene());
}
+ // 清空信息
+ clonePathField.setText("");
+ targetPathField.setText("");
+ downloadButton.setDisable(true);
}
} catch (Exception e) {
show(null, "下载失败,请稍后重试", Level.DANGER);
@@ -92,27 +90,40 @@ public class HomeView extends BorderPane {
});
right.setOnMouseClicked(event -> {
- dirChooser.setInitialDirectory(new File(INIT_DIR + File.separator));
+ dirChooser.setInitialDirectory(new File(H2PoolUtils.queryDictByLabel("GIT_CURRENT_CLONE_DIR", "D:") + File.separator));
File file = dirChooser.showDialog(getScene().getWindow());
if (null != file) {
- targetPath.setText(file.getPath());
targetFolderPath.set(file.getPath());
+ H2PoolUtils.updateDictData("GIT_CURRENT_CLONE_DIR", file.getPath());
+
+ String downloadPathText = clonePathField.getText();
+ if (StringUtils.isNotBlank(downloadPathText)) {
+ if (downloadPathText.contains("/") && !downloadPathText.startsWith("/")) {
+ String downloadPathFolder = downloadPathText.substring(downloadPathText.lastIndexOf("/") + 1);
+ String actPath = downloadPathFolder.endsWith(".git") ? downloadPathFolder.substring(0, downloadPathFolder.lastIndexOf(".")) : downloadPathFolder;
+ targetPathField.setText(file.getPath() + File.separator + actPath);
+ } else {
+ targetPathField.setText(file.getPath());
+ }
+ } else {
+ targetPathField.setText(file.getPath());
+ }
}
event.consume();
});
- downloadPath.setOnKeyReleased(event -> {
+ clonePathField.setOnKeyReleased(event -> {
String targetPathText = StringUtils.isBlank(targetFolderPath.get()) ? "" : targetFolderPath.get() + File.separator;
- String downloadPathText = downloadPath.getText();
+ String downloadPathText = clonePathField.getText();
if (downloadPathText.contains("/") && !downloadPathText.startsWith("/")) {
String downloadPathFolder = downloadPathText.substring(downloadPathText.lastIndexOf("/") + 1);
String actPath = downloadPathFolder.endsWith(".git") ? downloadPathFolder.substring(0, downloadPathFolder.lastIndexOf(".")) : downloadPathFolder;
if (StringUtils.isNotBlank(targetPathText)) {
- targetPath.setText(targetPathText + actPath);
+ targetPathField.setText(targetPathText + actPath);
}
downloadButton.setDisable(!downloadPathText.endsWith(".git"));
} else {
- targetPath.setText(targetPathText);
+ targetPathField.setText(targetPathText);
downloadButton.setDisable(true);
}
});
diff --git a/src/main/java/com/light/view/ManagerView.java b/src/main/java/com/light/view/ManagerView.java
index b81404ef74473840ea24e027e24d4f93e797024c..2ac8bc01f1687d783cd810a4a8d1a885a53eaa0f 100644
--- a/src/main/java/com/light/view/ManagerView.java
+++ b/src/main/java/com/light/view/ManagerView.java
@@ -3,16 +3,25 @@ package com.light.view;
import atlantafx.base.controls.CustomTextField;
import atlantafx.base.theme.Styles;
import atlantafx.base.theme.Tweaks;
+import com.light.component.AuthenticationPane;
import com.light.component.LevelTableCell;
import com.light.component.OperationTableCell;
import com.light.component.TooltipTableRow;
+import com.light.exception.AuthException;
+import com.light.exception.JGitException;
+import com.light.exception.TimeOutException;
+import com.light.model.GitAuthInfo;
import com.light.model.GitProject;
import com.light.thread.AsyncTask;
+import com.light.util.DateUtils;
import com.light.util.FxApplicationContextUtils;
import com.light.util.H2PoolUtils;
import com.light.util.JGitUtils;
+import javafx.application.Platform;
+import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
+import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableColumn;
@@ -25,10 +34,12 @@ import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.DirectoryChooser;
import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jgit.transport.CredentialsProvider;
import org.kordamp.ikonli.bootstrapicons.BootstrapIcons;
import org.kordamp.ikonli.javafx.FontIcon;
import java.io.File;
+import java.util.Date;
import java.util.List;
public class ManagerView extends StackPane {
@@ -37,7 +48,6 @@ public class ManagerView extends StackPane {
private CustomTextField searchField;
private final Button updateButton = new Button("更新");
private final Button addLocalButton = new Button("添加本地项目");
- public static final String INIT_DIR = "D:";
private final DirectoryChooser dirChooser = new DirectoryChooser();
private final HBox hBox = new HBox(5);
@@ -52,8 +62,6 @@ public class ManagerView extends StackPane {
this.getChildren().add(vBox);
initialize();
initEvent();
- // 异步初始化数据
- AsyncTask.runOnce("初始化项目数据", this::initData);
}
public void initialize() {
@@ -127,11 +135,6 @@ public class ManagerView extends StackPane {
tableView.setEditable(true);
}
- public void initData() {
- // 查H2数据库获取数据
- H2PoolUtils.queryGitProjects();
- }
-
public void initEvent() {
// 全选按钮事件
selectAll.setOnAction(event -> {
@@ -141,13 +144,13 @@ public class ManagerView extends StackPane {
event.consume();
});
- /**
+ /*
* 添加本地项目按钮事件
* 输入框 让用户键入代码存放路径
* 按钮 加载
*/
addLocalButton.setOnAction(btn -> {
- dirChooser.setInitialDirectory(new File(INIT_DIR + File.separator));
+ dirChooser.setInitialDirectory(new File(H2PoolUtils.queryDictByLabel("GIT_CURRENT_LOCAL_DIR", "D:") + File.separator));
File file = dirChooser.showDialog(getScene().getWindow());
if (null != file) {
AsyncTask.runOnce("加载本地项目", () -> {
@@ -180,14 +183,40 @@ public class ManagerView extends StackPane {
List list = tableView.getItems().stream().filter(param -> param.selected().get()).toList();
if (!list.isEmpty()) {
updateButton.setDisable(true);
- FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.addAndGet(list.size())));
}
list.forEach(param -> {
- param.downloadRate().set(0.0);
- for (int i = 0; i <= 100; i++) {
- double dRate = (double) i / 100;
- param.downloadRate().set(dRate);
- }
+ SimpleDoubleProperty rate = param.downloadRate();
+ rate.set(0.0);
+ // 更新更新数量+1
+ FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.incrementAndGet()));
+ AsyncTask.runOnce("更新项目", () -> {
+ File localRepoFile = new File(param.local().get());
+ String remoteUrl = param.remote();
+ try {
+ GitAuthInfo existsAuthInfo = JGitUtils.isExistsAuthInfo(param.remote());
+ CredentialsProvider provider = null;
+ if (existsAuthInfo != null) {
+ provider = JGitUtils.createCredential(existsAuthInfo.username(), existsAuthInfo.password());
+ }
+ boolean pull = JGitUtils.pull(remoteUrl, localRepoFile, provider, rate);
+ if (pull) {
+ param.updateTime().set(DateUtils.formatDateTime(new Date()));
+ H2PoolUtils.updateGitProject(param);
+ param.selected().set(false);
+ }
+ } catch (AuthException e) {
+ // 弹出输入权限界面
+ if (!(Boolean) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("authDialogShowing")) {
+ AuthenticationPane authPane = new AuthenticationPane(false, -1, remoteUrl, localRepoFile, rate, param, updateButton);
+ Platform.runLater(() -> authPane.show((Scene) FxApplicationContextUtils.GLOBAL_CONTEXT_MAP.get("scene")));
+ }
+ } catch (TimeOutException | JGitException e) {
+
+ }
+ // 更新更新数量-1
+ FxApplicationContextUtils.UPDATE_PROPERTY.set(String.valueOf(FxApplicationContextUtils.UPDATE_NUMBER.decrementAndGet()));
+ updateButton.setDisable(false);
+ });
});
});
}
diff --git a/src/main/java/com/light/view/NotificationView.java b/src/main/java/com/light/view/NotificationView.java
index a7870d4ee9ed89c8fdb40e816f533f21d759fa3c..af09622f24eaa18eed5fe732ec447cd7e1039390 100644
--- a/src/main/java/com/light/view/NotificationView.java
+++ b/src/main/java/com/light/view/NotificationView.java
@@ -1,13 +1,14 @@
package com.light.view;
+import atlantafx.base.theme.Styles;
import com.light.util.FxApplicationContextUtils;
import javafx.collections.ListChangeListener;
-import javafx.scene.control.Label;
+import javafx.scene.text.Text;
-public class NotificationView extends Label {
+public class NotificationView extends Text {
public NotificationView() {
super(FxApplicationContextUtils.HISTORY_NOTICE_LIST.size() + "");
- this.getStyleClass().add("notice-label");
+ getStyleClass().addAll(Styles.TEXT, Styles.WARNING);
FxApplicationContextUtils.HISTORY_NOTICE_LIST.addListener((ListChangeListener) c -> setText(FxApplicationContextUtils.HISTORY_NOTICE_LIST.size() + ""));
}
}
diff --git a/src/main/resources/css/menu.css b/src/main/resources/css/menu.css
index fca6ccaf4e3c09f643103fe624e3c06f2b3a476a..f2a1ba5901ac9a45378b583def9ecf86633dc144 100644
--- a/src/main/resources/css/menu.css
+++ b/src/main/resources/css/menu.css
@@ -53,7 +53,7 @@
-fx-icon-color: -cf-primary-color;
}
-/*动态导航栏*/
+/*动态菜单导航栏*/
.menu {
-fx-background-insets: 0px;
-fx-background-color: transparent;
diff --git a/src/main/resources/css/root.css b/src/main/resources/css/root.css
index 1e94ac24f857a8aa3643fff6bb68da02ece271f4..b2b9a7998113878ef78777db2b36750a5f43bd04 100644
--- a/src/main/resources/css/root.css
+++ b/src/main/resources/css/root.css
@@ -51,4 +51,19 @@
.theme-thumbnail > .label {
-fx-underline: true;
+}
+
+.du-list {
+ -fx-background-insets: 0px;
+ -fx-background-color: transparent;
+ -fx-padding: 0 0 5px 0;
+ -fx-border-width: 0;
+}
+
+.du-list .scroll-bar {
+ -fx-opacity: 0;
+}
+
+.du-list:hover .scroll-bar {
+ -fx-opacity: 1;
}
\ No newline at end of file