Finished libpit 1.1.0. Added change operations (priority, category, etc)
Began unit testing of libpit. Made most of the changes to pit-cli needed to incorporate the new libpit features.
This commit is contained in:
parent
cfed10c3ed
commit
4035f366f3
@ -1,5 +1,5 @@
|
|||||||
Add the ability to change an issue's status
|
Add the ability to change an issue's category
|
||||||
===========================================
|
=============================================
|
||||||
|
|
||||||
The -l/--list options lists issues, add a set of options to reclassify
|
The -l/--list options lists issues, add a set of options to reclassify
|
||||||
an issue from one category to another. The most common is CLOSED, but
|
an issue from one category to another. The most common is CLOSED, but
|
||||||
|
@ -1,4 +1,2 @@
|
|||||||
Add the ability to re-prioritize a set of issues
|
Add the ability to re-prioritize an issue.
|
||||||
================================================
|
==========================================
|
||||||
|
|
||||||
Add a mode that changes the priority of a selection of issues.
|
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
Add the ability to enter new issues
|
Add the ability to enter new issues
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
|
Implemented on 2010/02/17
|
@ -1,2 +1,4 @@
|
|||||||
Add unit tests for changing an issue's category.
|
Add unit tests for changing an issue's category.
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
|
Test defined in test/com/jdbernard/pit/IssueTest.groovy
|
@ -1,2 +1,5 @@
|
|||||||
Add unit tests for changing an issue's priority.
|
Add unit tests for changing an issue's priority.
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
|
|
||||||
|
Test defined in test/com/jdbernard/pit/IssueTest.groovy
|
@ -1,3 +1,4 @@
|
|||||||
Add unit tests covering Issue construction.
|
Add unit tests covering Issue construction.
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
|
Test defined in test/com/jdbernard/pit/IssueTest.groovy
|
2
issues/pit-cli/0003c5.rst
Normal file
2
issues/pit-cli/0003c5.rst
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Add the ability to change an Issue's priority.
|
||||||
|
==============================================
|
2
issues/pit-cli/0004c5.rst
Normal file
2
issues/pit-cli/0004c5.rst
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Add the ability to change an Issue's category.
|
||||||
|
==============================================
|
2
issues/pit-cli/0005f4.rst
Normal file
2
issues/pit-cli/0005f4.rst
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Add the ability to create a new issue.
|
||||||
|
======================================
|
@ -14,6 +14,12 @@
|
|||||||
<fileset dir="${lib.dir}">
|
<fileset dir="${lib.dir}">
|
||||||
<include name="**/*.jar"/>
|
<include name="**/*.jar"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
|
<pathelement path="${build.dir}/classes"/>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path id="test.classpath">
|
||||||
|
<path refid="groovyc.classpath"/>
|
||||||
|
<pathelement path="${build.dir}/tests"/>
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
<taskdef name="groovyc"
|
<taskdef name="groovyc"
|
||||||
@ -68,7 +74,27 @@
|
|||||||
classpathref="groovyc.classpath"/>
|
classpathref="groovyc.classpath"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="build" depends="compile">
|
<target name="compile-tests" depends="init,compile">
|
||||||
|
<mkdir dir="${build.dir}/tests"/>
|
||||||
|
<groovyc
|
||||||
|
srcdir="${test.dir}"
|
||||||
|
destdir="${build.dir}/tests"
|
||||||
|
classpathref="groovyc.classpath"/>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="run-tests" depends="compile-tests">
|
||||||
|
<junit fork="yes" haltonfailure="yes">
|
||||||
|
<classpath refid="test.classpath"/>
|
||||||
|
<formatter type="brief" usefile="false" />
|
||||||
|
<batchtest>
|
||||||
|
<fileset dir="${build.dir}/tests">
|
||||||
|
<include name="**/*.class"/>
|
||||||
|
</fileset>
|
||||||
|
</batchtest>
|
||||||
|
</junit>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="build" depends="compile,run-tests">
|
||||||
<mkdir dir="${build.dir}/jar"/>
|
<mkdir dir="${build.dir}/jar"/>
|
||||||
<jar
|
<jar
|
||||||
destfile="${build.dir}/jar/pit-${application.version}.${build.number.final}.jar"
|
destfile="${build.dir}/jar/pit-${application.version}.${build.number.final}.jar"
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#Mon Feb 15 21:53:26 CST 2010
|
#Thu Feb 18 10:56:00 CST 2010
|
||||||
expected.application.version=1.1.0
|
|
||||||
build.number=2
|
|
||||||
src.dir=src
|
|
||||||
release.dir=release
|
|
||||||
build.dir=build
|
build.dir=build
|
||||||
|
src.dir=src
|
||||||
|
lib.shared.dir=../shared-libs
|
||||||
|
test.dir=test
|
||||||
|
build.number=58
|
||||||
|
expected.application.version=1.1.0
|
||||||
lib.dir=lib
|
lib.dir=lib
|
||||||
|
release.dir=release
|
||||||
release.jar=pit-${application.version}.jar
|
release.jar=pit-${application.version}.jar
|
||||||
|
BIN
libpit/release/pit-1.1.0.jar
Normal file
BIN
libpit/release/pit-1.1.0.jar
Normal file
Binary file not shown.
@ -11,4 +11,6 @@ public enum Category {
|
|||||||
if (c.toString().startsWith(s.toUpperCase())) return c
|
if (c.toString().startsWith(s.toUpperCase())) return c
|
||||||
throw new IllegalArgumentException("No category matches ${s}.")
|
throw new IllegalArgumentException("No category matches ${s}.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSymbol() { toString()[0].toLowerCase() }
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,11 @@ class Filter {
|
|||||||
List<String> ids = null
|
List<String> ids = null
|
||||||
int priority = 9
|
int priority = 9
|
||||||
boolean acceptProjects = true
|
boolean acceptProjects = true
|
||||||
Closure projectSorter
|
Closure projectSorter = defaultIssueSorter
|
||||||
Closure issueSorter
|
Closure issueSorter = defaultProjectSorter
|
||||||
|
|
||||||
|
public static Closure defaultIssueSorter = { it.id.toInteger() }
|
||||||
|
public static Closure defaultProjectSorter = { it.name }
|
||||||
|
|
||||||
public boolean accept(Issue i) {
|
public boolean accept(Issue i) {
|
||||||
return (i.priority <= priority &&
|
return (i.priority <= priority &&
|
||||||
|
@ -26,16 +26,22 @@ public class Issue {
|
|||||||
|
|
||||||
void setCategory(Category c) {
|
void setCategory(Category c) {
|
||||||
this.category = c
|
this.category = c
|
||||||
source.renameTo(getFilename())
|
source.renameTo(new File(source.canonicalFile.parentFile, getFilename()))
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPriority(int p) {
|
void setPriority(int p) {
|
||||||
if (p < 0) priority = 0
|
if (p < 0) priority = 0
|
||||||
else if (p > 9) priority = 9
|
else if (p > 9) priority = 9
|
||||||
else priority = p
|
else priority = p
|
||||||
source.renameTo(getFilename())
|
source.renameTo(new File(source.canonicalFile.parentFile, getFilename()))
|
||||||
}
|
}
|
||||||
|
|
||||||
String getFilename() { return id + category.symbol + priority + ".rst"; }
|
String getFilename() { return makeFilename(id, category, priority) }
|
||||||
|
|
||||||
|
static String makeFilename(String id, Category category, int priority) {
|
||||||
|
return id + category.symbol + priority + ".rst";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString() { return "${id}(${priority}): ${category} ${title}" }
|
||||||
}
|
}
|
||||||
|
@ -38,16 +38,26 @@ class Project {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rename(String newName) { source.renameTo(newName) }
|
public void rename(String newName) {
|
||||||
|
this.name = newName
|
||||||
|
source.renameTo(new File(source.canonicalFile.parentFile, newName))
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) { rename(name) }
|
||||||
|
|
||||||
public void eachIssue(Closure c) {
|
public void eachIssue(Filter filter = null, Closure c) {
|
||||||
for (i in issues.values()) c.call(i)
|
def sorter = filter?.issueSorter ?: Filter.defaultIssueSorter
|
||||||
for (p in projects.values()) p.eachIssue(c)
|
for (i in issues.values().sort(sorter)) c.call(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
public void eachProject(Filter filter = null, Closure c) {
|
||||||
|
def sorter = filter?.projectSorter ?: Filter.defaultProjectSorter
|
||||||
|
for (p in projects.values().sort(sorter)) c.call(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
public void each(Filter filter = null, Closure c) {
|
public void each(Filter filter = null, Closure c) {
|
||||||
def is = filter?.issueSorter ?: { it.id.toInteger() }
|
def is = filter?.issueSorter ?: Filter.defaultIssueSorter
|
||||||
def ps = filter?.projectSorter ?: { it.name }
|
def ps = filter?.projectSorter ?: Filter.defaultProjectSorter
|
||||||
|
|
||||||
for (issue in issues.values().sort(is)) {
|
for (issue in issues.values().sort(is)) {
|
||||||
if (filter && !filter.accept(issue))
|
if (filter && !filter.accept(issue))
|
||||||
@ -61,23 +71,25 @@ class Project {
|
|||||||
return
|
return
|
||||||
|
|
||||||
c.call(project)
|
c.call(project)
|
||||||
project.each(c)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void list(Map options = [:]) {
|
public Issue createNewIssue(Map options) {
|
||||||
if (!options.offset) options.offset = ""
|
if (!options.category) options.category = Category.TASK
|
||||||
if (!options.verbose) options.verbose = false
|
if (!options.priority) options.priority = 5
|
||||||
|
if (!options.text) options.text = "Default issue title.\n" +
|
||||||
|
"====================\n"
|
||||||
|
String id = (issues.values().max { it.id.toInteger() }).id
|
||||||
|
|
||||||
each(options.filter) {
|
def issueFile = new File(source, Issue.makeFilename(id, options.category, options.priority))
|
||||||
if (it instanceof Project) {
|
assert !issueFile.exists()
|
||||||
println "\n${options.offset}${it.name}"
|
issueFile.createNewFile()
|
||||||
println "${options.offset}${'-'.multiply(it.name.length())}"
|
issueFile.write(options.text)
|
||||||
} else {
|
|
||||||
println "${options.offset}${it.id}(${it.priority}): " +
|
return new Issue(issueFile)
|
||||||
"${it.category} ${it.title}"
|
|
||||||
if (options.verbose) println "\n${it.text}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String toString() { return name }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
12
libpit/test/com/jdbernard/pit/FilterTest.groovy
Normal file
12
libpit/test/com/jdbernard/pit/FilterTest.groovy
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package com.jdbernard.pit
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import static org.junit.Assert.assertTrue
|
||||||
|
|
||||||
|
class FilterTest {
|
||||||
|
|
||||||
|
@Test void emptyTest() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,10 @@
|
|||||||
package com.jdbernard.pit
|
package com.jdbernard.pit
|
||||||
|
|
||||||
class IssueTest
|
import org.junit.*
|
||||||
|
import static org.junit.Assert.assertTrue
|
||||||
|
import static org.junit.Assert.assertFalse
|
||||||
|
|
||||||
|
class IssueTest {
|
||||||
|
|
||||||
def issues
|
def issues
|
||||||
File testDir
|
File testDir
|
||||||
@ -23,43 +27,60 @@ class IssueTest
|
|||||||
issueFile.write(
|
issueFile.write(
|
||||||
"Obtain donuts.\n" +
|
"Obtain donuts.\n" +
|
||||||
"==============\n\n" +
|
"==============\n\n" +
|
||||||
"The office is seriously lacking in sugary donuts.\n\n
|
"The office is seriously lacking in sugary donuts.\n\n" +
|
||||||
"We must rectify this at once!")
|
"We must rectify this at once!")
|
||||||
issues << new Issue(issueFile)
|
issues << new Issue(issueFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass void deleteIssueFiles() {
|
@After void deleteIssueFiles() {
|
||||||
testDir.deleteDir()
|
testDir.deleteDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test void testSetCategory() {
|
@Test void testSetCategory() {
|
||||||
|
|
||||||
assert issues[0].category == Category.FEATURE
|
assertTrue issues[0].category == Category.FEATURE
|
||||||
assert issues[1].category == Category.TASK
|
assertTrue issues[1].category == Category.TASK
|
||||||
|
|
||||||
issues[0].category == Category.CLOSED
|
issues[0].category = Category.CLOSED
|
||||||
issues[1].category == Category.TASK
|
issues[1].category = Category.BUG
|
||||||
|
|
||||||
assert issues[0].category == Category.CLOSED
|
assertTrue issues[0].category == Category.CLOSED
|
||||||
assert issues[1].category == Category.BUG
|
assertTrue issues[1].category == Category.BUG
|
||||||
|
|
||||||
assert new File(testDir, '0001c1.rst').exists()
|
assertTrue new File(testDir, '0001c1.rst').exists()
|
||||||
assert new File(testDir, '0002b5.rst').exists()
|
assertTrue new File(testDir, '0002b5.rst').exists()
|
||||||
assertFalse new File(testDir, '0001f1.rst').exists()
|
assertFalse new File(testDir, '0001f1.rst').exists()
|
||||||
assertFalse new File(testDir, '0002t5.rst').exists()
|
assertFalse new File(testDir, '0002t5.rst').exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test void testIssueConstructor() {
|
@Test void testSetPriority() {
|
||||||
|
|
||||||
|
assertTrue issues[0].priority == 1
|
||||||
|
assertTrue issues[1].priority == 5
|
||||||
|
|
||||||
|
issues[0].priority = 2
|
||||||
|
issues[1].priority = 9
|
||||||
|
|
||||||
|
assertTrue issues[0].priority == 2
|
||||||
|
assertTrue issues[1].priority == 9
|
||||||
|
|
||||||
|
assertTrue new File(testDir, '0001f2.rst').exists()
|
||||||
|
assertTrue new File(testDir, '0002t9.rst').exists()
|
||||||
|
assertFalse new File(testDir, '0001f1.rst').exists()
|
||||||
|
assertFalse new File(testDir, '0002t5.rst').exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testConstruction() {
|
||||||
File issueFile = new File(testDir, '0001f1.rst')
|
File issueFile = new File(testDir, '0001f1.rst')
|
||||||
Issue issue = new Issue(issueFile)
|
Issue issue = new Issue(issueFile)
|
||||||
|
|
||||||
assert issue.id == "0001"
|
assertTrue issue.id == "0001"
|
||||||
assert issue.category == Category.FEATURE
|
assertTrue issue.category == Category.FEATURE
|
||||||
assert issue.priority == 1
|
assertTrue issue.priority == 1
|
||||||
assert issue.title == "Add the killer feature to the killer app."
|
assertTrue issue.title == "Add the killer feature to the killer app."
|
||||||
assert issue.text == "Add the killer feature to the killer app.\n" +
|
assertTrue issue.text == "Add the killer feature to the killer app.\n" +
|
||||||
"=========================================\n\n" +
|
"=========================================\n\n" +
|
||||||
"Make our killer app shine!."
|
"Make our killer app shine!."
|
||||||
assert issue.source == issueFile
|
assertTrue issue.source == issueFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
115
libpit/test/com/jdbernard/pit/ProjectTest.groovy
Normal file
115
libpit/test/com/jdbernard/pit/ProjectTest.groovy
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package com.jdbernard.pit
|
||||||
|
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import static org.junit.Assert.assertTrue
|
||||||
|
import static org.junit.Assert.assertFalse
|
||||||
|
|
||||||
|
class ProjectTest {
|
||||||
|
|
||||||
|
File testDir
|
||||||
|
Project rootProj
|
||||||
|
|
||||||
|
@Before void createTestProjects() {
|
||||||
|
testDir = new File('testdir')
|
||||||
|
testDir.mkdirs()
|
||||||
|
|
||||||
|
def issueFile = new File(testDir, '0001t5.rst')
|
||||||
|
issueFile.createNewFile()
|
||||||
|
issueFile.write('Test Issue 1\n' +
|
||||||
|
'============\n\n' +
|
||||||
|
'This is the first test issue.')
|
||||||
|
|
||||||
|
issueFile = new File(testDir, '0002b5.rst')
|
||||||
|
issueFile.createNewFile()
|
||||||
|
issueFile.write('Test Bug\n' +
|
||||||
|
'========\n\n' +
|
||||||
|
'Yeah, it is a test bug.')
|
||||||
|
|
||||||
|
issueFile = new File(testDir, '0003f2.rst')
|
||||||
|
issueFile.createNewFile()
|
||||||
|
issueFile.write('Important Feature Request\n' +
|
||||||
|
'=========================\n\n' +
|
||||||
|
'Here is our sweet feature. Please implement it!')
|
||||||
|
|
||||||
|
def subDir = new File(testDir, 'subproj1')
|
||||||
|
subDir.mkdirs()
|
||||||
|
|
||||||
|
issueFile = new File(subDir, '0001f3.rst')
|
||||||
|
issueFile.createNewFile()
|
||||||
|
issueFile.write('First feature in subproject\n' +
|
||||||
|
'===========================\n\n' +
|
||||||
|
'Please make the grubblers grobble.')
|
||||||
|
|
||||||
|
issueFile = new File(subDir, '0002b4.rst')
|
||||||
|
issueFile.createNewFile()
|
||||||
|
issueFile.write('Zippners are not zippning.\n' +
|
||||||
|
'==========================\n\n' +
|
||||||
|
'For some reason, the Zippners are bilperring, not zippning.')
|
||||||
|
|
||||||
|
rootProj = new Project(testDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After void deleteTestProjects() {
|
||||||
|
testDir.delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testConstruction() {
|
||||||
|
Project proj = new Project(testDir, null)
|
||||||
|
|
||||||
|
assertTrue proj.name == 'testdir'
|
||||||
|
assertTrue proj.issues.size() == 3
|
||||||
|
assertTrue proj.projects.size() == 1
|
||||||
|
|
||||||
|
// Issue construction in general is under test in IssueTest
|
||||||
|
// just check that the issues actually exists
|
||||||
|
assertTrue proj.issues['0001'].id == '0001'
|
||||||
|
assertTrue proj.issues['0001'].title == 'Test Issue 1'
|
||||||
|
|
||||||
|
assertTrue proj.issues['0002'].id == '0002'
|
||||||
|
assertTrue proj.issues['0002'].title == 'Test Bug'
|
||||||
|
|
||||||
|
assertTrue proj.issues['0003'].id == '0003'
|
||||||
|
assertTrue proj.issues['0003'].title == 'Important Feature Request'
|
||||||
|
|
||||||
|
// check sub-project behaviour
|
||||||
|
assertTrue proj.projects.subproj1 != null
|
||||||
|
assertTrue proj.projects.subproj1.name == 'subproj1'
|
||||||
|
assertTrue proj.projects.subproj1.issues.size() == 2
|
||||||
|
assertTrue proj.projects.subproj1.projects.size() == 0
|
||||||
|
assertTrue proj.projects.subproj1.issues['0001'].id == '0001'
|
||||||
|
assertTrue proj.projects.subproj1.issues['0001'].title == 'First feature in subproject'
|
||||||
|
assertTrue proj.projects.subproj1.issues['0002'].id == '0002'
|
||||||
|
assertTrue proj.projects.subproj1.issues['0002'].title == 'Zippners are not zippning.'
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testRename() {
|
||||||
|
assert rootProj.name == 'testdir'
|
||||||
|
|
||||||
|
rootProj.rename('renamedTestDir')
|
||||||
|
|
||||||
|
assertTrue rootProj.name == 'renamedTestDir'
|
||||||
|
assertTrue new File('renamedTestDir').exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@Test void testEachIssue() {
|
||||||
|
def expectedList = [rootProj.issues['0001'],
|
||||||
|
rootProj.issues['0002'], rootProj.issues['0003']]
|
||||||
|
|
||||||
|
// sort using default ordering (ids ascending)
|
||||||
|
def actualList = []
|
||||||
|
rootProj.eachIssue { actualList << it }
|
||||||
|
|
||||||
|
assertArrayEquals expectedList, actualList
|
||||||
|
|
||||||
|
// sort using reverse ordering (ids descending)
|
||||||
|
expectedList = expectedList.reverse()
|
||||||
|
actualList = []
|
||||||
|
|
||||||
|
rootProj.eachIssue(
|
||||||
|
new Filter(issueSorter: { -(it.id.toInteger()) }))
|
||||||
|
{ actualList << it }
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
@ -9,13 +9,29 @@
|
|||||||
</fileset>
|
</fileset>
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
<path id="groovyc.classpath">
|
<path id="groovy.embeddable">
|
||||||
<path refid="groovy.libs"/>
|
<fileset dir="${env.GROOVY_HOME}/embeddable">
|
||||||
|
<include name="**/*.jar"/>
|
||||||
|
</fileset>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
|
||||||
|
<path id="project.libs">
|
||||||
<fileset dir="${lib.dir}">
|
<fileset dir="${lib.dir}">
|
||||||
<include name="**/*.jar"/>
|
<include name="**/*.jar"/>
|
||||||
</fileset>
|
</fileset>
|
||||||
</path>
|
</path>
|
||||||
|
|
||||||
|
<path id="groovyc.classpath">
|
||||||
|
<path refid="groovy.libs"/>
|
||||||
|
<path refid="project.libs"/>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<path id="package.jars">
|
||||||
|
<path refid="groovy.embeddable"/>
|
||||||
|
<path refid="project.libs"/>
|
||||||
|
</path>
|
||||||
|
|
||||||
<taskdef name="groovyc"
|
<taskdef name="groovyc"
|
||||||
classname="org.codehaus.groovy.ant.Groovyc"
|
classname="org.codehaus.groovy.ant.Groovyc"
|
||||||
classpathref="groovy.libs"/>
|
classpathref="groovy.libs"/>
|
||||||
@ -80,7 +96,7 @@
|
|||||||
<target name="build" depends="compile">
|
<target name="build" depends="compile">
|
||||||
<mkdir dir="${build.dir}/jar"/>
|
<mkdir dir="${build.dir}/jar"/>
|
||||||
<unjar dest="${build.dir}/classes">
|
<unjar dest="${build.dir}/classes">
|
||||||
<path refid="groovy.libs"/>
|
<path refid="package.jars"/>
|
||||||
</unjar>
|
</unjar>
|
||||||
<jar
|
<jar
|
||||||
destfile="${build.dir}/jar/${build.jar}"
|
destfile="${build.dir}/jar/${build.jar}"
|
||||||
|
BIN
pit-cli/lib/commons-cli-1.2.jar
Normal file
BIN
pit-cli/lib/commons-cli-1.2.jar
Normal file
Binary file not shown.
Binary file not shown.
@ -1,9 +1,9 @@
|
|||||||
#Sun Feb 14 02:05:14 CST 2010
|
#Wed Feb 17 17:38:59 CST 2010
|
||||||
build.dir=build
|
build.dir=build
|
||||||
src.dir=src
|
src.dir=src
|
||||||
build.jar=pit-cli-${application.version}.${build.number}.jar
|
build.jar=pit-cli-${application.version}.${build.number}.jar
|
||||||
build.number=1
|
build.number=28
|
||||||
expected.application.version=1.0.0
|
expected.application.version=1.1.0
|
||||||
lib.dir=lib
|
lib.dir=lib
|
||||||
release.dir=release
|
release.dir=release
|
||||||
release.jar=pit-cli-${application.version}.jar
|
release.jar=pit-cli-${application.version}.jar
|
||||||
|
137
pit-cli/src/com/jdbernard/pit/PersonalIssueTrackerCLI.groovy
Normal file
137
pit-cli/src/com/jdbernard/pit/PersonalIssueTrackerCLI.groovy
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package com.jdbernard.pit
|
||||||
|
|
||||||
|
import static java.lang.Math.max
|
||||||
|
import static java.lang.Math.min
|
||||||
|
|
||||||
|
def cli = new CliBuilder(usage: '')
|
||||||
|
cli.h(longOpt: 'help', 'Show help information.')
|
||||||
|
cli.v(longOpt: 'verbose', 'Show verbose task information')
|
||||||
|
cli.l(longOpt: 'list', 'List issues. Unless otherwise specified it lists all '
|
||||||
|
+ 'sub projects and all unclosed issue categories.')
|
||||||
|
cli.i(argName: 'id', longOpt: 'id', args: 1,
|
||||||
|
'Filter issues by id. Accepts a comma-delimited list.')
|
||||||
|
cli.c(argName: 'category', longOpt: 'category', args: 1,
|
||||||
|
'Filter issues by category (bug, feature, task, closed). Accepts a '
|
||||||
|
+ 'comma-delimited list.')
|
||||||
|
cli.p(argName: 'priority', longOpt: 'priority', args: 1,
|
||||||
|
'Filter issues by priority. This acts as a threshhold, listing all issues '
|
||||||
|
+ 'greater than or equal to the given priority.')
|
||||||
|
cli.r(argName: 'project', longOpt: 'project', args: 1,
|
||||||
|
'Filter issues by project (relative to the current directory). Accepts a '
|
||||||
|
+ 'comma-delimited list.')
|
||||||
|
cli.s(longOpt: 'show-subprojects',
|
||||||
|
'Include sup projects in listing (default behaviour)')
|
||||||
|
cli.S(longOpt: 'no-subprojects', 'Do not list subprojects.')
|
||||||
|
cli.P(argName: 'new-priority', longOpt: 'set-priority', args: 1,
|
||||||
|
required: false, 'Modify the priority of the selected issues.')
|
||||||
|
cli.C(argName: 'new-category', longOpt: 'set-category', args: 1,
|
||||||
|
required: false, 'Modify the category of the selected issues.')
|
||||||
|
cli.n(longOpt: 'new-issue', 'Create a new issue.')
|
||||||
|
|
||||||
|
def opts = cli.parse(args)
|
||||||
|
def issuedb = [:]
|
||||||
|
|
||||||
|
if (!opts) System.exit(1) // better solution?
|
||||||
|
|
||||||
|
if (opts.h) cli.usage()
|
||||||
|
|
||||||
|
def categories = ['bug','feature','task']
|
||||||
|
if (opts.c) categories = opts.c.split(/[,\s]/)
|
||||||
|
categories = categories.collect { Category.toCategory(it) }
|
||||||
|
|
||||||
|
// build issue list
|
||||||
|
issuedb = new Project(new File('.'),
|
||||||
|
new Filter('categories': categories,
|
||||||
|
'priority': (opts.p ? opts.p.toInteger() : 9),
|
||||||
|
'projects': (opts.r ? opts.r.toLowerCase().split(/[,\s]/).asType(List.class) : []),
|
||||||
|
'ids': (opts.i ? opts.i.split(/[,\s]/).asType(List.class) : []),
|
||||||
|
'acceptProjects': (opts.s || !opts.S)))
|
||||||
|
|
||||||
|
// list first
|
||||||
|
if (opts.l) {
|
||||||
|
def issuePrinter = { issue, offset ->
|
||||||
|
println "${offset}${issue}"
|
||||||
|
if (opts.v) {
|
||||||
|
println ""
|
||||||
|
issue.text.eachLine { println "${offset} ${it}" }
|
||||||
|
println ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def projectPrinter
|
||||||
|
projectPrinter = { project, offset ->
|
||||||
|
println "\n${offset}${project.name}"
|
||||||
|
println "${offset}${'-'.multiply(project.name.length())}"
|
||||||
|
project.eachIssue { issuePrinter.call(it, offset) }
|
||||||
|
project.eachProject { projectPrinter.call(it, offset + " ") }
|
||||||
|
}
|
||||||
|
|
||||||
|
issuedb.eachIssue { issuePrinter.call(it, "") }
|
||||||
|
issuedb.eachProject { projectPrinter.call(it, "") }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// change priority second
|
||||||
|
else if (opts.P) {
|
||||||
|
def priority
|
||||||
|
try { priority = max(0, min(9, opts.P.toInteger())) }
|
||||||
|
catch (e) { println "Invalid priority: ${opts.P}"; return 1 }
|
||||||
|
|
||||||
|
walkProject(issuedb) { it.priority = priority }
|
||||||
|
}
|
||||||
|
// change category third
|
||||||
|
else if (opts.C) {
|
||||||
|
def cat
|
||||||
|
try { cat = Category.toCategory(opts.C) }
|
||||||
|
catch (e) { println "Invalid category: ${opts.C}"; return 1 }
|
||||||
|
|
||||||
|
walkProject(issuedb) { it.category = cat }
|
||||||
|
}
|
||||||
|
// new entry last
|
||||||
|
else if (opts.n) {
|
||||||
|
def cat, priority
|
||||||
|
String text = ""
|
||||||
|
Issue ussie
|
||||||
|
def sin = System.in.newReader()
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
try {
|
||||||
|
print "Category (bug, feature, task, closed): "
|
||||||
|
cat = Category.toCategory(sin.readLine())
|
||||||
|
break
|
||||||
|
} catch (e) {
|
||||||
|
println "Invalid category: " + e.getLocalizedMessage()
|
||||||
|
println "Valid options are: \n${Category.values().join(', ')}\n " +
|
||||||
|
"(abbreviations are accepted.)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
print "Priority (0-9): "
|
||||||
|
priority = max(0, min(9, sin.readLine().toInteger()))
|
||||||
|
break
|
||||||
|
} catch (e) { println "Not a valid value." }
|
||||||
|
}
|
||||||
|
|
||||||
|
println "Enter issue (use EOF of ^D to end): "
|
||||||
|
try {
|
||||||
|
sin.eachLine { line ->
|
||||||
|
def m = line =~ /(.*)EOF.*/
|
||||||
|
if (m) {
|
||||||
|
text << m[0][1]
|
||||||
|
sin.close()
|
||||||
|
} else text << line
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
issue = issuedb.createNewIssue(category: cat, priority: priority, text: text)
|
||||||
|
|
||||||
|
println "New issue created: "
|
||||||
|
println issue
|
||||||
|
}
|
||||||
|
|
||||||
|
def walkProject(Project p, Closure c) {
|
||||||
|
p.eachIssue(c)
|
||||||
|
p.eachProject { walkProject(it, c) }
|
||||||
|
}
|
@ -1,51 +0,0 @@
|
|||||||
package com.jdbernard.pit
|
|
||||||
|
|
||||||
def cli = new CliBuilder(usage: '')
|
|
||||||
cli.h(longOpt: 'help', 'Show help information.')
|
|
||||||
cli.v(longOpt: 'verbose', 'Show verbose task information')
|
|
||||||
cli.l(longOpt: 'list', 'List issues. Unless otherwise specified it lists all '
|
|
||||||
+ 'sub projects and all unclosed issue categories.')
|
|
||||||
cli.i(argName: 'id', longOpt: 'id', args: 1,
|
|
||||||
'Filter issues by id. Accepts a comma-delimited list.')
|
|
||||||
cli.c(argName: 'category', longOpt: 'category', args: 1,
|
|
||||||
'Filter issues by category (bug, feature, task, closed). Accepts a '
|
|
||||||
+ 'comma-delimited list.')
|
|
||||||
cli.p(argName: 'priority', longOpt: 'priority', args: 1,
|
|
||||||
'Filter issues by priority. This acts as a threshhold, listing all issues '
|
|
||||||
+ 'greater than or equal to the given priority.')
|
|
||||||
cli.r(argName: 'project', longOpt: 'project', args: 1,
|
|
||||||
'Filter issues by project (relative to the current directory). Accepts a '
|
|
||||||
+ 'comma-delimited list.')
|
|
||||||
cli.s(longOpt: 'show-subprojects',
|
|
||||||
'Include sup projects in listing (default behaviour)')
|
|
||||||
cli.S(longOpt: 'no-subprojects', 'Do not list subprojects.')
|
|
||||||
|
|
||||||
def opts = cli.parse(args)
|
|
||||||
def issuedb = [:]
|
|
||||||
|
|
||||||
if (!opts) System.exit(1) // better solution?
|
|
||||||
|
|
||||||
if (opts.h) cli.usage()
|
|
||||||
|
|
||||||
def categories = ['bug','feature','task']
|
|
||||||
if (opts.c) categories = opts.c.split(/[,\s]/)
|
|
||||||
categories = categories.collect { Category.toCategory(it) }
|
|
||||||
|
|
||||||
// build issue list
|
|
||||||
issuedb = new Project(new File('.'),
|
|
||||||
new Filter('categories': categories,
|
|
||||||
'priority': (opts.p ? opts.p.toInteger() : 9),
|
|
||||||
'projects': (opts.r ? opts.r.toLowerCase().split(/[,\s]/).asType(List.class) : []),
|
|
||||||
'ids': (opts.i ? opts.i.split(/[,\s]/).asType(List.class) : []),
|
|
||||||
'acceptProjects': (opts.s || !opts.S)))
|
|
||||||
|
|
||||||
// list first
|
|
||||||
if (opts.l) issuedb.list('verbose': opts.v)
|
|
||||||
|
|
||||||
// change priority second
|
|
||||||
//else if (opts.cp)
|
|
||||||
|
|
||||||
// change category third
|
|
||||||
//else if (opts.cc)
|
|
||||||
|
|
||||||
// new entry last
|
|
Loading…
x
Reference in New Issue
Block a user