Push first working version
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
[submodule "io.gitea.mylyn.updatesite"]
|
||||
path = io.gitea.mylyn.updatesite
|
||||
url = https://forge.chapril.org/gitea/mylyn-gitea-updatesite.git
|
||||
[submodule "java.gitea.api"]
|
||||
path = java.gitea.api
|
||||
url = https://forge.chapril.org/gitea/java.gitea.api.git
|
11
.project
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>mylyn-gitea</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
</natures>
|
||||
</projectDescription>
|
72
README.md
@ -1,34 +1,40 @@
|
||||
# mylyn-gitea
|
||||
|
||||
Gitea Mylyn Connector : Gitea Issues management for Eclipse/Mylyn.
|
||||
Mylyn/Gitea Tasks Connector : Gitea's issues management for Eclipse/Mylyn.
|
||||
|
||||
This Mylyn connector will allow you to connect Mylyn to a Gitea instance (self hosted or not) in order to manage your issues on Gitea with your local Eclipse instance.
|
||||
This Mylyn connector will allow you to connect Mylyn to a Gitea's instance (self hosted or not) in order to manage your issues from your local Eclipse instance.
|
||||
|
||||
The update site for the Mylyn/Gitea Tasks Connector plug-in is https://forge.chapril.org/gitea/mylyn-gitea-updatesite.
|
||||
|
||||
## Thanks and Credits
|
||||
|
||||
I want to thanks and credit:
|
||||
|
||||
* pweingardt for the "Mylyn Gilab Connector" https://github.com/pweingardt/mylyn-gitlab, the "Mylyn Gitea Connector" which helps me in my initial plugin setup.
|
||||
* zeripath for the "Java Gitea API" https://github.com/zeripath/java-gitea-api , I used first to communicate with Gitea instance before facing ssl and JDK 11 compliance issues.
|
||||
* pweingardt for the "Mylyn Gilab Connector" https://github.com/pweingardt/mylyn-gitlab, the "Mylyn Gitlab Connector" which helps me in my initial plug-ins setup.
|
||||
* zeripath for the "Java Gitea API" https://github.com/zeripath/java-gitea-api , I used first to communicate with Gitea's instance before facing ssl and JDK 11 compliance issues.
|
||||
|
||||
## Changes
|
||||
|
||||
* 08.02.2021 - I'm currently working to make the connector working, resolving package and installation issues (plugins crash on eclipse start due to missing class Exception), then I will debug basic features (repository connectorion ...) before I will upload first code and binaries.
|
||||
* 28.02.2021 - First connector version is working in debug in front og https://forge.chapril.org. I still have maven/jdk 11 generation issue. So I switch to a newly generated "Java Gitea API", OpenAPI based.
|
||||
* 08.02.2021 - I'm currently working to make the connector working, resolving package and installation issues (plug-ins crash on eclipse start due to missing class Exception), then I will debug basic features (repository connectorion ...) before I will upload first code and binaries.
|
||||
* 28.02.2021 - First connector version is working in debug in front of https://forge.chapril.org. I still have maven/jdk 11 generation issue. So I switch to a newly generated "Java Gitea API", OpenAPI based.
|
||||
|
||||
|
||||
## Planned Features
|
||||
|
||||
### Version 0.1.x - prove of concept
|
||||
* use basic (user,password) or token authentication (preferred)
|
||||
* list and query for issues
|
||||
* handles issues on a repository basis
|
||||
|
||||
- [ ] use basic (user,password) or token authentication (preferred)
|
||||
- [ ] list and query for issues
|
||||
- [ ] handles issues on a repository basis
|
||||
- [ ] installation though update site
|
||||
|
||||
### Planned features
|
||||
* edit issue - add comment on issues
|
||||
* edit issue - close/reopen issue
|
||||
* edit issue - change assignee list, labels, project, milestone
|
||||
* create issue
|
||||
* enhance query hmi - labels selection per list
|
||||
|
||||
- [ ] edit issue - add comment on issues
|
||||
- [ ] edit issue - close/reopen issue
|
||||
- [ ] edit issue - change assignee list, labels, project, milestone
|
||||
- [ ] create issue
|
||||
- [ ] enhance query hmi - labels selection per list
|
||||
|
||||
### Missing features
|
||||
|
||||
@ -36,34 +42,26 @@ I want to thanks and credit:
|
||||
|
||||
### Won't be implemented
|
||||
|
||||
The goal of this connector is not to replaced the Gitea web interfac, so everything which is not Issue related or not link with what may help a developper in his day-to-day issue management will not be implemented, typically Team/Repository management and milestone management.
|
||||
The goal of this connector is not to replaced the Gitea's web interface, so everything which is not Issue related or not link with what may help a developer in his day-to-day issues management
|
||||
like Team/Repository management and milestone management will not be implemented.
|
||||
|
||||
## Usage
|
||||
|
||||
1. Install the plugin obviously (you can use the https://github.com/teilginn/mylyn-gitea update site)
|
||||
2. Add a new Connector, using the new Gitea Connector
|
||||
1. enter the project URL (something like `http(s)://my-gitea-instance.org/myname_or_organisation/myrepository`)
|
||||
2. enter your usename and your password
|
||||
3. **Do not forget to check the "Save Password" checkbox**. I don't know how to create a password prompt...
|
||||
3. You can now create queries and issues
|
||||
|
||||
If you use https instead of http (and you absolutely should use https), be sure you have a valid certificate. That means it is signed by a trusted CA. If you don't have a valid certificate (like a self signed certificate), the plugin will refuse to connect. If you want to add your CA certificate to the java keystore, you have to:
|
||||
|
||||
1. find the keystore which is used by your JVM (on my machine it is /etc/ssl/certs/java/cacerts)
|
||||
2. find out the password for the keystore (the default is "changeit")
|
||||
3. add the CA certificate to this keystore
|
||||
1. On Linux, Mac OS X, or Unix systems, use `keytool -import -alias A-UNIQUE-ALIAS -file YOUR-CA.crt -keystore $PATH_TO_YOUR_KEYSTORE` (root permissions may be necessary)
|
||||
2. On Windows, in an Administrator Command Prompt use `"%PROGRAMFILES%\java\jre7\bin\keytool" -import -alias A-UNIQUE-ALIAS -file YOUR-CA.cer -keystore "%PROGRAMFILES%\Java\jre7\lib\security\cacerts"`
|
||||
|
||||
I don't kown if I will introduce the option to ignore certificate errors. It is not a good way to do those kind of things, especially as it's now not so difficult to get a valid certificate for self hosted services thanks to Let's Encrypt.
|
||||
see (Mylyn/Gitea Tasks Connector plug-ins update site)[https://forge.chapril.org/gitea/mylyn-gitea-updatesite]
|
||||
|
||||
## Known issues/Limitations
|
||||
|
||||
* List of Eclipse versions plugins is compliant with, is to be defined. It will be test with the version of Eclipse I'm using (Linux/Windows) in front of an always up to date gitea instance.
|
||||
* Version 1.x will only support read acess and queries, we have may to wait the Version 2.x to create and modify issues.
|
||||
* If you created a new milestone or added a new project member via the web interface, you have to update the repository configuration, so that the connector reloads the project members and milestones. Right click on the Gitea repository in the Task repositories view and click on "Update Repository Configuration".
|
||||
* Offline mode does not work.
|
||||
* Out of the box support for valid certificates only.
|
||||
* Ssl connection issue with some servers
|
||||
* [Known issues](https://github.com/teilginn/mylyn-gitea/issues?q=is%3Aopen+is%3Aissue)
|
||||
* [known limitations](https://github.com/teilginn/mylyn-gitea/labels/known_limitation)
|
||||
|
||||
## Report an issue
|
||||
|
||||
To avoid any account management activity, issues tracker is handled at [Github](https://github.com/teilginn/mylyn-gitea/issues).
|
||||
|
||||
Feel free to open issues to report bugs or request new features.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
28
io.gitea.mylyn.core/.classpath
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/annotations-13.0.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/commons-lang3-3.11.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/gson-2.8.6.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/gson-fire-1.8.5.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/hamcrest-core-1.3.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/java.gitea.api-1.13.0.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/javax.annotation-api-1.3.2.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/jsr305-3.0.2.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/junit-4.13.1.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/kotlin-stdlib-1.4.10.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/kotlin-stdlib-common-1.4.0.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/kotlin-stdlib-jdk7-1.4.10.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/kotlin-stdlib-jdk8-1.4.10.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/logging-interceptor-4.9.1.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/okhttp-4.9.1.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/okio-2.8.0.jar"/>
|
||||
<classpathentry exported="true" kind="lib" path="lib/swagger-annotations-1.6.2.jar"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="org.eclipse.pde.api.tools.apiAnalysisBuilder"/>
|
||||
<mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
</launchConfiguration>
|
24
io.gitea.mylyn.core/.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
/bin/
|
38
io.gitea.mylyn.core/.project
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>io.gitea.mylyn.core</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/org.eclipse.pde.api.tools.apiAnalysisBuilder.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
15
io.gitea.mylyn.core/.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,15 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
|
||||
org.eclipse.jdt.core.compiler.release=disabled
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
|
19
io.gitea.mylyn.core/LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
MIT License Copyright (c) 2021 F.Terrot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
37
io.gitea.mylyn.core/META-INF/MANIFEST.MF
Normal file
@ -0,0 +1,37 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Mylyn Gitea Connector Core
|
||||
Bundle-SymbolicName: io.gitea.mylyn.core;singleton:=true
|
||||
Bundle-Version: 0.1.0
|
||||
Bundle-Activator: io.gitea.mylyn.core.GiteaPluginCore
|
||||
Bundle-Vendor: io.gitea
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
org.eclipse.mylyn.tasks.core;bundle-version="[3.8.0,4.0.0)",
|
||||
org.eclipse.mylyn.tasks.ui,
|
||||
org.eclipse.mylyn.commons.net;bundle-version="[3.8.0,4.0.0)"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Automatic-Module-Name: io.gitea.mylyn.core
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: io.gitea,
|
||||
io.gitea.api,
|
||||
io.gitea.model,
|
||||
io.gitea.mylyn.core,
|
||||
io.gitea.mylyn.core.exceptions
|
||||
Bundle-ClassPath: lib/annotations-13.0.jar,
|
||||
lib/commons-lang3-3.11.jar,
|
||||
lib/gson-2.8.6.jar,
|
||||
lib/gson-fire-1.8.5.jar,
|
||||
lib/hamcrest-core-1.3.jar,
|
||||
lib/java.gitea.api-1.13.0.jar,
|
||||
lib/javax.annotation-api-1.3.2.jar,
|
||||
lib/jsr305-3.0.2.jar,
|
||||
lib/junit-4.13.1.jar,
|
||||
lib/kotlin-stdlib-1.4.10.jar,
|
||||
lib/kotlin-stdlib-common-1.4.0.jar,
|
||||
lib/kotlin-stdlib-jdk7-1.4.10.jar,
|
||||
lib/kotlin-stdlib-jdk8-1.4.10.jar,
|
||||
lib/logging-interceptor-4.9.1.jar,
|
||||
lib/okhttp-4.9.1.jar,
|
||||
lib/okio-2.8.0.jar,
|
||||
lib/swagger-annotations-1.6.2.jar,
|
||||
.
|
22
io.gitea.mylyn.core/build.properties
Normal file
@ -0,0 +1,22 @@
|
||||
source.. = src/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml,\
|
||||
lib/annotations-13.0.jar,\
|
||||
lib/commons-lang3-3.11.jar,\
|
||||
lib/gson-2.8.6.jar,\
|
||||
lib/gson-fire-1.8.5.jar,\
|
||||
lib/hamcrest-core-1.3.jar,\
|
||||
lib/java.gitea.api-1.13.0.jar,\
|
||||
lib/javax.annotation-api-1.3.2.jar,\
|
||||
lib/jsr305-3.0.2.jar,\
|
||||
lib/junit-4.13.1.jar,\
|
||||
lib/kotlin-stdlib-1.4.10.jar,\
|
||||
lib/kotlin-stdlib-common-1.4.0.jar,\
|
||||
lib/kotlin-stdlib-jdk7-1.4.10.jar,\
|
||||
lib/kotlin-stdlib-jdk8-1.4.10.jar,\
|
||||
lib/logging-interceptor-4.9.1.jar,\
|
||||
lib/okhttp-4.9.1.jar,\
|
||||
lib/okio-2.8.0.jar,\
|
||||
lib/swagger-annotations-1.6.2.jar
|
||||
jre.compilation.profile = JavaSE-1.8
|
BIN
io.gitea.mylyn.core/lib/annotations-13.0.jar
Normal file
BIN
io.gitea.mylyn.core/lib/commons-lang3-3.11.jar
Normal file
BIN
io.gitea.mylyn.core/lib/gson-2.8.6.jar
Normal file
BIN
io.gitea.mylyn.core/lib/gson-fire-1.8.5.jar
Normal file
BIN
io.gitea.mylyn.core/lib/hamcrest-core-1.3.jar
Normal file
BIN
io.gitea.mylyn.core/lib/java.gitea.api-1.13.0.jar
Normal file
BIN
io.gitea.mylyn.core/lib/javax.annotation-api-1.3.2.jar
Normal file
BIN
io.gitea.mylyn.core/lib/jsr305-3.0.2.jar
Normal file
BIN
io.gitea.mylyn.core/lib/junit-4.13.1.jar
Normal file
BIN
io.gitea.mylyn.core/lib/kotlin-stdlib-1.4.10.jar
Normal file
BIN
io.gitea.mylyn.core/lib/kotlin-stdlib-common-1.4.0.jar
Normal file
BIN
io.gitea.mylyn.core/lib/kotlin-stdlib-jdk7-1.4.10.jar
Normal file
BIN
io.gitea.mylyn.core/lib/kotlin-stdlib-jdk8-1.4.10.jar
Normal file
BIN
io.gitea.mylyn.core/lib/logging-interceptor-4.9.1.jar
Normal file
BIN
io.gitea.mylyn.core/lib/okhttp-4.9.1.jar
Normal file
BIN
io.gitea.mylyn.core/lib/okio-2.8.0.jar
Normal file
BIN
io.gitea.mylyn.core/lib/swagger-annotations-1.6.2.jar
Normal file
14
io.gitea.mylyn.core/plugin.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.4"?>
|
||||
<plugin>
|
||||
<extension
|
||||
id="io.gitea.mylyn.core"
|
||||
name="%repository.name"
|
||||
point="org.eclipse.mylyn.tasks.ui.repositories">
|
||||
<connectorCore
|
||||
class="io.gitea.mylyn.core.GiteaConnector"
|
||||
id="io.gitea.mylyn.core"
|
||||
name="Gitea Connector"/>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
52
io.gitea.mylyn.core/src/io/gitea/api/ApiVersion.java
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.api;
|
||||
|
||||
import io.gitea.ApiClient;
|
||||
|
||||
/** Version of the Gitea API to communicate with. */
|
||||
public enum ApiVersion {
|
||||
V1;
|
||||
|
||||
/** API namespace to be used in URL. */
|
||||
public String getApiNamespace() {
|
||||
return "/api/" + name().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the client Api base path (URL) adapted to the selected Api version.
|
||||
*
|
||||
* @param hostUrl Uri of the server hosting the Gitea service (with protocol,
|
||||
* without trailing /).
|
||||
*
|
||||
* @return Url to be use to communication with Gitea
|
||||
*
|
||||
* @implNote No check is done on the validity of hostUrl
|
||||
*/
|
||||
public String getBasePath(String hostUrl) {
|
||||
return hostUrl + getApiNamespace();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the client Api base path adapted to the selected Api version.
|
||||
*
|
||||
* @param apiClient Gitea Api client object to configure.
|
||||
* @param hostUrl Uri of the server hosting the Gitea service (with protocol,
|
||||
* without trailing /).
|
||||
*
|
||||
* @implNote No check is done on the validity of hostUrl
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* ApiClient defaultConfiguration = Configuration.getDefaultApiClient();
|
||||
* String host = "https://forge.chapril.org" ;
|
||||
* ApiVersion.V1.setBasePath(defaultConfiguration, host);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public void setBasePath(ApiClient apiClient, String hostUrl) {
|
||||
apiClient.setBasePath(hostUrl + getApiNamespace());
|
||||
}
|
||||
}
|
6
io.gitea.mylyn.core/src/io/gitea/api/package-info.java
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/** <i>local</i> extension of the generated Java Gitea API "io.gitea.api" package. */
|
||||
package io.gitea.api;
|
@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.model;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
/** Handles Gitea to Mylyn date conversions */
|
||||
public class GiteaDateTimeUtils {
|
||||
private static final String dateFormat_from_LocalDateTime = "yyyy-MM-dd'T'HH:mm:ss"; //$NON-NLS-1$
|
||||
private static final String dateFormat_from_Offset = "yyyy-MM-dd'T'HH:mm:ssX"; //$NON-NLS-1$
|
||||
private static final String dateFormat_1 = "yyyy-MM-dd HH:mm:ss"; //$NON-NLS-1$
|
||||
|
||||
private static final String dateFormat_2 = "yyyy-MM-dd HH:mm"; //$NON-NLS-1$
|
||||
|
||||
private static final String dateFormat_3 = "yyyy-MM-dd"; //$NON-NLS-1$
|
||||
|
||||
private static final String dateFormat_1_TimeZone = "yyyy-MM-dd HH:mm:ss Z"; //$NON-NLS-1$
|
||||
|
||||
private static final String dateFormat_2_TimeZone = "yyyy-MM-dd HH:mm z"; //$NON-NLS-1$
|
||||
|
||||
private static final String dateFormat_3_TimeZone = "yyyy-MM-dd z"; //$NON-NLS-1$
|
||||
// Order is significant
|
||||
private static final String[] dateFormats = { dateFormat_from_Offset, dateFormat_from_LocalDateTime,
|
||||
dateFormat_1_TimeZone, dateFormat_1, dateFormat_2_TimeZone, dateFormat_2, dateFormat_3_TimeZone,
|
||||
dateFormat_3 };
|
||||
|
||||
/**
|
||||
* Note: Date formatter constructed within method for thread safety
|
||||
*/
|
||||
public static final Date parseDate(String dateString) {
|
||||
for (String format : dateFormats) {
|
||||
try {
|
||||
SimpleDateFormat simpleFormatter = new SimpleDateFormat(format);
|
||||
return simpleFormatter.parse(dateString);
|
||||
} catch (ParseException e) {
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Convert OffsetDateTime to Date */
|
||||
public static final Date toDate(OffsetDateTime offset) {
|
||||
return parseDate(offset.toString()); // FIXME: use better Offset to date convertion
|
||||
}
|
||||
}
|
108
io.gitea.mylyn.core/src/io/gitea/model/GiteaPriorityLevel.java
Normal file
@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.mylyn.tasks.core.ITask.PriorityLevel;
|
||||
|
||||
/**
|
||||
* Extract Mylyn PriorityLevel from Issue label
|
||||
*
|
||||
*/
|
||||
public enum GiteaPriorityLevel {
|
||||
HIGHEST(PriorityLevel.P1), HIGH(PriorityLevel.P2), MIDDLE(PriorityLevel.P3), LOW(PriorityLevel.P4),
|
||||
LOWEST(PriorityLevel.P5);
|
||||
|
||||
private PriorityLevel level;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private GiteaPriorityLevel(PriorityLevel p) {
|
||||
this.level = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GiteaPriority level.
|
||||
*
|
||||
* @return PriorityLevel
|
||||
*/
|
||||
public PriorityLevel getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* GiteaPriority level as String
|
||||
*
|
||||
* {@code giteaPriority.ToString() <=> giteaPriority.GetLevel().toString()}
|
||||
*
|
||||
* To Get GiteaPriority as String use standard Enum name() API.
|
||||
*
|
||||
* @{code HIGHEST.toString() -> "P1" HIGHEST.name() -> "HIGHEST"}
|
||||
*/
|
||||
public String toString() {
|
||||
return level.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GiteaPriority from PriorityLevel
|
||||
*
|
||||
* @param level
|
||||
* @return
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
public static GiteaPriorityLevel getPriority(PriorityLevel level) throws IllegalArgumentException {
|
||||
return Arrays.stream(values()).filter(v -> v.level.equals(level)).findFirst()
|
||||
.orElseThrow(() -> new IllegalArgumentException("unknown priority level:" + level.toString()));
|
||||
}
|
||||
|
||||
// P1 .. P5
|
||||
private static Pattern valuePattern = Pattern.compile("(?::?priority:)?(p[1-5])", Pattern.CASE_INSENSITIVE);
|
||||
// Xtra very_normal is supported, surprising but not a big issue, kept it regexp
|
||||
// 'simple'
|
||||
private static Pattern alternativePattern = Pattern.compile("(?::?priority:)?(?:very_?)?(high|low|normal)",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern priorityPattern = Pattern.compile("(?::?priority:)?(highest|high|middle|low|lowest)",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* Return the Priority from labels value.
|
||||
*
|
||||
* @param labels as string
|
||||
*
|
||||
* @return found priority or MIDDLE if no priority found.
|
||||
*/
|
||||
public static GiteaPriorityLevel getPriority(String labels) {
|
||||
|
||||
Matcher m = priorityPattern.matcher(labels);
|
||||
if (m.find()) {
|
||||
return GiteaPriorityLevel.valueOf(m.group(1).toUpperCase());
|
||||
}
|
||||
m = valuePattern.matcher(labels);
|
||||
if (m.find()) {
|
||||
return GiteaPriorityLevel.getPriority(PriorityLevel.valueOf(m.group(1).toUpperCase()));
|
||||
}
|
||||
|
||||
m = alternativePattern.matcher(labels);
|
||||
if (m.find()) {
|
||||
switch (m.group(1).toLowerCase()) {
|
||||
case "high":
|
||||
return GiteaPriorityLevel.HIGHEST;
|
||||
case "normal":
|
||||
return GiteaPriorityLevel.MIDDLE;
|
||||
case "low":
|
||||
return GiteaPriorityLevel.LOWEST;
|
||||
default:
|
||||
}
|
||||
}
|
||||
return GiteaPriorityLevel.MIDDLE;
|
||||
}
|
||||
|
||||
}
|
18
io.gitea.mylyn.core/src/io/gitea/model/GiteaUser.java
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.model;
|
||||
|
||||
public class GiteaUser {
|
||||
/** Name is user FullName or Login when FullName is empty. */
|
||||
static public String getName(User user) {
|
||||
String name = "";
|
||||
if (user != null) {
|
||||
name = user.getFullName();
|
||||
if (name.isBlank() || name.isEmpty())
|
||||
name = user.getLogin();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
18
io.gitea.mylyn.core/src/io/gitea/model/IssueAction.java
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.model;
|
||||
|
||||
public enum IssueAction {
|
||||
CLOSE("close"),
|
||||
LEAVE("leave"),
|
||||
REOPEN("open");
|
||||
|
||||
IssueAction(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
public final String label;
|
||||
|
||||
|
||||
}
|
66
io.gitea.mylyn.core/src/io/gitea/model/IssueState.java
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.model;
|
||||
|
||||
import io.gitea.model.Issue;
|
||||
|
||||
/** Gitea Issue State
|
||||
*
|
||||
* Note: Constructor is private to limit IssueState to predefined ones.
|
||||
*/
|
||||
public enum IssueState {
|
||||
STATE_ANY("all"),STATE_OPENED("open"),STATE_CLOSED("closed");
|
||||
|
||||
private String value;
|
||||
private IssueState(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public boolean equals(IssueState arg0) {
|
||||
return this.value.equals(arg0.toString());
|
||||
}
|
||||
public boolean equals(String arg0) {
|
||||
return this.value.equals(arg0);
|
||||
}
|
||||
|
||||
/**Check if an issue is "open"
|
||||
*
|
||||
* @param issue Gitea Issue
|
||||
* @return True if the state is "open".
|
||||
*
|
||||
* @apiNote isOpen() is not the opposite of isClose()
|
||||
* "isOpen() == false" doesn't means that "isClose() == true"
|
||||
*
|
||||
*/
|
||||
public static boolean isOpen(Issue issue) {
|
||||
return IssueState.isOpen(issue.getState());
|
||||
}
|
||||
/**Check if a status value is "open".
|
||||
*
|
||||
* @param status Status value as String
|
||||
*/
|
||||
public static boolean isOpen(String value) {
|
||||
return STATE_OPENED.equals(value);
|
||||
}
|
||||
/**Check if the issue is "closed".
|
||||
*
|
||||
* @param issue GItea Issue
|
||||
* @return True if the issue state is "closed"
|
||||
*/
|
||||
public static boolean isClosed(Issue issue) {
|
||||
return IssueState.isClosed(issue.getState());
|
||||
}
|
||||
/**Check if a status value is "closed".
|
||||
*
|
||||
* @param status Status value as String
|
||||
*/
|
||||
public static boolean isClosed(String value) {
|
||||
return STATE_CLOSED.equals(value);
|
||||
}
|
||||
}
|
46
io.gitea.mylyn.core/src/io/gitea/model/IssueType.java
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.model;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
public enum IssueType {
|
||||
EPIC("epic"), STORY("story"), FEATURE("feature"), BUG("bug"), TASK("task"), ENHANCEMENT("enhancement"),
|
||||
QUESTION("question"), IMPEDIMENT("impediment");
|
||||
|
||||
static public final Pattern PATTERN = Pattern.compile("(" + StringUtils.join(IssueType.values(), "|") + ")");
|
||||
|
||||
private String value;
|
||||
|
||||
private IssueType(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean equals(IssueType arg0) {
|
||||
return this.value.contentEquals(arg0.getValue());
|
||||
}
|
||||
|
||||
public boolean equals(String arg0) {
|
||||
return this.value.equals(arg0);
|
||||
}
|
||||
|
||||
public static boolean contains(String value) {
|
||||
for (IssueType t : IssueType.values()) {
|
||||
if (t.equals(value))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
6
io.gitea.mylyn.core/src/io/gitea/model/package-info.java
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/** <i>local</i> extension of the generated Java Gitea API "io.gitea.model" package. */
|
||||
package io.gitea.model;
|
@ -0,0 +1,200 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.mylyn.commons.net.AuthenticationType;
|
||||
import org.eclipse.mylyn.tasks.core.TaskRepository;
|
||||
|
||||
import io.gitea.*;
|
||||
import io.gitea.auth.*;
|
||||
import io.gitea.model.*;
|
||||
import io.gitea.api.UserApi;
|
||||
import io.gitea.mylyn.core.exceptions.GiteaException;
|
||||
import io.gitea.mylyn.core.exceptions.GiteaExceptionHandler;
|
||||
import io.gitea.mylyn.core.exceptions.UnknownRepositoryException;
|
||||
|
||||
/**
|
||||
* The ConnectionManager is a singleton that handles all GiteaConnection
|
||||
* instances in a HashMap. The key in this HashMap is the URL to the Gitea
|
||||
* instance constructed using a TaskRepository class.
|
||||
*/
|
||||
public class ConnectionManager {
|
||||
|
||||
/**
|
||||
* The HashMap used to store all GiteaConnections
|
||||
*/
|
||||
private static HashMap<String, GiteaConnection> connections = new HashMap<String, GiteaConnection>();
|
||||
|
||||
/**
|
||||
* The pattern is used to verify a ULR to a valid Gitea repository URL. group 1
|
||||
* -> server including protocol (without trailing '/') group 2 ->
|
||||
* repository/project path excluding potential ".git"
|
||||
*
|
||||
* trick: for server we are locking for any character which is not / which is
|
||||
* same as looking not greedy to all character until /
|
||||
*
|
||||
* example: https://forge.chapril.org/gitea/mylyn-gitea.git group 1 =>
|
||||
* https//forge.chapril.org group 2 => gitea/mylyn-gitea
|
||||
*/
|
||||
private static Pattern URLPattern = Pattern.compile("(https?://(?:[^\\/]*))/((?:.*?)/(?:[^\\/]*?))(?:\\.git)?$");
|
||||
|
||||
/**
|
||||
* Returns the GiteaConnection for the given task repository
|
||||
*
|
||||
* @param repository
|
||||
* @return
|
||||
* @throws GiteaException
|
||||
*/
|
||||
static public GiteaConnection get(TaskRepository repository) throws GiteaException {
|
||||
return get(repository, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GiteaConnection for the given task repository. If it fails for
|
||||
* whatever reason, it returns null.
|
||||
*
|
||||
* @param repository
|
||||
* @return
|
||||
*/
|
||||
static public GiteaConnection getSafe(TaskRepository repository) {
|
||||
try {
|
||||
return get(repository);
|
||||
} catch (GiteaException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gitea connection configuration.
|
||||
*/
|
||||
static public ApiClient getConfiguration() {
|
||||
return Configuration.getDefaultApiClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a "pseudo" URL string for the given task repository.
|
||||
*
|
||||
* @param repository
|
||||
* @return
|
||||
*/
|
||||
private static String constructHash(TaskRepository repository) {
|
||||
String username = repository.getCredentials(AuthenticationType.REPOSITORY).getUserName();
|
||||
String password = repository.getCredentials(AuthenticationType.REPOSITORY).getPassword();
|
||||
return repository.getUrl() + "?username=" + username + "&password=" + password.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given task repository and returns a GiteaConnection if the task
|
||||
* repository is a valid repository.
|
||||
*
|
||||
* @param repository
|
||||
* @return
|
||||
* @throws GiteaException
|
||||
*/
|
||||
// FIXME: redesign to limit this function to validation but not configuration
|
||||
static GiteaConnection validate(TaskRepository repository) throws GiteaException {
|
||||
try {
|
||||
String projectPath = null;
|
||||
String host = null;
|
||||
|
||||
// Extract host&project path from valid url
|
||||
if (repository.getProperty("giteaBaseUrl").trim().length() > 0) {
|
||||
host = repository.getProperty("giteaBaseUrl").trim();
|
||||
if (!repository.getUrl().startsWith(host)) {
|
||||
throw new GiteaException("Invalid repository URL!");
|
||||
}
|
||||
|
||||
projectPath = repository.getUrl().replaceFirst(Matcher.quoteReplacement(host), "");
|
||||
if (projectPath.startsWith("/")) {
|
||||
projectPath = projectPath.substring(1);
|
||||
}
|
||||
} else {
|
||||
Matcher matcher = URLPattern.matcher(repository.getUrl());
|
||||
if (!matcher.find()) {
|
||||
throw new GiteaException("Invalid Project-URL!");
|
||||
}
|
||||
|
||||
projectPath = matcher.group(2);
|
||||
host = matcher.group(1);
|
||||
}
|
||||
|
||||
// Configure credentials
|
||||
String username = repository.getCredentials(AuthenticationType.REPOSITORY).getUserName();
|
||||
String password = repository.getCredentials(AuthenticationType.REPOSITORY).getPassword();
|
||||
|
||||
ApiClient defaultClient = Configuration.getDefaultApiClient();
|
||||
defaultClient.setBasePath(GiteaConnection.apiVersion.getBasePath(host));
|
||||
|
||||
if (repository.getProperty("usePrivateToken") != null
|
||||
&& repository.getProperty("usePrivateToken").equals("true")) {
|
||||
ApiKeyAuth accessToken = (ApiKeyAuth) defaultClient.getAuthentication("AccessToken");
|
||||
accessToken.setApiKey(password); // token is stored in the password field.
|
||||
|
||||
} else {
|
||||
HttpBasicAuth basicAuth = (HttpBasicAuth) defaultClient.getAuthentication("BasicAuth");
|
||||
basicAuth.setUsername(username);
|
||||
basicAuth.setPassword(password);
|
||||
}
|
||||
|
||||
// Get user related repository list
|
||||
UserApi userApi = new UserApi();
|
||||
List<Repository> repositories = userApi.userCurrentListRepos(0, 0);
|
||||
for (Repository p : repositories) {
|
||||
if (p.getFullName().equals(projectPath)) {
|
||||
GiteaConnection connection = new GiteaConnection(host, p, new GiteaAttributeMapper(repository));
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
// At this point the authentication was successful, but the corresponding
|
||||
// repository
|
||||
// could not be found! which not not occurs with Gitea.
|
||||
throw new UnknownRepositoryException(projectPath);
|
||||
} catch (GiteaException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw GiteaExceptionHandler.handle(e);
|
||||
} catch (Error e) {
|
||||
throw GiteaExceptionHandler.handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a *valid* GiteaConnection, otherwise this method throws an exception.
|
||||
*
|
||||
* @param repository
|
||||
* @param forceUpdate if true, a new GiteaConnection instance will be created,
|
||||
* even if a Gitea Connection already exists for the given
|
||||
* task repository
|
||||
* @return connection
|
||||
* @throws GiteaException
|
||||
*/
|
||||
static GiteaConnection get(TaskRepository repository, boolean forceUpdate) throws GiteaException {
|
||||
try {
|
||||
String hash = constructHash(repository);
|
||||
if (connections.containsKey(hash) && !forceUpdate) {
|
||||
return connections.get(hash);
|
||||
} else {
|
||||
GiteaConnection connection = validate(repository);
|
||||
|
||||
connections.put(hash, connection);
|
||||
connection.update();
|
||||
|
||||
return connection;
|
||||
}
|
||||
} catch (GiteaException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw GiteaExceptionHandler.handle(e);
|
||||
} catch (Error e) {
|
||||
throw GiteaExceptionHandler.handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
65
io.gitea.mylyn.core/src/io/gitea/mylyn/core/GiteaAction.java
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import io.gitea.model.IssueState;
|
||||
import io.gitea.model.Issue;
|
||||
|
||||
/**
|
||||
* Represents an action that tell Gitea what to do with the issue, e.g. "close"
|
||||
* will close the issue in Gitea. This wrapper is necessary.
|
||||
*
|
||||
*/
|
||||
public enum GiteaAction {
|
||||
|
||||
LEAVE("leave"), CLOSE("close"), REOPEN("reopen");
|
||||
|
||||
/**
|
||||
* The valid actions for an open issue
|
||||
*/
|
||||
private final static GiteaAction[] opened = { LEAVE, CLOSE };
|
||||
|
||||
/**
|
||||
* The valid actions for a closed issue
|
||||
*/
|
||||
private final static GiteaAction[] closed = { LEAVE, REOPEN };
|
||||
|
||||
private GiteaAction(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public final String label;
|
||||
|
||||
/**
|
||||
* Returns all valid actions for the given issue.
|
||||
*
|
||||
* @param issue
|
||||
* @return
|
||||
*/
|
||||
public static GiteaAction[] getActions(Issue issue) {
|
||||
if (IssueState.isClosed(issue)) {
|
||||
return closed;
|
||||
} else {
|
||||
return opened;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GiteaAction enum for the given action string.
|
||||
*
|
||||
* @param action
|
||||
* @return
|
||||
*/
|
||||
public static GiteaAction find(String action) {
|
||||
for (GiteaAction a : values()) {
|
||||
if (a.label.equals(action)) {
|
||||
return a;
|
||||
}
|
||||
}
|
||||
return LEAVE;
|
||||
}
|
||||
|
||||
|
||||
}
|
114
io.gitea.mylyn.core/src/io/gitea/mylyn/core/GiteaAttribute.java
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
|
||||
|
||||
public enum GiteaAttribute {
|
||||
|
||||
BODY("Description", TaskAttribute.DESCRIPTION, TaskAttribute.TYPE_LONG_RICH_TEXT),
|
||||
|
||||
TITLE("Summary", TaskAttribute.SUMMARY, TaskAttribute.TYPE_SHORT_RICH_TEXT),
|
||||
|
||||
STATUS("Status", TaskAttribute.STATUS, TaskAttribute.TYPE_SHORT_TEXT, GiteaFlag.ATTRIBUTE, GiteaFlag.READ_ONLY),
|
||||
|
||||
LABELS("Labels", "io.gitea.mylyn.issue.labels", TaskAttribute.TYPE_LONG_TEXT, GiteaFlag.ATTRIBUTE),
|
||||
|
||||
UPDATED("Updated", TaskAttribute.DATE_MODIFICATION, TaskAttribute.TYPE_DATETIME, GiteaFlag.READ_ONLY,
|
||||
GiteaFlag.ATTRIBUTE),
|
||||
|
||||
CREATED("Created", TaskAttribute.DATE_CREATION, TaskAttribute.TYPE_DATETIME, GiteaFlag.READ_ONLY,
|
||||
GiteaFlag.ATTRIBUTE),
|
||||
|
||||
COMPLETED("Completed", TaskAttribute.DATE_COMPLETION, TaskAttribute.TYPE_DATETIME, GiteaFlag.READ_ONLY),
|
||||
|
||||
AUTHOR("Author", TaskAttribute.USER_REPORTER, TaskAttribute.TYPE_PERSON, GiteaFlag.READ_ONLY, GiteaFlag.ATTRIBUTE),
|
||||
|
||||
PROJECT("Project", TaskAttribute.PRODUCT, TaskAttribute.TYPE_SHORT_TEXT, GiteaFlag.READ_ONLY, GiteaFlag.ATTRIBUTE),
|
||||
|
||||
ASSIGNEE("Assignee", TaskAttribute.USER_ASSIGNED, TaskAttribute.TYPE_PERSON, GiteaFlag.ATTRIBUTE),
|
||||
|
||||
MILESTONE("Milestone", "io.gitea.mylyn.issue.milestone", TaskAttribute.TYPE_SINGLE_SELECT, GiteaFlag.ATTRIBUTE),
|
||||
|
||||
IID("IID", TaskAttribute.TASK_KEY, TaskAttribute.TYPE_INTEGER, GiteaFlag.READ_ONLY),
|
||||
|
||||
PRIORITY("Priority", TaskAttribute.PRIORITY, TaskAttribute.TYPE_SHORT_TEXT, GiteaFlag.READ_ONLY),
|
||||
|
||||
TYPE("Type", TaskAttribute.TASK_KIND, TaskAttribute.TYPE_SHORT_TEXT, GiteaFlag.READ_ONLY);
|
||||
|
||||
private Set<GiteaFlag> flags;
|
||||
|
||||
private final String prettyName;
|
||||
|
||||
private final String taskKey;
|
||||
|
||||
private final String type;
|
||||
|
||||
public String getKind() {
|
||||
if (type.equals(TaskAttribute.TYPE_PERSON)) {
|
||||
return TaskAttribute.KIND_PEOPLE;
|
||||
} else if (flags.contains(GiteaFlag.ATTRIBUTE)) {
|
||||
return TaskAttribute.KIND_DEFAULT;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return flags.contains(GiteaFlag.READ_ONLY);
|
||||
}
|
||||
|
||||
GiteaAttribute(String prettyName, String taskKey, String type, GiteaFlag... flags) {
|
||||
this.taskKey = taskKey;
|
||||
this.prettyName = prettyName;
|
||||
this.type = type;
|
||||
if (flags == null || flags.length == 0) {
|
||||
this.setFlags(EnumSet.noneOf(GiteaFlag.class));
|
||||
} else {
|
||||
this.setFlags(EnumSet.copyOf(Arrays.asList(flags)));
|
||||
}
|
||||
}
|
||||
|
||||
GiteaAttribute(String prettyName, String taskKey, String type) {
|
||||
this(prettyName, taskKey, type, new GiteaFlag[] {});
|
||||
}
|
||||
|
||||
public Set<GiteaFlag> getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public void setFlags(Set<GiteaFlag> flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public String getPrettyName() {
|
||||
return prettyName;
|
||||
}
|
||||
|
||||
public String getTaskKey() {
|
||||
return taskKey;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.prettyName;
|
||||
}
|
||||
|
||||
public static GiteaAttribute get(String key) {
|
||||
for (GiteaAttribute attr : GiteaAttribute.values()) {
|
||||
if (attr.getTaskKey().equals(key)) {
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.mylyn.tasks.core.TaskRepository;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
|
||||
|
||||
import io.gitea.model.GiteaDateTimeUtils;
|
||||
import io.gitea.model.Milestone;
|
||||
import io.gitea.model.User;
|
||||
|
||||
public class GiteaAttributeMapper extends TaskAttributeMapper {
|
||||
|
||||
public GiteaAttributeMapper(TaskRepository taskRepository) throws CoreException, IOException {
|
||||
super(taskRepository);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getOptions(TaskAttribute attribute) {
|
||||
if (attribute.getId().equals(GiteaAttribute.MILESTONE.getTaskKey())) {
|
||||
return getAsMap(getMilestones());
|
||||
} else {
|
||||
return super.getOptions(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
private GiteaConnection getConnection() throws CoreException {
|
||||
return ConnectionManager.get(getTaskRepository());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date getDateValue(TaskAttribute attribute) {
|
||||
if (attribute == null) {
|
||||
return null;
|
||||
}
|
||||
Date parsedDate = GiteaDateTimeUtils.parseDate(attribute.getValue());
|
||||
if (parsedDate != null) {
|
||||
return parsedDate;
|
||||
}
|
||||
return super.getDateValue(attribute);
|
||||
}
|
||||
|
||||
public User findProjectMemberByName(String name) {
|
||||
try {
|
||||
List<User> members = getConnection().getRepositoryCollaborators();
|
||||
for (User member : members) {
|
||||
if (member.getFullName().equals(name) || member.getLogin().equals(name)) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Milestone findMilestoneByName(String name) {
|
||||
try {
|
||||
List<Milestone> milestones = getConnection().getMilestones();
|
||||
for (Milestone m : milestones) {
|
||||
if (m.getTitle().equals(name)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<String> getMilestones() {
|
||||
List<String> target = new ArrayList<String>();
|
||||
try {
|
||||
List<Milestone> milestones = getConnection().getMilestones();
|
||||
for (Milestone m : milestones) {
|
||||
target.add(m.getTitle());
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private HashMap<String, String> getAsMap(List<String> list) {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
map.put("", "");
|
||||
for (String s : list) {
|
||||
map.put(s, s);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
166
io.gitea.mylyn.core/src/io/gitea/mylyn/core/GiteaConnection.java
Normal file
@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.gitea.ApiException;
|
||||
import io.gitea.api.ApiVersion;
|
||||
import io.gitea.api.IssueApi;
|
||||
import io.gitea.api.RepositoryApi;
|
||||
import io.gitea.api.UserApi;
|
||||
import io.gitea.model.Comment;
|
||||
import io.gitea.model.Issue;
|
||||
import io.gitea.model.IssueState;
|
||||
import io.gitea.model.Milestone;
|
||||
import io.gitea.model.Repository;
|
||||
import io.gitea.model.User;
|
||||
|
||||
/**
|
||||
* Handle Gitea connection and provides helpers to API.
|
||||
*
|
||||
*/
|
||||
public class GiteaConnection {
|
||||
public final String owner;
|
||||
public final String repo;
|
||||
public final String host;
|
||||
public final Repository repository;
|
||||
public final GiteaAttributeMapper mapper;
|
||||
|
||||
private List<Milestone> milestones;
|
||||
private List<User> members;
|
||||
|
||||
/** Targetted Gitea Api Version */
|
||||
public static final ApiVersion apiVersion = ApiVersion.V1;
|
||||
|
||||
public GiteaConnection(String host, Repository project, GiteaAttributeMapper mapper) {
|
||||
this.host = host;
|
||||
this.repository = project;
|
||||
this.mapper = mapper;
|
||||
this.owner = project.getOwner().getLogin();
|
||||
this.repo = project.getName();
|
||||
}
|
||||
|
||||
public UserApi userApi() {
|
||||
return new UserApi();
|
||||
}
|
||||
|
||||
public IssueApi issueApi() {
|
||||
return new IssueApi();
|
||||
}
|
||||
|
||||
public RepositoryApi repositoryApi() {
|
||||
return new RepositoryApi();
|
||||
}
|
||||
|
||||
public void update() throws IOException {
|
||||
ArrayList<User> memberList = new ArrayList<User>();
|
||||
|
||||
try {
|
||||
milestones = issueGetAllMilestones();
|
||||
} catch (ApiException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
try {
|
||||
memberList.addAll(repoListAllCollaborators());
|
||||
} catch (ApiException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
members = Collections.unmodifiableList(memberList);
|
||||
}
|
||||
|
||||
public List<Repository> userCurrentListRepos() throws ApiException {
|
||||
return userApi().userCurrentListRepos(null, null);
|
||||
}
|
||||
|
||||
public List<Milestone> getMilestones() {
|
||||
return Collections.unmodifiableList(milestones);
|
||||
}
|
||||
|
||||
public List<User> getRepositoryCollaborators() {
|
||||
return Collections.unmodifiableList(members);
|
||||
}
|
||||
|
||||
public List<User> repoListAllCollaborators() throws ApiException {
|
||||
return repositoryApi().repoListCollaborators(owner, repo, null, null);
|
||||
}
|
||||
|
||||
public List<Milestone> issueGetMilestones(IssueState state, String filterByName) throws ApiException {
|
||||
return issueApi().issueGetMilestonesList(owner, repo, state.toString(), filterByName, null, null);
|
||||
}
|
||||
|
||||
public List<Milestone> issueGetAllMilestones() throws ApiException {
|
||||
return issueGetMilestones(IssueState.STATE_ANY, null);
|
||||
}
|
||||
|
||||
public List<Milestone> issueGetOpenMilestones() throws ApiException {
|
||||
return issueGetMilestones(IssueState.STATE_OPENED, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get issues list by state.
|
||||
*
|
||||
* @param state
|
||||
* @return
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<Issue> repoGetIssues(IssueState state, String labels, Integer page, String query, String milestones) throws ApiException {
|
||||
return issueApi().issueListIssues(owner, repo, state.toString(), labels, "", query, milestones, page, 0);
|
||||
}
|
||||
|
||||
public List<Issue> repoGetIssues(String state, String labels, Integer page, String query, String milestones) throws ApiException {
|
||||
return issueApi().issueListIssues(owner, repo, state, labels, query, "", milestones, page, 0);
|
||||
}
|
||||
|
||||
public List<Issue> repoGetAllIssues() throws ApiException {
|
||||
return repoGetIssues(IssueState.STATE_ANY, "", 0, "", "");
|
||||
}
|
||||
|
||||
public List<Issue> repoGetOpenIssues() throws ApiException {
|
||||
return repoGetIssues(IssueState.STATE_OPENED, "", 0, "", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific Issue.
|
||||
*
|
||||
* @param issueId : issue id
|
||||
* @return Issue
|
||||
* @throws ApiException
|
||||
*/
|
||||
public Issue issueGetIssue(Long issueId) throws ApiException {
|
||||
return issueApi().issueGetIssue(owner, repo, issueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all comments attached to an issue.
|
||||
*
|
||||
* @param issue Issue to retrieve comments from.
|
||||
* @param since
|
||||
* @return List<Comment>
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<Comment> issueGetComments(Issue issue, String since, String before) throws ApiException {
|
||||
return issueApi().issueGetComments(owner, repo, issue.getNumber(), null, null); // FIXME: support since and before
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all comments attached to an issue identified by its id.
|
||||
*
|
||||
* @param issueId
|
||||
* @param since
|
||||
* @return
|
||||
* @throws ApiException
|
||||
*/
|
||||
public List<Comment> issueGetComments(Long issueId, String since) throws ApiException {
|
||||
return issueGetComments(issueGetIssue(issueId), since, null); // FIXME: support since and before
|
||||
}
|
||||
|
||||
public List<Comment> issueGetComments(Issue issue) throws ApiException {
|
||||
return issueGetComments(issue, null, null);
|
||||
}
|
||||
}
|
160
io.gitea.mylyn.core/src/io/gitea/mylyn/core/GiteaConnector.java
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector;
|
||||
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
|
||||
import org.eclipse.mylyn.tasks.core.ITask;
|
||||
import org.eclipse.mylyn.tasks.core.TaskRepository;
|
||||
import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskData;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskDataCollector;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskMapper;
|
||||
import org.eclipse.mylyn.tasks.core.sync.ISynchronizationSession;
|
||||
import io.gitea.*;
|
||||
import io.gitea.model.Issue;
|
||||
import io.gitea.mylyn.core.exceptions.GiteaException;
|
||||
|
||||
/**
|
||||
* Establishes a connection to the Gitea Instance and handles all requests like
|
||||
* search requests etc.
|
||||
*/
|
||||
public class GiteaConnector extends AbstractRepositoryConnector {
|
||||
|
||||
private GiteaTaskDataHandler handler = new GiteaTaskDataHandler();
|
||||
|
||||
@Override
|
||||
public boolean canCreateNewTask(TaskRepository repository) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCreateTaskFromKey(TaskRepository repository) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnectorKind() {
|
||||
return GiteaPluginCore.CONNECTOR_KIND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return "Gitea issues";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRepositoryUrlFromTaskUrl(String arg0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskData getTaskData(TaskRepository repository, String id, IProgressMonitor monitor) throws CoreException {
|
||||
|
||||
try {
|
||||
monitor.beginTask("Task Download", IProgressMonitor.UNKNOWN);
|
||||
return handler.downloadTaskData(repository, GiteaConnector.getTicketId(id));
|
||||
} finally {
|
||||
monitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTaskIdFromTaskUrl(String url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTaskUrl(String arg0, String arg1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTaskChanged(TaskRepository repository, ITask task, TaskData data) {
|
||||
TaskMapper mapper = new GiteaTaskMapper(data);
|
||||
if (data.isPartial()) {
|
||||
return mapper.hasChanges(task);
|
||||
} else {
|
||||
Date repositoryDate = mapper.getModificationDate();
|
||||
Date localDate = task.getModificationDate();
|
||||
if (repositoryDate != null && repositoryDate.equals(localDate)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IStatus performQuery(TaskRepository repository, IRepositoryQuery query, TaskDataCollector collector,
|
||||
ISynchronizationSession session, IProgressMonitor monitor) {
|
||||
|
||||
try {
|
||||
monitor.beginTask("Tasks querying", IProgressMonitor.UNKNOWN);
|
||||
GiteaConnection connection = ConnectionManager.get(repository);
|
||||
GiteaIssueSearch search = new GiteaIssueSearch(query);
|
||||
List<Issue> issues = connection.repoGetAllIssues();
|
||||
|
||||
for (Issue i : issues) {
|
||||
if (search.doesMatch(i)) {
|
||||
collector.accept(
|
||||
handler.createTaskDataFromGiteaIssue(i, repository, connection.issueGetComments(i)));
|
||||
}
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
} catch (ApiException e) {
|
||||
return new Status(Status.ERROR, GiteaPluginCore.ID_PLUGIN, "Unable to execute Query: " + e.getMessage());
|
||||
} catch (CoreException e) {
|
||||
return new Status(Status.ERROR, GiteaPluginCore.ID_PLUGIN, "Unable to execute Query: " + e.getMessage());
|
||||
} finally {
|
||||
monitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRepositoryConfiguration(TaskRepository repository, IProgressMonitor monitor)
|
||||
throws CoreException {
|
||||
try {
|
||||
monitor.beginTask("Updating repository configuration", IProgressMonitor.UNKNOWN);
|
||||
ConnectionManager.get(repository, true);
|
||||
} finally {
|
||||
monitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTaskFromTaskData(TaskRepository repository, ITask task, TaskData data) {
|
||||
GiteaTaskMapper mapper = new GiteaTaskMapper(data);
|
||||
mapper.applyTo(task);
|
||||
}
|
||||
|
||||
public static void validate(TaskRepository taskRepo) throws CoreException {
|
||||
try {
|
||||
ConnectionManager.validate(taskRepo);
|
||||
} catch (GiteaException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new GiteaException("Connection not successful or repository not found: " + e.getMessage());
|
||||
} catch (Error e) {
|
||||
throw new GiteaException("Connection not successful or repository not found: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractTaskDataHandler getTaskDataHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public static Long getTicketId(String id) {
|
||||
return (long) Integer.parseInt(id);
|
||||
}
|
||||
|
||||
}
|
26
io.gitea.mylyn.core/src/io/gitea/mylyn/core/GiteaFlag.java
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
/**
|
||||
* A flag for Gitea attributes.
|
||||
*
|
||||
*/
|
||||
public enum GiteaFlag {
|
||||
/**
|
||||
* Sets the attribute to ReadOnly.
|
||||
*/
|
||||
READ_ONLY,
|
||||
|
||||
/**
|
||||
* Default Attribute
|
||||
*/
|
||||
ATTRIBUTE,
|
||||
|
||||
/**
|
||||
* A flag to indicate, that an attribute describes a person.
|
||||
*/
|
||||
PEOPLE;
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
|
||||
|
||||
import io.gitea.model.IssueState;
|
||||
import io.gitea.model.Issue;
|
||||
import io.gitea.model.Label;
|
||||
|
||||
public class GiteaIssueSearch {
|
||||
|
||||
private String assignee;
|
||||
private String milestone;
|
||||
|
||||
private Boolean opened;
|
||||
private Boolean closed;
|
||||
|
||||
private List<Pattern> labels = new ArrayList<Pattern>();
|
||||
|
||||
public GiteaIssueSearch(IRepositoryQuery query) {
|
||||
assignee = query.getAttribute("assignee");
|
||||
milestone = query.getAttribute("milestone");
|
||||
|
||||
opened = Boolean.parseBoolean(query.getAttribute("opened"));
|
||||
closed = Boolean.parseBoolean(query.getAttribute("closed"));
|
||||
|
||||
for (String label : query.getAttribute("labels").split(",")) {
|
||||
if (label.trim().length() > 0) {
|
||||
labels.add(Pattern.compile(label.trim()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean doesMatch(Issue issue) {
|
||||
if (!assignee.equals("") && (issue.getAssignee() == null || !(assignee.equals(issue.getAssignee().getLogin())
|
||||
|| assignee.equals(issue.getAssignee().getFullName())))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!milestone.equals("")
|
||||
&& (issue.getMilestone() == null || !milestone.equals(issue.getMilestone().getTitle()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Pattern> matchedLabels = new ArrayList<Pattern>();
|
||||
for (Pattern p : labels) {
|
||||
for (Label label : issue.getLabels()) {
|
||||
if (p.matcher(label.getName()).find()) {
|
||||
matchedLabels.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedLabels.size() < labels.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!closed && IssueState.isClosed(issue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!opened && IssueState.isOpen(issue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class GiteaPluginCore extends Plugin {
|
||||
|
||||
private static GiteaPluginCore plugin;
|
||||
|
||||
public static final String ID_PLUGIN = "io.gitea.mylyn.core";
|
||||
|
||||
public static final String CONNECTOR_KIND = "gitea";
|
||||
|
||||
public static final String ENCODING_UTF_8 = "UTF-8";
|
||||
|
||||
public GiteaPluginCore() {
|
||||
}
|
||||
|
||||
public static GiteaPluginCore get() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,275 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.mylyn.tasks.core.ITaskMapping;
|
||||
import org.eclipse.mylyn.tasks.core.RepositoryResponse;
|
||||
import org.eclipse.mylyn.tasks.core.TaskRepository;
|
||||
import org.eclipse.mylyn.tasks.core.data.AbstractTaskDataHandler;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMetaData;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskCommentMapper;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskData;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskOperation;
|
||||
|
||||
import io.gitea.ApiException;
|
||||
import io.gitea.model.Comment;
|
||||
import io.gitea.model.GiteaDateTimeUtils;
|
||||
import io.gitea.model.GiteaPriorityLevel;
|
||||
import io.gitea.model.GiteaUser;
|
||||
import io.gitea.model.Issue;
|
||||
import io.gitea.model.IssueState;
|
||||
import io.gitea.model.IssueType;
|
||||
import io.gitea.model.Label;
|
||||
import io.gitea.model.Milestone;
|
||||
import io.gitea.model.User;
|
||||
import io.gitea.mylyn.core.exceptions.GiteaException;
|
||||
|
||||
/**
|
||||
* Handles the issues. It maps the attributes from the Gitea API to real Mylyn
|
||||
* issue attributes, downloads the issues for a specific task repository, and
|
||||
* creates new issues.
|
||||
*/
|
||||
public class GiteaTaskDataHandler extends AbstractTaskDataHandler {
|
||||
|
||||
public GiteaTaskDataHandler() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskAttributeMapper getAttributeMapper(TaskRepository repository) {
|
||||
try {
|
||||
return ConnectionManager.get(repository).mapper;
|
||||
} catch (CoreException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initializeTaskData(TaskRepository repository, TaskData data, ITaskMapping mapping,
|
||||
IProgressMonitor monitor) throws CoreException {
|
||||
createDefaultAttributes(data, false);
|
||||
|
||||
GiteaConnection connection = ConnectionManager.get(repository);
|
||||
TaskAttribute root = data.getRoot();
|
||||
|
||||
root.getAttribute(GiteaAttribute.PROJECT.getTaskKey()).setValue(connection.repository.getName());// FIXME: not
|
||||
// the project
|
||||
root.getAttribute(GiteaAttribute.LABELS.getTaskKey()).setValue("");
|
||||
root.getAttribute(GiteaAttribute.STATUS.getTaskKey()).setValue("open");
|
||||
root.getAttribute(GiteaAttribute.MILESTONE.getTaskKey()).setValue("");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryResponse postTaskData(TaskRepository repository, TaskData data, Set<TaskAttribute> attributes,
|
||||
IProgressMonitor monitor) throws CoreException {
|
||||
|
||||
GiteaAttributeMapper attributeMapper = (GiteaAttributeMapper) data.getAttributeMapper();
|
||||
|
||||
TaskAttribute root = data.getRoot();
|
||||
String labels = root.getAttribute(GiteaAttribute.LABELS.getTaskKey()).getValue();
|
||||
String title = root.getAttribute(GiteaAttribute.TITLE.getTaskKey()).getValue();
|
||||
String body = root.getAttribute(GiteaAttribute.BODY.getTaskKey()).getValue();
|
||||
|
||||
Long assigneeId = 0L;
|
||||
|
||||
// TODO : confirm gitea behaviour
|
||||
// We have to check, if the assignee has changed. The gitea api leaves three
|
||||
// posiblities for the assignee ID:
|
||||
// 0: leave as it is
|
||||
// -1: unassign
|
||||
// real id: assign
|
||||
// If we didnt do this, Gitea would create a comment everytime we edit the
|
||||
// issue and there is still no
|
||||
// assignee
|
||||
for (TaskAttribute a : attributes) {
|
||||
if (a.getId().equals(GiteaAttribute.ASSIGNEE.getTaskKey())) {
|
||||
User assignee = attributeMapper
|
||||
.findProjectMemberByName(root.getAttribute(GiteaAttribute.ASSIGNEE.getTaskKey()).getValue());
|
||||
assigneeId = (assignee == null ? -1 : assignee.getId());
|
||||
}
|
||||
}
|
||||
|
||||
Milestone milestone = attributeMapper
|
||||
.findMilestoneByName(root.getAttribute(GiteaAttribute.MILESTONE.getTaskKey()).getValue());
|
||||
Long milestoneId = (milestone == null ? 0 : milestone.getId());
|
||||
|
||||
/*
|
||||
* FIXME: Support issue creation GiteaConnection connection =
|
||||
* ConnectionManager.get(repository); Gitlea API api = connection.api(); try {
|
||||
* monitor.beginTask("Uploading task", IProgressMonitor.UNKNOWN); Issue issue =
|
||||
* null; if(data.isNew()) { issue =
|
||||
* api.createIssue(connection.repository.getId(), assigneeId, milestoneId,
|
||||
* labels, body, title); return new
|
||||
* RepositoryResponse(ResponseKind.TASK_CREATED, "" + issue.getIid()); } else {
|
||||
* if(root.getAttribute(TaskAttribute.COMMENT_NEW) != null &&
|
||||
* !root.getAttribute(TaskAttribute.COMMENT_NEW).getValue().equals("")) {
|
||||
* api.createNote(connection.repository.getId(),
|
||||
* GiteaConnector.getTicketId(data.getTaskId()),
|
||||
* root.getAttribute(TaskAttribute.COMMENT_NEW).getValue()); } String action =
|
||||
* root.getAttribute(TaskAttribute.OPERATION).getValue(); issue =
|
||||
* api.editIssue(connection.repository.getId(),
|
||||
* GiteaConnector.getTicketId(data.getTaskId()), assigneeId, milestoneId,
|
||||
* labels, body, title, GiteaAction.find(action).getGiteaIssueAction()); return
|
||||
* new RepositoryResponse(ResponseKind.TASK_UPDATED, "" + issue.getIid()); } }
|
||||
* catch (IOException e) { throw new
|
||||
* GiteaException("Unknown connection error!"); } finally { monitor.done(); }
|
||||
*/
|
||||
return null;// FIXME:
|
||||
}
|
||||
|
||||
public TaskData downloadTaskData(TaskRepository repository, Long ticketId) throws CoreException {
|
||||
try {
|
||||
GiteaConnection connection = ConnectionManager.get(repository);
|
||||
Issue issue = connection.issueGetIssue(ticketId);
|
||||
List<Comment> notes = connection.issueGetComments(issue);
|
||||
return createTaskDataFromGiteaIssue(issue, repository, notes);
|
||||
} catch (ApiException e) {
|
||||
throw new GiteaException("Unknown connection error!");
|
||||
}
|
||||
}
|
||||
|
||||
public TaskData createTaskDataFromGiteaIssue(Issue issue, TaskRepository repository, List<Comment> notes)
|
||||
throws CoreException {
|
||||
GiteaConnection connection = ConnectionManager.get(repository);
|
||||
TaskData data = new TaskData(connection.mapper, GiteaPluginCore.CONNECTOR_KIND, repository.getUrl(),
|
||||
issue.getNumber().toString());
|
||||
|
||||
// Labels
|
||||
List<String> labelsNames = new ArrayList<String>();
|
||||
List<Label> issueLabels = issue.getLabels();
|
||||
issueLabels.forEach((label) -> labelsNames.add(label.getName()));
|
||||
String labels = StringUtils.join(labelsNames, ", ");
|
||||
|
||||
createDefaultAttributes(data, true);
|
||||
|
||||
TaskAttribute root = data.getRoot();
|
||||
root.getAttribute(GiteaAttribute.AUTHOR.getTaskKey()).setValue(GiteaUser.getName(issue.getUser()));
|
||||
root.getAttribute(GiteaAttribute.CREATED.getTaskKey()).setValue(issue.getCreatedAt().toString());
|
||||
root.getAttribute(GiteaAttribute.BODY.getTaskKey()).setValue(issue.getBody() == null ? "" : issue.getBody());
|
||||
root.getAttribute(GiteaAttribute.LABELS.getTaskKey()).setValue(labels);
|
||||
root.getAttribute(GiteaAttribute.PROJECT.getTaskKey()).setValue(connection.repository.getName()); // FIXME:
|
||||
root.getAttribute(GiteaAttribute.STATUS.getTaskKey()).setValue(issue.getState());
|
||||
root.getAttribute(GiteaAttribute.TITLE.getTaskKey()).setValue(issue.getTitle());
|
||||
|
||||
root.getAttribute(GiteaAttribute.IID.getTaskKey()).setValue("" + issue.getNumber().toString());
|
||||
root.getAttribute(GiteaAttribute.PRIORITY.getTaskKey())
|
||||
.setValue(GiteaPriorityLevel.getPriority(labels).toString());
|
||||
root.getAttribute(GiteaAttribute.TYPE.getTaskKey()).setValue(getType(labels));
|
||||
|
||||
if (issue.getMilestone() != null) {
|
||||
root.getAttribute(GiteaAttribute.MILESTONE.getTaskKey()).setValue(issue.getMilestone().getTitle());
|
||||
}
|
||||
|
||||
if (issue.getUpdatedAt() != null) {
|
||||
root.getAttribute(GiteaAttribute.UPDATED.getTaskKey()).setValue(issue.getUpdatedAt().toString());
|
||||
}
|
||||
|
||||
if (IssueState.isClosed(issue.getState())) {
|
||||
root.getAttribute(GiteaAttribute.COMPLETED.getTaskKey()).setValue(issue.getUpdatedAt().toString());
|
||||
}
|
||||
|
||||
// Assignee name is either FulleName either Login either empty
|
||||
List<String> assigneesNames = new ArrayList<String>();
|
||||
List<User> assignees = issue.getAssignees();
|
||||
if (assignees != null) {
|
||||
assignees.forEach((assignee) -> assigneesNames.add(GiteaUser.getName(assignee)));
|
||||
root.getAttribute(GiteaAttribute.ASSIGNEE.getTaskKey()).setValue(StringUtils.join(assigneesNames, ", "));
|
||||
}
|
||||
Collections.sort(notes, new Comparator<Comment>() {
|
||||
@Override
|
||||
public int compare(Comment o1, Comment o2) {
|
||||
return o1.getCreatedAt().compareTo(o2.getCreatedAt());
|
||||
}
|
||||
});
|
||||
|
||||
int i = 0;
|
||||
for (Comment note : notes) {
|
||||
TaskCommentMapper cmapper = new TaskCommentMapper();
|
||||
cmapper.setAuthor(repository.createPerson(GiteaUser.getName(note.getUser())));
|
||||
cmapper.setCreationDate(GiteaDateTimeUtils.toDate(note.getCreatedAt()));//FIXME:
|
||||
cmapper.setText(note.getBody());
|
||||
cmapper.setNumber(++i);
|
||||
TaskAttribute attribute = data.getRoot().createAttribute(TaskAttribute.PREFIX_COMMENT + (i + 1));
|
||||
cmapper.applyTo(attribute);
|
||||
}
|
||||
|
||||
GiteaAction[] actions = GiteaAction.getActions(issue);
|
||||
for (GiteaAction action : actions) {
|
||||
TaskAttribute attribute = data.getRoot().createAttribute(TaskAttribute.PREFIX_OPERATION + action.label);
|
||||
TaskOperation.applyTo(attribute, action.label, action.label);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private void createDefaultAttributes(TaskData data, boolean existingTask) {
|
||||
createAttribute(data, GiteaAttribute.BODY);
|
||||
createAttribute(data, GiteaAttribute.TITLE);
|
||||
createAttribute(data, GiteaAttribute.LABELS);
|
||||
createAttribute(data, GiteaAttribute.STATUS);
|
||||
createAttribute(data, GiteaAttribute.PROJECT);
|
||||
|
||||
createAttribute(data, GiteaAttribute.CREATED);
|
||||
createAttribute(data, GiteaAttribute.COMPLETED);
|
||||
createAttribute(data, GiteaAttribute.UPDATED);
|
||||
createAttribute(data, GiteaAttribute.ASSIGNEE);
|
||||
createAttribute(data, GiteaAttribute.MILESTONE);
|
||||
|
||||
createAttribute(data, GiteaAttribute.IID);
|
||||
createAttribute(data, GiteaAttribute.PRIORITY);
|
||||
createAttribute(data, GiteaAttribute.TYPE);
|
||||
|
||||
data.getRoot().getAttribute(GiteaAttribute.CREATED.getTaskKey()).setValue("" + (new Date().getTime()));
|
||||
|
||||
if (existingTask) {
|
||||
data.getRoot().createAttribute(TaskAttribute.COMMENT_NEW).getMetaData()
|
||||
.setType(TaskAttribute.TYPE_LONG_RICH_TEXT).setReadOnly(false);
|
||||
|
||||
createAttribute(data, GiteaAttribute.AUTHOR);
|
||||
}
|
||||
|
||||
TaskAttribute operation = data.getRoot().createAttribute(TaskAttribute.OPERATION);
|
||||
operation.getMetaData().setType(TaskAttribute.TYPE_OPERATION);
|
||||
}
|
||||
|
||||
private void createAttribute(TaskData data, GiteaAttribute attribute) {
|
||||
TaskAttribute attr = data.getRoot().createAttribute(attribute.getTaskKey());
|
||||
TaskAttributeMetaData metaData = attr.getMetaData();
|
||||
metaData.setType(attribute.getType());
|
||||
metaData.setKind(attribute.getKind());
|
||||
metaData.setLabel(attribute.toString());
|
||||
metaData.setReadOnly(attribute.isReadOnly());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type string for Mylyn. Uses a regular expression to check for
|
||||
* types in the given label.
|
||||
*
|
||||
* @param labels
|
||||
* @return
|
||||
*/
|
||||
private String getType(String labels) {
|
||||
Matcher m = IssueType.PATTERN.matcher(labels);
|
||||
if (m.find()) {
|
||||
return m.group(1);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core;
|
||||
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskData;
|
||||
import org.eclipse.mylyn.tasks.core.data.TaskMapper;
|
||||
|
||||
public class GiteaTaskMapper extends TaskMapper {
|
||||
|
||||
public GiteaTaskMapper(TaskData taskData) {
|
||||
super(taskData);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core.exceptions;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
import io.gitea.mylyn.core.GiteaPluginCore;
|
||||
|
||||
/**
|
||||
* Gitea Exception class
|
||||
*/
|
||||
public class GiteaException extends CoreException {
|
||||
|
||||
private static final long serialVersionUID = 7631319898671055531L;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param message : Exception message
|
||||
*/
|
||||
public GiteaException(String message) {
|
||||
super(new Status(Status.ERROR, GiteaPluginCore.ID_PLUGIN, message));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core.exceptions;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.NoRouteToHostException;
|
||||
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
|
||||
public class GiteaExceptionHandler {
|
||||
|
||||
public static GiteaException handle(Throwable e) {
|
||||
if (e instanceof SSLHandshakeException) {
|
||||
return new GiteaException("Invalid TLS Certificate: " + e.getMessage());
|
||||
} else if (e instanceof ConnectException) {
|
||||
return new GiteaException("Connection refused");
|
||||
} else if (e instanceof NoRouteToHostException) {
|
||||
return new GiteaException("No route to host");
|
||||
} else if (e instanceof FileNotFoundException) {
|
||||
return new GiteaException("Invalid path in host");
|
||||
} else if (e instanceof IOException) {
|
||||
return new GiteaException("Invalid username/password/private token combination");
|
||||
}
|
||||
|
||||
return new GiteaException("Unknown Exception: " + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.core.exceptions;
|
||||
|
||||
/**
|
||||
* Exception raised when trying to access unkown repository.
|
||||
*
|
||||
*/
|
||||
public class UnknownRepositoryException extends GiteaException {
|
||||
|
||||
private static final long serialVersionUID = 4976633904836890061L;
|
||||
|
||||
public UnknownRepositoryException(String project) {
|
||||
super("Unknown repository " + project + " or insufficient access rights");
|
||||
}
|
||||
|
||||
}
|
6
io.gitea.mylyn.core/src/io/gitea/package-info.java
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/** <i>local</i> extension of the generated Java Gitea API "io.gitea" package. */
|
||||
package io.gitea;
|
1
io.gitea.mylyn.core/target/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/classes/
|
12
io.gitea.mylyn.ui/.classpath
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/io.gitea.mylyn.core"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="org.eclipse.pde.api.tools.apiAnalysisBuilder"/>
|
||||
<mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
</launchConfiguration>
|
1
io.gitea.mylyn.ui/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target/
|
39
io.gitea.mylyn.ui/.project
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>io.gitea.mylyn.ui</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
<project>io.gitea.mylyn.core</project>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/org.eclipse.pde.api.tools.apiAnalysisBuilder (1).launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
108
io.gitea.mylyn.ui/.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,108 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
|
||||
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
|
||||
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
|
||||
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
|
||||
org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
|
||||
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.APILeak=warning
|
||||
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deadCode=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
|
||||
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
|
||||
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
|
||||
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
|
||||
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
|
||||
org.eclipse.jdt.core.compiler.problem.nullReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
|
||||
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
|
||||
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
|
||||
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
|
||||
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
|
||||
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
|
||||
org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
|
||||
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
|
||||
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
|
||||
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
|
||||
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
19
io.gitea.mylyn.ui/LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
MIT License Copyright (c) 2021 F.Terrot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
io.gitea.mylyn.ui/META-INF/MANIFEST.MF
Normal file
@ -0,0 +1,20 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Mylyn Gitea Connector UI
|
||||
Bundle-SymbolicName: io.gitea.mylyn.ui;singleton:=true
|
||||
Bundle-Version: 0.1.0
|
||||
Automatic-Module-Name: io.gitea.mylyn.ui
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Bundle-Activator: io.gitea.mylyn.ui.GiteaUIPlugin
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
org.eclipse.ui,
|
||||
org.eclipse.ui.forms,
|
||||
org.eclipse.mylyn.commons.net;bundle-version="[3.8.0,4.0.0)",
|
||||
org.eclipse.mylyn.commons.core;bundle-version="[3.8.0,4.0.0)",
|
||||
org.eclipse.mylyn.tasks.ui;bundle-version="[3.8.0,4.0.0)",
|
||||
org.eclipse.mylyn.tasks.core;bundle-version="[3.8.0,4.0.0)",
|
||||
org.eclipse.mylyn.commons.workbench;bundle-version="[3.8.0,4.0.0)",
|
||||
org.eclipse.mylyn.commons.ui;bundle-version="[3.8.0,4.0.0)",
|
||||
io.gitea.mylyn.core
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: io.gitea.mylyn.ui
|
9
io.gitea.mylyn.ui/build.properties
Normal file
@ -0,0 +1,9 @@
|
||||
source.. = src/
|
||||
bin.includes = META-INF/,.,plugin.xml,icons/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml,\
|
||||
LICENSE,\
|
||||
icons,\
|
||||
icons/
|
||||
jre.compilation.profile = JavaSE-1.8
|
BIN
io.gitea.mylyn.ui/icons/gitea-icon.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
io.gitea.mylyn.ui/icons/gitea-issue-open.png
Normal file
After Width: | Height: | Size: 1007 B |
BIN
io.gitea.mylyn.ui/icons/gitea-issue.png
Normal file
After Width: | Height: | Size: 768 B |
BIN
io.gitea.mylyn.ui/icons/gitea-label.png
Normal file
After Width: | Height: | Size: 718 B |
BIN
io.gitea.mylyn.ui/icons/gitea-milestone.png
Normal file
After Width: | Height: | Size: 667 B |
BIN
io.gitea.mylyn.ui/icons/gitea-overlay.png
Normal file
After Width: | Height: | Size: 687 B |
BIN
io.gitea.mylyn.ui/icons/gitea-repository.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
22
io.gitea.mylyn.ui/plugin.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.4"?>
|
||||
<plugin>
|
||||
<extension
|
||||
id="io.gitea.mylyn.ui"
|
||||
name="%repository.name"
|
||||
point="org.eclipse.mylyn.tasks.ui.repositories">
|
||||
<connectorUi
|
||||
brandingIcon="icons/gitea-icon.png"
|
||||
class="io.gitea.mylyn.ui.GiteaConnectorUI"
|
||||
id="io.gitea.mylyn.ui"
|
||||
name="GiteaConnector Ui"
|
||||
overlayIcon="icons/gitea-overlay.png"/>
|
||||
</extension>
|
||||
|
||||
<extension point="org.eclipse.mylyn.tasks.ui.editors">
|
||||
<pageFactory
|
||||
class="io.gitea.mylyn.ui.GiteaEditorPageFactory"
|
||||
id="io.gitea.mylyn.ui.pageFactory">
|
||||
</pageFactory>
|
||||
</extension>
|
||||
</plugin>
|
@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.ui;
|
||||
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.eclipse.jface.wizard.IWizard;
|
||||
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
|
||||
import org.eclipse.mylyn.tasks.core.ITask;
|
||||
import org.eclipse.mylyn.tasks.core.ITaskComment;
|
||||
import org.eclipse.mylyn.tasks.core.ITaskMapping;
|
||||
import org.eclipse.mylyn.tasks.core.TaskRepository;
|
||||
import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi;
|
||||
import org.eclipse.mylyn.tasks.ui.wizards.ITaskRepositoryPage;
|
||||
import org.eclipse.mylyn.tasks.ui.wizards.NewTaskWizard;
|
||||
import org.eclipse.mylyn.tasks.ui.wizards.RepositoryQueryWizard;
|
||||
|
||||
import io.gitea.model.IssueType;
|
||||
import io.gitea.mylyn.core.GiteaPluginCore;
|
||||
|
||||
public class GiteaConnectorUI extends AbstractRepositoryConnectorUi {
|
||||
|
||||
@Override
|
||||
public String getConnectorKind() {
|
||||
return GiteaPluginCore.CONNECTOR_KIND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWizard getNewTaskWizard(TaskRepository repository, ITaskMapping mapping) {
|
||||
return new NewTaskWizard(repository, mapping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWizard getQueryWizard(TaskRepository repository, IRepositoryQuery query) {
|
||||
RepositoryQueryWizard wizard = new RepositoryQueryWizard(repository);
|
||||
wizard.addPage(new GiteaQueryPage("New Page", repository, query));
|
||||
return wizard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITaskRepositoryPage getSettingsPage(TaskRepository repository) {
|
||||
return new GiteaRepositorySettingsPage(Labels.NEW_REPOSITORY, Labels.SETTINGS_PAGE, repository);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSearchPage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageDescriptor getTaskKindOverlay(ITask task) {
|
||||
//FIXME: complete with other kind epic,...enhancement ...
|
||||
String kind = task.getTaskKind();
|
||||
try {
|
||||
switch(IssueType.valueOf(kind)) {
|
||||
case BUG:
|
||||
return GiteaImages.ISSUE;
|
||||
case FEATURE:
|
||||
return GiteaImages.OVERLAY_FEATURE;
|
||||
case STORY:
|
||||
return GiteaImages.OVERLAY_STORY;
|
||||
default:
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// unhandled task kind.
|
||||
}
|
||||
return super.getTaskKindOverlay(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReplyText(TaskRepository taskRepository, ITask task, ITaskComment taskComment,
|
||||
boolean includeTask) {
|
||||
return "Reply to " + taskComment.getAuthor();
|
||||
}
|
||||
|
||||
}
|
36
io.gitea.mylyn.ui/src/io/gitea/mylyn/ui/GiteaEditorPage.java
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.ui;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPage;
|
||||
import org.eclipse.mylyn.tasks.ui.editors.TaskEditor;
|
||||
import org.eclipse.mylyn.tasks.ui.editors.TaskEditorPartDescriptor;
|
||||
|
||||
public class GiteaEditorPage extends AbstractTaskEditorPage {
|
||||
|
||||
public GiteaEditorPage(TaskEditor editor, String connectorKind) {
|
||||
super(editor, connectorKind);
|
||||
setNeedsPrivateSection(false);
|
||||
setNeedsSubmitButton(true);
|
||||
setNeedsAddToCategory(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<TaskEditorPartDescriptor> createPartDescriptors() {
|
||||
Set<TaskEditorPartDescriptor> descriptors = super.createPartDescriptors();
|
||||
// FIXME: remove unnecessary default editor parts
|
||||
for (Iterator<TaskEditorPartDescriptor> it = descriptors.iterator(); it.hasNext();) {
|
||||
TaskEditorPartDescriptor descriptor = it.next();
|
||||
if (descriptor.getId().equals(ID_PART_PLANNING)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.ui;
|
||||
|
||||
import org.eclipse.mylyn.commons.ui.CommonImages;
|
||||
import org.eclipse.mylyn.tasks.ui.ITasksUiConstants;
|
||||
import org.eclipse.mylyn.tasks.ui.TasksUiImages;
|
||||
import org.eclipse.mylyn.tasks.ui.TasksUiUtil;
|
||||
import org.eclipse.mylyn.tasks.ui.editors.AbstractTaskEditorPageFactory;
|
||||
import org.eclipse.mylyn.tasks.ui.editors.TaskEditor;
|
||||
import org.eclipse.mylyn.tasks.ui.editors.TaskEditorInput;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.ui.forms.editor.IFormPage;
|
||||
|
||||
import io.gitea.mylyn.core.GiteaPluginCore;
|
||||
|
||||
public class GiteaEditorPageFactory extends AbstractTaskEditorPageFactory {
|
||||
|
||||
@Override
|
||||
public boolean canCreatePageFor(TaskEditorInput input) {
|
||||
if (input.getTask().getConnectorKind().equals(GiteaPluginCore.CONNECTOR_KIND)) {
|
||||
return true;
|
||||
} else if (TasksUiUtil.isOutgoingNewTask(input.getTask(), GiteaPluginCore.CONNECTOR_KIND)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFormPage createPage(TaskEditor editor) {
|
||||
return new GiteaEditorPage(editor, GiteaPluginCore.CONNECTOR_KIND);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getPageImage() {
|
||||
return CommonImages.getImage(TasksUiImages.TASK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPageText() {
|
||||
return Labels.GITEA_ISSUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getConflictingIds(TaskEditorInput input) {
|
||||
return new String[] { ITasksUiConstants.ID_PAGE_PLANNING };
|
||||
}
|
||||
|
||||
}
|
47
io.gitea.mylyn.ui/src/io/gitea/mylyn/ui/GiteaImages.java
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.ui;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.jface.resource.ImageDescriptor;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
//FIXME: complete with other kind of issue
|
||||
public class GiteaImages {
|
||||
|
||||
private static final URL baseURL = GiteaUIPlugin.getDefault().getBundle().getEntry("/icons/"); //$NON-NLS-1$
|
||||
|
||||
public static final ImageDescriptor ISSUE = create("gitea-issue.png"); //$NON-NLS-1$
|
||||
public static final ImageDescriptor ISSUE_OPEN = create("gitea-issue-open.png"); //$NON-NLS-1$
|
||||
public static final ImageDescriptor ISSUE_CLOSED = create("gitea-issue-closed.png"); //$NON-NLS-1$
|
||||
|
||||
public static final ImageDescriptor OVERLAY_FEATURE = create("overlay-feature.png"); //$NON-NLS-1$
|
||||
|
||||
public static final ImageDescriptor OVERLAY_STORY = create("overlay-story.png"); //$NON-NLS-1$
|
||||
|
||||
public static final Image LABEL = create("gitea-label.png").createImage();
|
||||
public static final Image MILESTONE = create("gitea-milestone.png").createImage();
|
||||
public static final Image REPOSITORY = create("gitea-repository.png").createImage();
|
||||
|
||||
private static ImageDescriptor create(String name) {
|
||||
try {
|
||||
return ImageDescriptor.createFromURL(makeIconFileURL(name));
|
||||
} catch (MalformedURLException e) {
|
||||
return ImageDescriptor.getMissingImageDescriptor();
|
||||
}
|
||||
}
|
||||
|
||||
private static URL makeIconFileURL(String name) throws MalformedURLException {
|
||||
if (baseURL == null) {
|
||||
throw new MalformedURLException();
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(name);
|
||||
return new URL(baseURL, buffer.toString());
|
||||
}
|
||||
|
||||
}
|
289
io.gitea.mylyn.ui/src/io/gitea/mylyn/ui/GiteaQueryPage.java
Normal file
@ -0,0 +1,289 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.ui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jface.layout.GridDataFactory;
|
||||
import org.eclipse.jface.layout.GridLayoutFactory;
|
||||
import org.eclipse.jface.viewers.ArrayContentProvider;
|
||||
import org.eclipse.jface.viewers.LabelProvider;
|
||||
import org.eclipse.jface.viewers.StructuredSelection;
|
||||
import org.eclipse.jface.viewers.TableViewer;
|
||||
import org.eclipse.jface.wizard.IWizardPage;
|
||||
import org.eclipse.mylyn.tasks.core.IRepositoryQuery;
|
||||
import org.eclipse.mylyn.tasks.core.TaskRepository;
|
||||
import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositoryQueryPage;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.FocusEvent;
|
||||
import org.eclipse.swt.events.FocusListener;
|
||||
import org.eclipse.swt.events.KeyEvent;
|
||||
import org.eclipse.swt.events.KeyListener;
|
||||
import org.eclipse.swt.events.ModifyEvent;
|
||||
import org.eclipse.swt.events.ModifyListener;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.events.SelectionListener;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Combo;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.TableItem;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
import io.gitea.model.IssueState;
|
||||
import io.gitea.model.Milestone;
|
||||
import io.gitea.mylyn.core.ConnectionManager;
|
||||
import io.gitea.mylyn.core.GiteaConnection;
|
||||
|
||||
public class GiteaQueryPage extends AbstractRepositoryQueryPage implements IWizardPage {
|
||||
|
||||
private Button openButton;
|
||||
private Button closedButton;
|
||||
private Text titleText;
|
||||
private Text assigneeText;
|
||||
private Text newLabel;
|
||||
private Combo milestoneCombo;
|
||||
private TableViewer labelsViewer;
|
||||
|
||||
private SelectionListener completeListener = new SelectionAdapter() {
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
setPageComplete(isPageComplete());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param pageName
|
||||
* @param taskRepository
|
||||
* @param query
|
||||
*/
|
||||
public GiteaQueryPage(String pageName, TaskRepository taskRepository, IRepositoryQuery query) {
|
||||
super(pageName, taskRepository, query);
|
||||
setDescription("Specify your query");
|
||||
setPageComplete(false);
|
||||
}
|
||||
|
||||
private void createLabelsArea(Composite parent) {
|
||||
Group labelsArea = new Group(parent, SWT.NONE);
|
||||
labelsArea.setText(Labels.QUERY_GROUP_LABELS);
|
||||
GridDataFactory.fillDefaults().grab(true, true).applyTo(labelsArea);
|
||||
GridLayoutFactory.swtDefaults().applyTo(labelsArea);
|
||||
|
||||
labelsViewer = new TableViewer(labelsArea, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
|
||||
|
||||
GridDataFactory.fillDefaults().grab(true, true).hint(100, 80).applyTo(labelsViewer.getControl());
|
||||
labelsViewer.setContentProvider(ArrayContentProvider.getInstance());
|
||||
labelsViewer.setLabelProvider(new LabelProvider() {
|
||||
public Image getImage(Object element) {
|
||||
return GiteaImages.LABEL;
|
||||
}
|
||||
});
|
||||
|
||||
newLabel = new Text(labelsArea, SWT.BORDER);
|
||||
GridDataFactory.fillDefaults().grab(true, false).applyTo(newLabel);
|
||||
|
||||
Composite btnArea = new Composite(labelsArea, SWT.NONE);
|
||||
GridDataFactory.fillDefaults().grab(true, true).applyTo(btnArea);
|
||||
GridLayoutFactory.swtDefaults().numColumns(2).equalWidth(true).applyTo(btnArea);
|
||||
|
||||
final Button btnAdd = new Button(btnArea, SWT.BORDER);
|
||||
btnAdd.setText(Labels.QUERY_NEW_LABEL_REGEX);
|
||||
GridDataFactory.fillDefaults().grab(true, false).applyTo(btnAdd);
|
||||
|
||||
Button btnRemove = new Button(btnArea, SWT.BORDER);
|
||||
btnRemove.setText(Labels.QUERY_REMOVE_LABEL_REGEX);
|
||||
GridDataFactory.fillDefaults().grab(true, false).applyTo(btnRemove);
|
||||
|
||||
btnAdd.addSelectionListener(new SelectionListener() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
String[] split = newLabel.getText().split(",");
|
||||
for (String s : split) {
|
||||
if (s.trim().length() > 0) {
|
||||
labelsViewer.add(s.trim());
|
||||
}
|
||||
}
|
||||
newLabel.setText("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
}
|
||||
});
|
||||
|
||||
btnRemove.addSelectionListener(new SelectionListener() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
removeSelection();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
}
|
||||
});
|
||||
|
||||
newLabel.addFocusListener(new FocusListener() {
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
getShell().setDefaultButton(null);
|
||||
setPageComplete(isPageComplete());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
getShell().setDefaultButton(btnAdd);
|
||||
}
|
||||
});
|
||||
|
||||
labelsViewer.getTable().addKeyListener(new KeyListener() {
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if (e.keyCode == SWT.DEL) {
|
||||
removeSelection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeSelection() {
|
||||
StructuredSelection selection = (StructuredSelection) labelsViewer.getSelection();
|
||||
if (!selection.isEmpty()) {
|
||||
labelsViewer.remove(selection.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void createOptionsArea(Composite parent) {
|
||||
Composite optionsArea = new Composite(parent, SWT.NONE);
|
||||
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(optionsArea);
|
||||
GridDataFactory.fillDefaults().grab(true, true).applyTo(optionsArea);
|
||||
|
||||
Composite statusArea = new Composite(optionsArea, SWT.NONE);
|
||||
GridLayoutFactory.fillDefaults().numColumns(4).equalWidth(false).applyTo(statusArea);
|
||||
GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(statusArea);
|
||||
|
||||
new Label(statusArea, SWT.NONE).setText(Labels.QUERY_STATE);
|
||||
|
||||
openButton = new Button(statusArea, SWT.CHECK);
|
||||
openButton.setSelection(true);
|
||||
openButton.setText(IssueState.STATE_OPENED.toString());
|
||||
openButton.addSelectionListener(completeListener);
|
||||
|
||||
closedButton = new Button(statusArea, SWT.CHECK);
|
||||
closedButton.setSelection(true);
|
||||
closedButton.setText(IssueState.STATE_CLOSED.toString());
|
||||
closedButton.addSelectionListener(completeListener);
|
||||
|
||||
Label milestonesLabel = new Label(optionsArea, SWT.NONE);
|
||||
milestonesLabel.setText(Labels.QUERY_MILESTONE);
|
||||
|
||||
milestoneCombo = new Combo(optionsArea, SWT.DROP_DOWN | SWT.READ_ONLY);
|
||||
GridDataFactory.fillDefaults().grab(true, false).applyTo(milestoneCombo);
|
||||
GiteaConnection connection = ConnectionManager.getSafe(getTaskRepository());
|
||||
if (connection != null) {
|
||||
milestoneCombo.add("");
|
||||
for (Milestone s : connection.getMilestones()) {
|
||||
milestoneCombo.add(s.getTitle());
|
||||
}
|
||||
}
|
||||
|
||||
Label assigneeLabel = new Label(optionsArea, SWT.NONE);
|
||||
assigneeLabel.setText(Labels.QUERY_ASSIGNEE);
|
||||
|
||||
assigneeText = new Text(optionsArea, SWT.BORDER | SWT.SINGLE);
|
||||
GridDataFactory.fillDefaults().grab(true, false).applyTo(assigneeText);
|
||||
}
|
||||
|
||||
public void createControl(Composite parent) {
|
||||
Composite displayArea = new Composite(parent, SWT.NONE);
|
||||
GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(true).applyTo(displayArea);
|
||||
GridDataFactory.fillDefaults().grab(true, true).applyTo(displayArea);
|
||||
|
||||
if (!inSearchContainer()) {
|
||||
Composite titleArea = new Composite(displayArea, SWT.NONE);
|
||||
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(titleArea);
|
||||
GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(titleArea);
|
||||
|
||||
new Label(titleArea, SWT.NONE).setText(Labels.QUERY_TITLE);
|
||||
titleText = new Text(titleArea, SWT.SINGLE | SWT.BORDER);
|
||||
GridDataFactory.fillDefaults().grab(true, false).applyTo(titleText);
|
||||
titleText.addModifyListener(new ModifyListener() {
|
||||
public void modifyText(ModifyEvent e) {
|
||||
setPageComplete(isPageComplete());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
createOptionsArea(displayArea);
|
||||
|
||||
createLabelsArea(displayArea);
|
||||
|
||||
initialize();
|
||||
setControl(displayArea);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
IRepositoryQuery query = getQuery();
|
||||
if (query == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
titleText.setText(query.getSummary());
|
||||
assigneeText.setText(query.getAttribute("assignee"));
|
||||
milestoneCombo.setText(query.getAttribute("milestone"));
|
||||
|
||||
openButton.setSelection(Boolean.parseBoolean(query.getAttribute("opened")));
|
||||
closedButton.setSelection(Boolean.parseBoolean(query.getAttribute("closed")));
|
||||
|
||||
for (String label : query.getAttribute("labels").split(",")) {
|
||||
if (label.trim().length() > 0) {
|
||||
labelsViewer.add(label.trim());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isPageComplete() {
|
||||
boolean complete = inSearchContainer() ? true : super.isPageComplete();
|
||||
if (complete) {
|
||||
String message = null;
|
||||
if (!openButton.getSelection() && !closedButton.getSelection()) {
|
||||
message = "Select either closed, opened or both issue states";
|
||||
}
|
||||
|
||||
setErrorMessage(message);
|
||||
complete = message == null;
|
||||
}
|
||||
return complete;
|
||||
}
|
||||
|
||||
public String getQueryTitle() {
|
||||
return titleText != null ? titleText.getText() : null;
|
||||
}
|
||||
|
||||
public void applyTo(IRepositoryQuery query) {
|
||||
query.setSummary(titleText.getText());
|
||||
query.setAttribute("assignee", assigneeText.getText());
|
||||
query.setAttribute("milestone", milestoneCombo.getText());
|
||||
query.setAttribute("opened", "" + openButton.getSelection());
|
||||
query.setAttribute("closed", "" + closedButton.getSelection());
|
||||
|
||||
ArrayList<String> labels = new ArrayList<String>();
|
||||
|
||||
for (TableItem i : labelsViewer.getTable().getItems()) {
|
||||
labels.add(i.getText());
|
||||
}
|
||||
query.setAttribute("labels", StringUtils.join(labels, ","));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.ui;
|
||||
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.jface.layout.GridDataFactory;
|
||||
import org.eclipse.mylyn.tasks.core.TaskRepository;
|
||||
import org.eclipse.mylyn.tasks.ui.wizards.AbstractRepositorySettingsPage;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
import io.gitea.mylyn.core.GiteaConnector;
|
||||
import io.gitea.mylyn.core.GiteaPluginCore;
|
||||
|
||||
/** Mylyn Gitea repository configuration page. */
|
||||
public class GiteaRepositorySettingsPage extends AbstractRepositorySettingsPage {
|
||||
|
||||
private Button useToken;
|
||||
private Text giteaBaseUrl;
|
||||
|
||||
public GiteaRepositorySettingsPage(String title, String description, TaskRepository taskRepository) {
|
||||
super(title, description, taskRepository);
|
||||
|
||||
setNeedsValidateOnFinish(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createAdditionalControls(final Composite composite) {
|
||||
savePasswordButton.setSelection(true);
|
||||
|
||||
useToken = new Button(composite, SWT.CHECK);
|
||||
useToken.setText("Use private token instead of username/password");
|
||||
GridDataFactory.fillDefaults().span(2, 1).applyTo(useToken);
|
||||
|
||||
useToken.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
setUsernameFieldEnabled(!useToken.getSelection());
|
||||
getWizard().getContainer().updateButtons();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void widgetDefaultSelected(SelectionEvent e) {
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Label l = new Label(composite, SWT.NONE);
|
||||
l.setText("Gitea base URL");
|
||||
|
||||
giteaBaseUrl = new Text(composite, SWT.SINGLE | SWT.BORDER);
|
||||
GridDataFactory.fillDefaults().span(1, 1).applyTo(giteaBaseUrl);
|
||||
|
||||
/**
|
||||
* Set widget texts and check boxes if necessary.
|
||||
*/
|
||||
if (serverUrlCombo.getText().length() == 0) {
|
||||
// This means, that there the user is *not* editing an existing repository
|
||||
// configuration
|
||||
serverUrlCombo.setText("https://your-host.org/namespace/repository.git");
|
||||
serverUrlCombo.setText(Labels.SAMPLE_URL);
|
||||
}
|
||||
|
||||
if (getRepository() != null) {
|
||||
if ("true".equals(getRepository().getProperty("usePrivateToken"))) {
|
||||
useToken.setSelection(true);
|
||||
setUsernameFieldEnabled(false);
|
||||
}
|
||||
|
||||
if (getRepository().getProperty("giteaBaseUrl") != null) {
|
||||
giteaBaseUrl.setText(getRepository().getProperty("giteaBaseUrl"));
|
||||
}
|
||||
} else {
|
||||
// Default is to use token
|
||||
useToken.setSelection(true); // Let select use token by default
|
||||
setUsernameFieldEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void setUsernameFieldEnabled(boolean enabled) {
|
||||
if (enabled) {
|
||||
repositoryUserNameEditor.getTextControl(compositeContainer).setEnabled(true);
|
||||
repositoryUserNameEditor.setEmptyStringAllowed(false);
|
||||
repositoryPasswordEditor.setLabelText(LABEL_PASSWORD);
|
||||
compositeContainer.layout();
|
||||
} else {
|
||||
repositoryUserNameEditor.setStringValue("");
|
||||
repositoryUserNameEditor.getTextControl(compositeContainer).setEnabled(false);
|
||||
repositoryUserNameEditor.setEmptyStringAllowed(true);
|
||||
repositoryPasswordEditor.setLabelText("Private token:");
|
||||
compositeContainer.layout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnectorKind() {
|
||||
return GiteaPluginCore.CONNECTOR_KIND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskRepository createTaskRepository() {
|
||||
TaskRepository repo = super.createTaskRepository();
|
||||
return repo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyTo(TaskRepository repository) {
|
||||
repository.setCategory(TaskRepository.CATEGORY_BUGS);
|
||||
super.applyTo(repository);
|
||||
if (useToken.getSelection()) {
|
||||
repository.setProperty("usePrivateToken", "true");
|
||||
} else {
|
||||
repository.setProperty("usePrivateToken", "false");
|
||||
}
|
||||
|
||||
repository.setProperty("giteaBaseUrl", giteaBaseUrl.getText());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isMissingCredentials() {
|
||||
if (useToken != null && useToken.getSelection()) {
|
||||
return repositoryPasswordEditor.getStringValue().trim().equals("");
|
||||
} else {
|
||||
return super.isMissingCredentials();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Validator getValidator(final TaskRepository repository) {
|
||||
return new Validator() {
|
||||
|
||||
@Override
|
||||
public void run(IProgressMonitor monitor) throws CoreException {
|
||||
GiteaConnector.validate(repository);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
33
io.gitea.mylyn.ui/src/io/gitea/mylyn/ui/GiteaUIPlugin.java
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.ui;
|
||||
|
||||
import org.eclipse.ui.plugin.AbstractUIPlugin;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
public class GiteaUIPlugin extends AbstractUIPlugin {
|
||||
|
||||
private static GiteaUIPlugin plugin;
|
||||
|
||||
public GiteaUIPlugin() {
|
||||
plugin = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(BundleContext context) throws Exception {
|
||||
super.start(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext context) throws Exception {
|
||||
plugin = null;
|
||||
super.stop(context);
|
||||
}
|
||||
|
||||
public static GiteaUIPlugin getDefault() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
}
|
25
io.gitea.mylyn.ui/src/io/gitea/mylyn/ui/Labels.java
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2021, Fr.Terrot. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package io.gitea.mylyn.ui;
|
||||
|
||||
public class Labels {
|
||||
public final static String SAMPLE_URL = "https://forge.chapril.org/gitea/mylyn-gitea.git";
|
||||
|
||||
public final static String NEW_REPOSITORY = "New repository";
|
||||
public final static String SETTINGS_PAGE = "Enter the HTTPS-URL to your Gitea repository";
|
||||
|
||||
public final static String QUERY_TITLE = "Query title: ";
|
||||
|
||||
public final static String QUERY_GROUP_LABELS = "Labels";
|
||||
public final static String QUERY_NEW_LABEL_REGEX = "Add label regex";
|
||||
public final static String QUERY_REMOVE_LABEL_REGEX = "Remove selected label";
|
||||
|
||||
public final static String QUERY_ASSIGNEE = "Assignee: ";
|
||||
public final static String QUERY_MILESTONE = "Milestone: ";
|
||||
public final static String QUERY_STATE = "State: ";
|
||||
|
||||
public final static String GITEA_ISSUE = "Gitea issue";
|
||||
|
||||
}
|
1
io.gitea.mylyn.updatesite
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit f379a24a325596b54048a634152fda657e53a6c9
|
17
io.gitea.mylyn/.project
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>io.gitea.mylyn</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.FeatureBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.FeatureNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
19
io.gitea.mylyn/LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
MIT License Copyright (c) 2021 F.Terrot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
3
io.gitea.mylyn/build.properties
Normal file
@ -0,0 +1,3 @@
|
||||
bin.includes = feature.xml,\
|
||||
feature.properties,\
|
||||
LICENSE
|
46
io.gitea.mylyn/feature.properties
Normal file
@ -0,0 +1,46 @@
|
||||
#/* **************************************************************************
|
||||
# *
|
||||
# * Copyright (c) 2021, Fr.Terrot
|
||||
# *
|
||||
# * All rights reserved.
|
||||
# *
|
||||
# * This program and the accompanying materials are made available under the terms
|
||||
# * of the Eclipse Public License v2.0 which accompanies this distribution, and is
|
||||
# * available at http://www.eclipse.org/legal/epl-v20.html
|
||||
# *
|
||||
# * ************************************************************************** */
|
||||
featureName=Mylyn Gitea Connector
|
||||
|
||||
providerName=Gitea
|
||||
description=Mylyn Tasks connector for the open source management software Gitea.
|
||||
|
||||
|
||||
# "licenseURL" property - URL of the "Feature License"
|
||||
# do not translate value - just change to point to a locale-specific HTML page
|
||||
licenseURL=https://forge.chapril.org/gitea/mylyn-gitea/raw/branch/development/LICENSE
|
||||
|
||||
# "license" property - text of the "Feature Update License"
|
||||
# should be plain text version of license agreement pointed to be "licenseURL"
|
||||
license=\
|
||||
\n
|
||||
MIT License Copyright (c) 2021 F.Terrot\n
|
||||
\n
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy\n
|
||||
of this software and associated documentation files (the "Software"), to deal\n
|
||||
in the Software without restriction, including without limitation the rights\n
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n
|
||||
copies of the Software, and to permit persons to whom the Software is furnished\n
|
||||
to do so, subject to the following conditions:\n
|
||||
\n
|
||||
The above copyright notice and this permission notice (including the next\n
|
||||
paragraph) shall be included in all copies or substantial portions of the\n
|
||||
Software.\n
|
||||
\n
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS\n
|
||||
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF\n
|
||||
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n
|
||||
\n
|
||||
########### end of license property ##########################################
|
55
io.gitea.mylyn/feature.xml
Normal file
@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feature
|
||||
id="io.gitea.mylyn"
|
||||
label="Mylyn Gitea Connector"
|
||||
version="0.1.0"
|
||||
provider-name="io.gitea">
|
||||
|
||||
<description>
|
||||
%description
|
||||
</description>
|
||||
|
||||
<copyright>
|
||||
Copyright (c) 2021 François Terrot
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the MIT License which
|
||||
accompanies this distribution.
|
||||
</copyright>
|
||||
|
||||
<license url="">
|
||||
%license
|
||||
</license>
|
||||
|
||||
<url>
|
||||
<update label="Mylyn Gitea Connector Update Site" url="https://forge.chapril.org/gitea/mylyn-gitea/io.gitea.mylyn.updatesite"/>
|
||||
</url>
|
||||
|
||||
<requires>
|
||||
<import plugin="org.eclipse.core.runtime"/>
|
||||
<import plugin="org.eclipse.mylyn.tasks.core" version="3.8.0" match="compatible"/>
|
||||
<import plugin="org.eclipse.mylyn.tasks.ui"/>
|
||||
<import plugin="org.eclipse.mylyn.commons.net" version="3.8.0" match="compatible"/>
|
||||
<import plugin="org.eclipse.ui"/>
|
||||
<import plugin="org.eclipse.ui.forms"/>
|
||||
<import plugin="org.eclipse.mylyn.commons.core" version="3.8.0" match="compatible"/>
|
||||
<import plugin="org.eclipse.mylyn.tasks.ui" version="3.8.0" match="compatible"/>
|
||||
<import plugin="org.eclipse.mylyn.commons.workbench" version="3.8.0" match="compatible"/>
|
||||
<import plugin="org.eclipse.mylyn.commons.ui" version="3.8.0" match="compatible"/>
|
||||
</requires>
|
||||
|
||||
<plugin
|
||||
id="io.gitea.mylyn.core"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.1.2"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="io.gitea.mylyn.ui"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.1.1"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
1
java.gitea.api
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 0f63be058234fcfa1bce7d09f3b4caff06f84ffc
|