131 Commits

Author SHA1 Message Date
Patrick Georgi
945429abf0 Provide MD5 value of downloads to HTTP client
Content-MD5 is a HTTP header to provide end-to-end integrity checks
(see RFC2616, 14.15). This doesn't protect against malicious
modifications, but against transmissions errors and storage errors
on the server.

The change also removes one redirect when downloading files.
2011-07-24 22:12:36 +02:00
William MARTIN
a016bcb51b Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-07-05 11:31:05 +02:00
William MARTIN
f2b1ce795c Fix issue 247 : cron overwrites authorized_keys during cron run 2011-07-05 11:30:23 +02:00
Thomas Keller
3a8c56acc4 Postgres needs a VARCHAR cast, which MySQL doesn't understand, of
course. *sigh*
2011-07-01 13:35:43 +02:00
Thomas Keller
7b2552f940 Postgres (and probably others as well) needs an explicit char cast. 2011-06-30 00:25:29 +02:00
Thomas Keller
324b202215 Fix the rendering of issue changes in a mail template and the issue feed fragment. 2011-06-29 17:41:18 +02:00
Loïc d'Anterroches
2c2da6082a Fixed stupid missing semicolon. 2011-06-29 14:41:57 +02:00
Loïc d'Anterroches
dd3fbbd7e4 Fixes to support older PHP versions. 2011-06-29 14:30:17 +02:00
William MARTIN
9bbcd571ec Merge branch 'feature.issue-summary' into develop 2011-06-20 11:37:26 +02:00
William MARTIN
bbc185bf3b Add unit test for IDF_Project::getIssueCountByOwner 2011-06-20 11:34:42 +02:00
Thomas Keller
d1bcdcda20 Fix the mtn getChanges() test. 2011-06-17 23:50:35 +02:00
William MARTIN
6d55602ef3 Add IDF_Project::getIssueCountByOwner and use it into IDF_Views_Issue::summary 2011-06-15 17:30:23 +02:00
William MARTIN
6e7c9f7c4b Use css instead of   2011-06-15 17:29:29 +02:00
William MARTIN
5427aab456 Change "ifnull" sql function to "coalesce" which is supported by postgresql 2011-06-15 13:52:58 +02:00
Thomas Keller
4879d64989 If git's author name does not contain valid utf-8 bytes, skip the author
lookup in the database, which would otherwise only bring up errors.
2011-06-15 13:50:02 +02:00
William MARTIN
dab8ea63fc Mark string for translation 2011-06-15 11:35:30 +02:00
William MARTIN
b03d7a04a0 improve rendering of 0% bar 2011-06-15 11:30:11 +02:00
William MARTIN
ef5b93e3f7 Fix the special case of a empty issue tracker, for the issue summary. 2011-06-15 11:18:41 +02:00
William MARTIN
69ae1c08ef Add an sub-tab under Issue to add a summury view 2011-06-15 09:11:47 +02:00
Thomas Keller
8e4f828cc6 Spelling. 2011-06-13 12:43:39 +02:00
Thomas Keller
c4f92f4569 Access all private methods in a non-static way, now that we have a instance-dependent _diagnoseProblem() method 2011-06-13 12:23:22 +02:00
Thomas Keller
c4d2b99656 Wrong object to call commit() on... 2011-06-13 01:59:21 +02:00
Thomas Keller
d4fe88adab Disable the fixed context bar if the content is already to big 2011-06-12 17:59:43 +02:00
Thomas Keller
69d0e8313a Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-06-11 00:48:38 +02:00
Thomas Keller
11a234e135 Fix the branch links users of the Subversion frontend get when they enter
a wrong revision and only display this list if there are any branches
available for all SCMs.
2011-06-11 00:47:54 +02:00
Thomas Keller
2f30e4e2f6 Fix a regression introduced with commit 20c3f14cc: If we can read from a process'
pipe doesn't mean the exit code of the process in question is zero, this is
actually what pclose() returns.
2011-06-11 00:44:32 +02:00
Thomas Keller
118ca9f11f Now that IDF_Scm::getChanges() is implemented for all SCMs, there is no need for the try-catch anymore. 2011-06-10 23:40:58 +02:00
Thomas Keller
24fc41ee0d XML node access didn't work and as such renames and copies weren't properly detected. 2011-06-10 23:40:22 +02:00
William MARTIN
c00dbac5e0 Merge branch 'feature.download-md5' into develop 2011-06-10 09:26:20 +02:00
William MARTIN
d7857c5126 Rename the migration script 2011-06-10 09:25:17 +02:00
Thomas Keller
ac6be0d3c0 Implement IDF_Scm::getChanges() for Subversion (closes issue 622) 2011-06-10 02:23:54 +02:00
Thomas Keller
7ff6f09f67 We can actually differentiate between copies and renames in Hg, so lets
add support for another change type, 'copies'. The previous implementation
for Hg was also slightly flawed in the way that it mixed sources with
targets.
2011-06-10 01:34:33 +02:00
Thomas Keller
00b576c5a3 Merge branch 'feature.issue-links' into develop 2011-06-10 00:39:39 +02:00
Thomas Keller
2a33510c96 \w doesn't match -, so better use [^)] to match server names 2011-06-06 23:24:00 +02:00
Thomas Keller
d1f79d906d Do not try to symlink the same file twice (fixes issue 695) 2011-06-06 23:18:06 +02:00
Thomas Keller
aa043f14ac Two occurrences forgotten 2011-06-06 23:01:25 +02:00
Thomas Keller
638b28399e Fix issues 695 and 697. Still, public keys aren't added to monotone
databases for some weird reason, so issue 696 is still open.
2011-06-05 02:37:47 +02:00
Thomas Keller
1d86f036a3 Add a warning to not configure a global key for all monotone
instances in usher.conf.
2011-06-05 01:31:21 +02:00
Thomas Keller
2f6e0f0a22 Include examples how to setup ACLs for different platforms. 2011-06-05 01:13:00 +02:00
Thomas Keller
1b1b00a10c The server list no longer renders a bogus server entry in case no
monotone server has been configured yet in the connected usher instance.
Also display a short info text if the server or connection list for
a running monotone server is empty.
2011-06-04 23:15:58 +02:00
Thomas Keller
8693418d39 Revert "Improve error handling and reporting (partially resolves issue 695)"
This reverts commit 8ff15368ce.
2011-06-04 01:14:22 +02:00
Thomas Keller
8ff15368ce Improve error handling and reporting (partially resolves issue 695) 2011-06-04 01:03:30 +02:00
Thomas Keller
32cde534bd Fix some errors in the German translation and unify some of the strings.
Thanks to Daniel Steudler <steudlerdaniel@gmail.com> for some of the
pointers. Fixes issue 694.
2011-06-04 00:31:12 +02:00
Thomas Keller
c0e26133bd Keep the context area in the view if a view scrolls down several pages. 2011-06-02 02:04:52 +02:00
Thomas Keller
592c2ff9ff Several f'ups in hg's parseLog() method 2011-06-02 01:21:32 +02:00
Thomas Keller
30efd0a2db Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-06-02 00:55:17 +02:00
Thomas Keller
20c3f14cc8 git and hg diff views did not show empty context lines, a regression
from the commit(s) from issue 633. The diff parser assumed a properly
formatted diff that denotes empty context lines with a single space in
the first column. This single space however was missing, because the
hg and git backends got the diff through PHP's exec() function and
this returns already line-splitted output, but - and this is the actual
problem - removes trailing whitespace at the end of each line, essentially
making " \n" only "\n". When splitting this string now again with
PREG_SPLIT_NO_EMPTY the empty line was completely lost in the diff output.

To make it clear that an empty line does not mark a context line now, but
should stop the diff parsing, the Diff parser now also defaults to 'false'
as line type.

This commit fixes issue 688.
2011-06-02 00:48:38 +02:00
Thomas Keller
80313c88c8 Properly reverse-sort git's tag list again; the rsort on the original output
of the command looked bogus: since each tag ref is prefixed by an iso date and
since commit 94da55d1 by hash, the whole string was of course sorted by this
date and later hash, but not the tag name. This should now make more sense.
2011-06-02 00:38:14 +02:00
Thomas Keller
cab1c09ffc Note that issue 559 has been fixed with the fix for issue 686. 2011-06-02 00:08:13 +02:00
William MARTIN
c421919092 Fix php syntax 2011-06-01 11:20:03 +02:00
William MARTIN
d350876bc1 Update allowed attributes in the Markdown Prefilter, to be less strict.
Fix issue 578
2011-06-01 10:10:01 +02:00
William MARTIN
de09c8af56 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-05-31 15:40:14 +02:00
William MARTIN
998f4576fe Fix div collision 2011-05-31 15:39:46 +02:00
William MARTIN
06c57f7da6 Set the SQL type to VARCHAR(32)
Process the md5 of each file during the migrationUpdate all IDF_Upload object to process their md5 during the migration
2011-05-31 14:53:44 +02:00
William MARTIN
4d5418a601 Fix migration methods name 2011-05-31 14:01:39 +02:00
William MARTIN
95cc7f627f Process a md5 on the uploaded file, and display it in the per file view.
- The uploader can check that the uploaded file is correct
- The downloader can check his download too
2011-05-31 13:58:12 +02:00
Thomas Keller
2aab4eea3b Apply (and adapt) the patch from issue 364, which should fix the issue. 2011-05-31 13:41:37 +02:00
Thomas Keller
5bbff9f5a6 Rename the "Go to revision" button in the SVN views to "Switch", so it
doesn't break into the next line.
2011-05-31 13:39:55 +02:00
Thomas Keller
b5fcf1636a String improvements. 2011-05-31 13:34:28 +02:00
Thomas Keller
13012be5d7 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-05-31 13:14:21 +02:00
Thomas Keller
ca2ef814fb Add support for the display of monotone node attributes.
(also fix the way the attributes view is displayed, i.e. do not
 use single strings, but one string in context which is much easier
 to translate)
2011-05-31 13:11:55 +02:00
William MARTIN
b9407f6aee Add some nobr, to keep the text formated when the message is long 2011-05-31 11:06:39 +02:00
Thomas Keller
9bcb5f9456 Fix a PHP notice / Pluf exception in case any issue type field is cleared. 2011-05-31 10:51:24 +02:00
Thomas Keller
f412099f69 Fix whitespace issues in the timeline. 2011-05-30 14:48:36 +02:00
Thomas Keller
0aa5999bb3 Finalize ticket relations (closes issue 638)
- IssueUpdate.php: use dynamically set field validators for dynamically
  created fields; let relation_type0 and relation_issue0 exist at any time;
  check the validity of a user selection and combine the various input fields
  if possible; do the database updates for links; change the "change" format
  for labels to a more precise structure and no longer trust on a leading
  dash for removed labels
- IssueCreate.php: change the validator calls and field names
- Issue.php (getGroupedRelatedIssues): make it possible to return only a
  flat list of integers for easier processing
- 17AddIssueRelations.php: migrate the previous serialized "changes" format
  for issue comments to the new, more structured format (up and down)
- js-autocomplete.html: add support for multiple input fields
- view.html: output relation changes and wrap the related issues stanzas into
  paragraphs
- NEWS.mdtext: note the addition and the need for a specific version of Pluf
2011-05-30 14:02:10 +02:00
Thomas Keller
16dda0743c Basic storage of relations for new issues has been done; the relations
are also properly displayed at the left side in the issue's detail view.
2011-05-28 23:48:00 +02:00
Thomas Keller
d079838818 Improve a translation 2011-05-28 01:36:25 +02:00
Thomas Keller
81ce4688df Let the SVN command line client not store the login credentials we give him. 2011-05-28 01:05:10 +02:00
Thomas Keller
ee33cc1832 Address files by name rather than ID in the downloads section (issue 686) 2011-05-28 00:48:24 +02:00
Thomas Keller
82bb18fe10 Merge branch 'release-1.1' into develop 2011-05-26 10:51:16 +02:00
Thomas Keller
09979b8551 Rewrite log parsing in Mercurial and fix whitespace bugs on the way:
- tags and branches with spaces are now properly parsed (issue 663)
- use --style instead of --template option of hg to include much more
  output for the log command; use that to query the parent revisions of
  a revision (if any) and also to query the actual changes of a revision
- make the log parser much more robust towards changes in the "header"
  of the log output
2011-05-25 23:26:14 +02:00
Thomas Keller
5b82efa0be Fix a couple of issues with our key parsing / validating code.
- be explicit and expect only ssh-dss or ssh-rsa keys
- allow any character (even line breaks and whitespace) in the optional comment,
  but shrink all of them to simple spaces (fixes issue 679)
- test the newly uploaded key against existing keys only by the base key data,
  not the fully uploaded string (that might contain a changed comment line or
  the like) to avoid duplicates; also only check the keys of the user for
  duplicates, not all existing keys in the forge (if for whatever reason two
  user accounts share a key)
2011-05-25 02:13:50 +02:00
Thomas Keller
8502a36481 Mark two new strings in the latest updates view for translation;
prettify the RSS icon display somewhat.
2011-05-16 23:49:08 +02:00
Thomas Keller
bcba64b2a1 Basic model files added. 2011-05-10 17:22:32 +02:00
Thomas Keller
e40d922eef Add two targets to easily install and update the IDF database 2011-05-10 17:21:56 +02:00
Thomas Keller
7e226b43d3 More work on the issue relation infrastructure
- actually query data for the incoming query
- exclude the current issue from being linked with itself
- allow multiple issues to be given in the second input field
- add the form fields to the ticket update view as well
2011-05-10 16:21:29 +02:00
Thomas Keller
9171bfd1ab Start with issue 638 (issue links); nothing workable yet. 2011-05-09 13:52:09 +02:00
Thomas Keller
be4774c95c Mark two strings for translation. 2011-05-06 14:04:08 +02:00
William MARTIN
9644784a79 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-05-04 11:22:50 +02:00
William MARTIN
1940d5c0b5 Fix issue 671 : Update the SSH Key preg pattern 2011-05-04 11:22:24 +02:00
Thomas Keller
7c7e3cd1f1 Rework idf.php-dist a bit more:
- move "Binary section" into "Path section"
- make individual sections more prominent and therefor
  easier to grasp / scan for
- fix the language and expand the explanations for a
  couple of items
- remove the 'debug_scm' configuration variable
  (it is used nowhere in the source and just confuses people)
- update the copyright
2011-04-28 23:53:15 +02:00
William MARTIN
3e2f95a152 Break too long line
Add space between section
2011-04-28 15:43:09 +02:00
William MARTIN
92de88ba13 Rewrite of the idf.php-dist file
- Add example for each mail and cache backend
- Add major part of option use in each Scm backend with description
2011-04-28 15:12:00 +02:00
William MARTIN
02d0f0923e Update the NEWS files 2011-04-27 15:09:04 +02:00
Thomas Keller
765a86ba90 Fix an URL in the RSS feed 2011-04-27 15:01:34 +02:00
William MARTIN
34309e34c3 Enhancement visibility of the RSS feed in the timeline view 2011-04-27 14:39:39 +02:00
Thomas Keller
2176d1cde2 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-04-27 00:08:10 +02:00
Thomas Keller
45d53e8d21 Merge branch 'feature.better-home' into develop 2011-04-27 00:07:40 +02:00
Thomas Keller
b36b8e3afb Final adjustions to the project logo code
- remove the question mark from the default logo for simplification,
  add a soft drop shadow to make the logo more visible on not so light
  backgrounds
- display the project logo and the lock icon in the project list dropdown
- re-position the project title and display the lock icon (if needed)
  on top of the main logo
The code now works best with uploaded logos of 32x32px^2; smaller logos
will be downsampled and repositioned on a best breed basis.
2011-04-27 00:03:44 +02:00
Thomas Keller
801af66a4e Apparently header() does kind of work for php-cli, but of course breaks horribly.
Luckily Pluf has a little knob (IN_UNIT_TESTS) that can prevent this breakage.
2011-04-19 11:07:58 +02:00
Thomas Keller
df6ffdf420 Three more test cases for the mtn interface added
- add tests for getTree(), getChanges() and isCommitLarge()
- anonymize the test data somewhat
- return false instead of null for unknown revisions given to getChanges()
2011-04-15 00:54:11 +02:00
Thomas Keller
b3368071ac Continue with the mtn interface tests
- test getRepositorySize() with a test file
- implement tests for inTags(), inBranches(), getFile(),
  getCommit() and getExtraProperties()
- mark the static methods as untestable
2011-04-14 00:48:36 +02:00
Thomas Keller
67b80ee11c Continue with the mtn interface tests
- getPathInfo(), disambiguateRevision() and validateRevision() are done
- we no longer need to check / skip a format_version stanza for the extended
  manifest (there is no such stanza outputted)
2011-04-12 23:47:44 +02:00
William MARTIN
dc31155de1 Second pass of code review 2011-04-11 15:37:40 +02:00
Thomas Keller
0bae69908b Spelling 2011-04-07 22:40:32 +02:00
Thomas Keller
47a077bc82 Merge branch 'feature.better-home' of projects.ceondo.com:indefero into feature.better-home 2011-04-07 22:38:40 +02:00
William MARTIN
836ff71364 Update code to fix thomas review's 2011-04-06 15:33:26 +02:00
William MARTIN
0afa07b2bd Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-04-06 12:01:04 +02:00
William MARTIN
4ee3d471fe Update the form validation of IDF_Form_ReviewFileComment.
Now we can add a general comment without per file comment.
2011-04-06 12:00:55 +02:00
Thomas Keller
29c7fed81b Merge branch 'develop' of git://projects.ceondo.com/indefero into develop 2011-04-06 03:01:40 +02:00
Thomas Keller
fb62061e5a Started with a unit test for the monotone interface.
Main test infrastructure is there, still lots of functionality left
for testing. Fixed a possible bug in the SCM interface already:
Pluf_HTTP_Response_NotFound needs a request instance as ctor argument,
which we don't have at this point, therefor we just throw an exception.
2011-04-06 02:59:26 +02:00
William MARTIN
9b92b7139f Fix copyright 2011-04-05 13:20:55 +02:00
William MARTIN
5ea4b02205 Update copyrigt 2011-04-02 21:37:07 +02:00
Thomas Keller
12d3eef3d1 monotone actually requires interface_version 13.0 or higher because of the extended manifest usage 2011-04-02 15:40:18 +02:00
Thomas Keller
576c06ffaf Merge branch 'feature.better-home' of git://projects.ceondo.com/indefero into feature.better-home 2011-04-02 00:17:51 +02:00
William MARTIN
352dc3e179 Add IDF_Form_ProjectConf
Update template
2011-04-01 16:05:32 +02:00
William MARTIN
aa164936f4 Remove commented code 2011-04-01 14:19:07 +02:00
William MARTIN
9a93acd1a5 Update the admin template 2011-04-01 14:17:56 +02:00
William MARTIN
587aa11cda Update the index template 2011-04-01 14:14:30 +02:00
William MARTIN
d04ecd60c4 Add default logo for project without one 2011-04-01 14:13:42 +02:00
Thomas Keller
ecef510f78 Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-04-01 11:18:01 +02:00
Thomas Keller
4976c20935 Its validateRevision, not isValidRevision, here as well 2011-04-01 11:17:21 +02:00
Thomas Keller
5553c37ccd Merge branch 'release-1.1' into develop 2011-04-01 11:17:06 +02:00
Thomas Keller
aa68fe3485 Note fix for issue 655. 2011-03-30 00:19:18 +02:00
Thomas Keller
e408fe8733 Make the function static again; this change silently slipped through. 2011-03-30 00:17:35 +02:00
Thomas Keller
836986462a Add Stewart to AUTHORS. 2011-03-30 00:13:50 +02:00
Stewart Platt
51c6cdb20d Only display those filter options for items the user actually has access to
(fixes issue 655)
2011-03-30 00:12:07 +02:00
Thomas Keller
766232f29b Add missing license header. 2011-03-30 00:00:22 +02:00
Thomas Keller
2ed021f30b Merge branch 'develop' of projects.ceondo.com:indefero into develop 2011-03-28 18:00:23 +02:00
Thomas Keller
899fe561df Merge branch 'release-1.1' into develop 2011-03-28 17:59:08 +02:00
Thomas Keller
1d89cec2cf Merge branch 'release-1.1' into develop 2011-03-28 01:26:20 +02:00
Thomas Keller
39ba5b37ef Ignore a couple of files for code coverage that should not be covered;
add a simle run-tests script that steals some code from photon to
return the code coverage at the end of the test execution
(we're only at about 8% - lots of work left...)
2011-03-25 00:29:50 +01:00
Thomas Keller
002fa05c7f Merge branch 'release-1.1' into develop 2011-03-25 00:14:26 +01:00
Thomas Keller
30900f7196 monotone zip archive entries now all carry the revision date as mtime (issue 645);
add a test case for the zip render response that works with and without PHP's
zip extension
2011-03-24 23:54:52 +01:00
Thomas Keller
b753cf0837 Fix a coment. 2011-03-24 01:19:05 +01:00
Thomas Keller
53ab5b6aff Expand the bootstrap script to setup an empty IDF environment. 2011-03-24 00:41:22 +01:00
Thomas Keller
78a0402351 Prepare the Stdio class for easier testing.
- create an interface that describes the basic methods
- let the real stdio class implement this interface
- inject the stdio instance into IDF_Scm_Monotone and do not
  create it in the constructor
- ensure in IDF_Scm_Monotone_ZipRender that we get the proper
  constructor arguments
On a slighly unrelated note, make _getAuthOptions() in the stdio
implementation private.
2011-03-23 00:47:17 +01:00
Thomas Keller
5b5705fe90 Add a unit test for monotone's basicio parser and compiler.
Also note a couple of quirks and be less strict (for now) when it
comes to hash parsing and stanza lines without values.
2011-03-23 00:26:26 +01:00
Thomas Keller
f08b5c5e3f Note syncmonotone.mdtext in INSTALL.mdtext 2011-03-20 14:19:53 +01:00
Thomas Keller
aa87acd432 Start 1.2 development. 2011-03-20 13:48:49 +01:00
Thomas Keller
7af7ef8357 Merge branch 'release-1.1' into develop 2011-03-20 13:46:45 +01:00
199 changed files with 4754 additions and 946 deletions

3
.gitignore vendored
View File

@@ -9,3 +9,6 @@ indefero-*.zip
src/IDF/conf/path.php src/IDF/conf/path.php
.tx/config .tx/config
src/IDF/locale/idf.pot.bak src/IDF/locale/idf.pot.bak
test/test.db
test/tmp
test/config.php

View File

@@ -12,6 +12,7 @@ Much appreciated contributors (in alphabetical order):
Brian Armstrong <brianar> Brian Armstrong <brianar>
Charles Melbye <charlie@yourwiki.net> Charles Melbye <charlie@yourwiki.net>
Ciaran Gultnieks <ciaran@ciarang.com> Ciaran Gultnieks <ciaran@ciarang.com>
Daniel Steudler <steudlerdaniel@gmail.com>
David Feeney <davidf> David Feeney <davidf>
Denis Kot <denis.kot@gmail.com> - Russian translation Denis Kot <denis.kot@gmail.com> - Russian translation
Dmitry Dulepov <dmitryd> Dmitry Dulepov <dmitryd>
@@ -31,6 +32,7 @@ Much appreciated contributors (in alphabetical order):
Raphaël Emourgeon <raphael> Raphaël Emourgeon <raphael>
Samuel Suther <info@suther.de> - German translation Samuel Suther <info@suther.de> - German translation
Sindre R. Myren <sindrero@stud.ntnu.no> Sindre R. Myren <sindrero@stud.ntnu.no>
Stewart Platt <stew@futurete.ch>
Thomas Keller <me@thomaskeller.biz> - Monotone support Thomas Keller <me@thomaskeller.biz> - Monotone support
Vladimir Solomatin <slash> Vladimir Solomatin <slash>
William Martin <william.martin@lcpc.fr> William Martin <william.martin@lcpc.fr>

View File

@@ -4,6 +4,12 @@ The installation of InDefero is composed of 2 parts, first the
installation of the [Pluf framework](http://www.pluf.org) and second, installation of the [Pluf framework](http://www.pluf.org) and second,
the installation of InDefero by itself. the installation of InDefero by itself.
## PHP modules for indefero
Indefero need the GD module for PHP. It's named "php5-gd" in debian.
$ apt-get install php5-gd
## Recommended Layout of the Files ## Recommended Layout of the Files
If your server document root is in `/var/www` a good thing is to keep If your server document root is in `/var/www` a good thing is to keep
@@ -126,6 +132,7 @@ The documentation is available in the `doc` folder.
* Subversion: `doc/syncsvn.mdtext`. * Subversion: `doc/syncsvn.mdtext`.
* Mercurial: `doc/syncmercurial.mdtext`. * Mercurial: `doc/syncmercurial.mdtext`.
* Git: `doc/syncgit.mdtext`. * Git: `doc/syncgit.mdtext`.
* Monotone: `doc/syncmonotone.mdtext`
## For the Apache Webserver Users ## For the Apache Webserver Users

View File

@@ -37,6 +37,10 @@ help:
@printf "\tpo-push - Send the all PO files to the transifex server.\n" @printf "\tpo-push - Send the all PO files to the transifex server.\n"
@printf "\tpo-pull - Get all PO files from the transifex server.\n" @printf "\tpo-pull - Get all PO files from the transifex server.\n"
@printf "\tpo-stats - Show translation statistics of all PO files.\n" @printf "\tpo-stats - Show translation statistics of all PO files.\n"
@printf "\nMisc Rules :\n";
@printf "\tdb-install - Install the database schema.\n"
@printf "\tdb-update - Update the database schema.\n"
# #
# Internationalization rule, POT & PO file manipulation # Internationalization rule, POT & PO file manipulation
@@ -139,3 +143,8 @@ po-stats:
> indefero-$(@:-zipfile=)-`git log $(@:-zipfile=) -n 1 \ > indefero-$(@:-zipfile=)-`git log $(@:-zipfile=) -n 1 \
--pretty=format:%h`.zip --pretty=format:%h`.zip
db-install:
@cd src && php $(PLUF_PATH)/migrate.php --conf=IDF/conf/idf.php -a -d -i
db-update:
@cd src && php $(PLUF_PATH)/migrate.php --conf=IDF/conf/idf.php -a -d

View File

@@ -1,3 +1,47 @@
# InDefero 1.2 - xxx xxx xx xx:xx 2011 UTC
ATTENTION: You need Pluf [324ae60b](http://projects.ceondo.com/p/pluf/source/commit/324ae60b)
or newer to properly run this version of Indefero!
## New Features
- Indefero's issue tracker can now bi-directionally link issues with variable, configurable
terms, such as "is related to", "is blocked by" or "is duplicated by" (issue 638)
- Mercurial source views now show parent revisions (if any) and detailed change information
- Subversion source views now show detailed change information (issue 622)
- File download URLs now contain the file name rather than the upload id; old links still work though (issues 559 and 686)
- Display monotone file and directory attributes in the tree and file view
(needs a monotone with an interface version of 13.1 or newer)
- The context area is now kept in view when a page scrolls down several pages
## Bugfixes
- The SVN interface acts more robust if an underlying repository has been restructured (issue 364)
- monotone zip archive entries now all carry the revision date as mtime (issue 645)
- Timeline only displays filter options for items a user has actually access to (issue 655)
- The log, tags and branches parsers for Mercurial are more robust now (issue 663)
- Fix SSH public key parsing issues and improve the check for existing, uploaded keys (issue 679)
- Diff views now show empty context lines for git and hg again (issue 688)
- Let the SVN command line client not store the login credentials we give him as arguments
- The usher section in the forge administration no longer displays a bogus
server enty in case no monotone server is configured in the connected
usher instance
- Prevent a timeout from popping up when Usher is restarted (issue 695)
- The SyncMonotone plugin now cleans up partial artifacts it created during the addition of
a new project or monotone key, in case an error popped up in the middle (issue 697)
- Better error detection and reporting in the SyncMonotone plugin
ATTENTION: This needs Pluf 46b7f251 or newer!
- Fix the branch links users of the Subversion frontend get when they enter a wrong revision
and only display this list if there are any branches available for all SCMs
- If git's author name is not encoded in an UTF-8 compatible encoding, skip the author lookup,
as we have no information what the author string is actually encoded in
## Documentation
- The documentation on the setup of the monotone plugin has been improved.
## Translations
# InDefero 1.1.2 - Thu May 26 07:42:25 2011 UTC # InDefero 1.1.2 - Thu May 26 07:42:25 2011 UTC
## Bugfixes ## Bugfixes

View File

@@ -25,7 +25,7 @@ If you install monotone from source (<http://monotone.ca/downloads.php>),
please follow the `INSTALL` document which comes with the software. please follow the `INSTALL` document which comes with the software.
It contains detailed instructions, including all needed dependencies. It contains detailed instructions, including all needed dependencies.
## Choose your indefero setup ## Choose your indefero (IDF) setup
The monotone plugin can be used in several different ways: The monotone plugin can be used in several different ways:
@@ -112,14 +112,40 @@ The monotone plugin can be used in several different ways:
^D ^D
$ chmod 600 usher.conf $ chmod 600 usher.conf
**ATTENTION:** Do _not_ configure a default monotone server key in `usher.conf`,
otherwise the individual server key that IDF creates for each project is
not used and this could cause problems.
Your indefero www user needs later write access to `usher.conf` and Your indefero www user needs later write access to `usher.conf` and
`projects/`. There are two ways of setting this up: `projects/`. There are two ways of setting this up:
* Make the usher user the web user, for example via Apache's `suexec` * Make the usher user the web user, for example via Apache's `suexec`.
* Use acls, like this: This is however a bit clumsy.
* Preferred: Use Access Control Lists (ACLs), like this:
#
# Linux
#
$ setfacl -m u:www:rw usher.conf $ setfacl -m u:www:rw usher.conf
$ setfacl -m d:u:www:rwx projects/ $ setfacl -m d:u:www:rwx projects/
$ setfacl -m d:u:usher:rwx projects/
#
# FreeBSD
#
$ setfacl -m user:www:rw::allow usher.conf
$ setfacl -m user:www:rwxp:fd:allow projects/
$ setfacl -m user:usher:rwxp:fd:allow projects/
#
# Mac OS X
#
chmod +a '_www allow read,write' usher.conf
chmod +a '_www allow read,write,delete,add_file,add_subdirectory,file_inherit,directory_inherit' projects/
chmod +a 'usher allow read,write,delete,add_file,add_subdirectory,file_inherit,directory_inherit' projects/
In each example's last line, `usher` is the user which is executing
the usher instance. **It is very important to add this line, otherwise
usher won't be able to read and write into the initial file system
setup IDF creates!**
5. Wrap a daemonizer around usher, for example supervise from daemontools 5. Wrap a daemonizer around usher, for example supervise from daemontools
(<http://cr.yp.to/damontools.html>): (<http://cr.yp.to/damontools.html>):

173
logo/no_logo.svg Normal file
View File

@@ -0,0 +1,173 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="no_logo.svg"
inkscape:version="0.47 r22583"
id="svg2985"
height="32"
width="32"
version="1.1"
inkscape:export-filename="/Users/tommyd/Entwicklung/indefero/www/media/idf/img/no_logo.png"
inkscape:export-xdpi="89.989998"
inkscape:export-ydpi="89.989998">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1440"
inkscape:window-height="852"
id="namedview9"
showgrid="false"
inkscape:zoom="16.0625"
inkscape:cx="8.5507561"
inkscape:cy="16.122403"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="g2847"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
orientation="1,0"
position="16,25.836575"
id="guide3752" />
<sodipodi:guide
orientation="0,1"
position="-18.677042,16"
id="guide3754" />
</sodipodi:namedview>
<defs
id="defs2987">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective13" />
<inkscape:perspective
id="perspective2863"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3676"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3717"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<filter
inkscape:collect="always"
id="filter3816"
x="-0.14434362"
width="1.2886872"
y="-0.11562817"
height="1.2312563">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="1.1799243"
id="feGaussianBlur3818" />
</filter>
</defs>
<metadata
id="metadata2990">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="shadow"
style="display:inline"
sodipodi:insensitive="true">
<g
transform="translate(0.44042901,0.78704792)"
id="g2847-8"
style="opacity:0.79710143;fill:#000000;stroke:#000000;stroke-opacity:1;filter:url(#filter3816)">
<g
id="g3838-0"
style="fill:#000000;stroke:#000000;stroke-opacity:1" />
<g
id="g2401-2"
transform="matrix(0.21219597,0,0,0.21219597,-70.751966,-27.73328)"
style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:2.4000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:export-filename="/home/loa/Projects/indefero/logo/powered-by-indefero.png"
inkscape:export-xdpi="12.330909"
inkscape:export-ydpi="12.330909">
<path
id="path2383-4"
d="m 396.19089,173.14471 c -7.67621,0.80661 -14.40195,5.39406 -19.58101,10.89131 -7.23597,7.88004 -11.69742,18.07908 -13.32198,28.60362 -1.7236,11.28173 -0.25925,23.20635 5.07686,33.37271 3.78607,7.24384 9.53161,13.92339 17.29701,16.96772 3.86478,1.53937 8.98362,1.03284 11.67912,-2.41036 2.64357,-3.5671 2.69463,-8.234 2.85756,-12.48867 0.045,-7.61054 -0.54749,-15.25544 0.45618,-22.83193 0.87131,-9.50623 4.03944,-18.56751 6.71612,-27.66851 1.16242,-4.44333 2.25094,-9.02808 1.97499,-13.64988 -0.48817,-4.62476 -3.58059,-9.31042 -8.2964,-10.4067 -1.57489,-0.44882 -3.23412,-0.48948 -4.85845,-0.37931 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
<path
id="path2391-8"
d="m 433.14691,149.28687 c 7.2059,2.76589 12.51512,8.93778 16.09494,15.58815 4.94991,9.48434 6.61962,20.49058 5.46486,31.07695 -1.25505,11.34342 -5.75582,22.48271 -13.54134,30.92159 -5.53192,6.01709 -12.81048,10.98198 -21.09918,11.91276 -4.13154,0.4866 -8.94486,-1.32748 -10.65734,-5.35104 -1.63027,-4.12976 -0.4717,-8.65084 0.47212,-12.80269 1.92628,-7.36287 4.47721,-14.59393 5.4687,-22.17201 1.61875,-9.40784 0.90381,-18.98034 0.67386,-28.46402 0.0272,-4.59278 0.1624,-9.30303 1.62515,-13.69592 1.66851,-4.34082 5.86829,-8.06645 10.70716,-7.90484 1.63738,-0.0259 3.25061,0.36424 4.79107,0.89107 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="logo"
style="display:inline">
<g
id="layer1"
transform="translate(-0.06540759,0.09444087)">
<g
id="g2847">
<g
id="g3838" />
<g
id="g2401"
transform="matrix(0.21219597,0,0,0.21219597,-70.751966,-27.73328)"
style="fill:#e6e6e6;fill-opacity:1;stroke:#a0a0a0;stroke-width:2.4000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
inkscape:export-filename="/home/loa/Projects/indefero/logo/powered-by-indefero.png"
inkscape:export-xdpi="12.330909"
inkscape:export-ydpi="12.330909">
<path
id="path2383"
d="m 396.19089,173.14471 c -7.67621,0.80661 -14.40195,5.39406 -19.58101,10.89131 -7.23597,7.88004 -11.69742,18.07908 -13.32198,28.60362 -1.7236,11.28173 -0.25925,23.20635 5.07686,33.37271 3.78607,7.24384 9.53161,13.92339 17.29701,16.96772 3.86478,1.53937 8.98362,1.03284 11.67912,-2.41036 2.64357,-3.5671 2.69463,-8.234 2.85756,-12.48867 0.045,-7.61054 -0.54749,-15.25544 0.45618,-22.83193 0.87131,-9.50623 4.03944,-18.56751 6.71612,-27.66851 1.16242,-4.44333 2.25094,-9.02808 1.97499,-13.64988 -0.48817,-4.62476 -3.58059,-9.31042 -8.2964,-10.4067 -1.57489,-0.44882 -3.23412,-0.48948 -4.85845,-0.37931 z"
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#a0a0a0;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
<path
id="path2391"
d="m 433.14691,149.28687 c 7.2059,2.76589 12.51512,8.93778 16.09494,15.58815 4.94991,9.48434 6.61962,20.49058 5.46486,31.07695 -1.25505,11.34342 -5.75582,22.48271 -13.54134,30.92159 -5.53192,6.01709 -12.81048,10.98198 -21.09918,11.91276 -4.13154,0.4866 -8.94486,-1.32748 -10.65734,-5.35104 -1.63027,-4.12976 -0.4717,-8.65084 0.47212,-12.80269 1.92628,-7.36287 4.47721,-14.59393 5.4687,-22.17201 1.61875,-9.40784 0.90381,-18.98034 0.67386,-28.46402 0.0272,-4.59278 0.1624,-9.30303 1.62515,-13.69592 1.66851,-4.34082 5.86829,-8.06645 10.70716,-7.90484 1.63738,-0.0259 3.25061,0.36424 4.79107,0.89107 z"
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:#a0a0a0;stroke-width:2.4000001;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -12,4 +12,16 @@
<directory>test/IDF/</directory> <directory>test/IDF/</directory>
</testsuite> </testsuite>
</testsuites> </testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/IDF</directory>
<exclude>
<directory suffix=".php">src/IDF/Tests</directory>
<directory suffix=".php">src/IDF/conf</directory>
<file>src/IDF/version.php</file>
</exclude>
</whitelist>
</filter>
</phpunit> </phpunit>

14
run-tests Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env php
<?php
$xmlfile = dirname(__FILE__) .'/test/report.xml';
passthru('phpunit --coverage-clover='.$xmlfile);
$xml = simplexml_load_string(file_get_contents($xmlfile));
unlink($xmlfile);
printf(
'>>> code coverage %s/%s (%s%%)'."\n",
$xml->project->metrics['coveredstatements'],
$xml->project->metrics['statements'],
round(($xml->project->metrics['coveredstatements']/(float)$xml->project->metrics['statements']) * 100.0, 2)
);

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
# #
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -4,7 +4,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2010 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -101,7 +101,7 @@ class IDF_Diff
$files[$current_file]['chunks'][] = array(); $files[$current_file]['chunks'][] = array();
while ($i < $diffsize && ($addlines >= 0 || $dellines >= 0)) { while ($i < $diffsize && ($addlines >= 0 || $dellines >= 0)) {
$linetype = $this->lines[$i] != '' ? $this->lines[$i][0] : ' '; $linetype = $this->lines[$i] != '' ? $this->lines[$i][0] : false;
switch ($linetype) { switch ($linetype) {
case ' ': case ' ':
$files[$current_file]['chunks'][$current_chunk][] = $files[$current_file]['chunks'][$current_chunk][] =

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2010 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -319,6 +319,7 @@ class IDF_Form_Admin_ProjectCreate extends Pluf_Form
'labels_issue_closed' => IDF_Form_IssueTrackingConf::init_closed, 'labels_issue_closed' => IDF_Form_IssueTrackingConf::init_closed,
'labels_issue_predefined' => IDF_Form_IssueTrackingConf::init_predefined, 'labels_issue_predefined' => IDF_Form_IssueTrackingConf::init_predefined,
'labels_issue_one_max' => IDF_Form_IssueTrackingConf::init_one_max, 'labels_issue_one_max' => IDF_Form_IssueTrackingConf::init_one_max,
'issue_relations' => IDF_Form_IssueTrackingConf::init_relations,
'webhook_url' => '', 'webhook_url' => '',
'downloads_access_rights' => 'all', 'downloads_access_rights' => 'all',
'review_access_rights' => 'all', 'review_access_rights' => 'all',

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,19 +3,19 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2010 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# Plume Framework is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or # the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# Plume Framework is distributed in the hope that it will be useful, # InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# #

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -36,6 +36,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
public $user = null; public $user = null;
public $project = null; public $project = null;
public $show_full = false; public $show_full = false;
public $relation_types = null;
public function initFields($extra=array()) public function initFields($extra=array())
{ {
@@ -45,9 +46,12 @@ class IDF_Form_IssueCreate extends Pluf_Form
or $this->user->hasPerm('IDF.project-member', $this->project)) { or $this->user->hasPerm('IDF.project-member', $this->project)) {
$this->show_full = true; $this->show_full = true;
} }
$this->relation_types = $this->project->getRelationsFromConfig();
$contentTemplate = $this->project->getConf()->getVal( $contentTemplate = $this->project->getConf()->getVal(
'labels_issue_template', IDF_Form_IssueTrackingConf::init_template 'labels_issue_template', IDF_Form_IssueTrackingConf::init_template
); );
$this->fields['summary'] = new Pluf_Form_Field_Varchar( $this->fields['summary'] = new Pluf_Form_Field_Varchar(
array('required' => true, array('required' => true,
'label' => __('Summary'), 'label' => __('Summary'),
@@ -76,11 +80,11 @@ class IDF_Form_IssueCreate extends Pluf_Form
// case of someone allowing the upload path to be accessible // case of someone allowing the upload path to be accessible
// to everybody. // to everybody.
for ($i=1;$i<4;$i++) { for ($i=1;$i<4;$i++) {
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
$this->fields['attachment'.$i] = new Pluf_Form_Field_File( $this->fields['attachment'.$i] = new Pluf_Form_Field_File(
array('required' => false, array('required' => false,
'label' => __('Attach a file'), 'label' => __('Attach a file'),
'move_function_params' => 'move_function_params' =>
array('upload_path' => $upload_path, array('upload_path' => $upload_path,
'upload_path_create' => true, 'upload_path_create' => true,
'file_name' => $filename, 'file_name' => $filename,
@@ -109,6 +113,20 @@ class IDF_Form_IssueCreate extends Pluf_Form
), ),
)); ));
$this->fields['relation_type0'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('This issue'),
'initial' => current($this->relation_types),
'widget_attrs' => array('size' => 15),
));
$this->fields['relation_issue0'] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => null,
'initial' => '',
'widget_attrs' => array('size' => 10),
));
/* /*
* get predefined tags for issues from current project * get predefined tags for issues from current project
* *
@@ -181,7 +199,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
$this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]);
if (strpos($this->cleaned_data['label'.$i], ':') !== false) { if (strpos($this->cleaned_data['label'.$i], ':') !== false) {
list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2);
list($class, $name) = array(mb_strtolower(trim($class)), list($class, $name) = array(mb_strtolower(trim($class)),
trim($name)); trim($name));
} else { } else {
$class = 'other'; $class = 'other';
@@ -215,10 +233,10 @@ class IDF_Form_IssueCreate extends Pluf_Form
function clean_status() function clean_status()
{ {
// Check that the status is in the list of official status // Check that the status is in the list of official status
$tags = $this->project->getTagsFromConfig('labels_issue_open', $tags = $this->project->getTagsFromConfig('labels_issue_open',
IDF_Form_IssueTrackingConf::init_open, IDF_Form_IssueTrackingConf::init_open,
'Status'); 'Status');
$tags = array_merge($this->project->getTagsFromConfig('labels_issue_closed', $tags = array_merge($this->project->getTagsFromConfig('labels_issue_closed',
IDF_Form_IssueTrackingConf::init_closed, IDF_Form_IssueTrackingConf::init_closed,
'Status') 'Status')
, $tags); , $tags);
@@ -235,6 +253,63 @@ class IDF_Form_IssueCreate extends Pluf_Form
return $this->cleaned_data['status']; return $this->cleaned_data['status'];
} }
// this method is not called from Pluf_Form directly, but shared for
// among all similar fields
function clean_relation_type($value)
{
$relation_type = trim($value);
if (empty($relation_type))
return '';
$found = false;
foreach ($this->relation_types as $type) {
if ($type == $relation_type) {
$found = true;
break;
}
}
if (!$found) {
throw new Pluf_Form_Invalid(__('You provided an invalid relation type.'));
}
return $relation_type;
}
function clean_relation_type0()
{
return $this->clean_relation_type($this->cleaned_data['relation_type0']);
}
// this method is not called from Pluf_Form directly, but shared for
// among all similar fields
function clean_relation_issue($value)
{
$issues = trim($value);
if (empty($issues))
return '';
$issue_ids = preg_split('/\s*,\s*/', $issues, -1, PREG_SPLIT_NO_EMPTY);
foreach ($issue_ids as $issue_id) {
if (!ctype_digit($issue_id) || (int)$issue_id < 1) {
throw new Pluf_Form_Invalid(sprintf(
__('The value "%s" is not a valid issue id.'), $issue_id
));
}
$issue = new IDF_Issue($issue_id);
if ($issue->id != $issue_id || $issue->project != $this->project->id) {
throw new Pluf_Form_Invalid(sprintf(
__('The issue "%s" does not exist.'), $issue_id
));
}
}
return implode(', ', $issue_ids);
}
function clean_relation_issue0()
{
return $this->clean_relation_issue($this->cleaned_data['relation_issue0']);
}
/** /**
* Clean the attachments post failure. * Clean the attachments post failure.
*/ */
@@ -298,6 +373,30 @@ class IDF_Form_IssueCreate extends Pluf_Form
foreach ($tags as $tag) { foreach ($tags as $tag) {
$issue->setAssoc($tag); $issue->setAssoc($tag);
} }
// add relations (if any)
if (!empty($this->cleaned_data['relation_type0'])) {
$verb = $this->cleaned_data['relation_type0'];
$other_verb = $this->relation_types[$verb];
$related_issues = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue0'], -1, PREG_SPLIT_NO_EMPTY);
foreach ($related_issues as $related_issue_id) {
$related_issue = new IDF_Issue($related_issue_id);
$rel = new IDF_IssueRelation();
$rel->issue = $issue;
$rel->verb = $verb;
$rel->other_issue = $related_issue;
$rel->submitter = $this->user;
$rel->create();
$other_rel = new IDF_IssueRelation();
$other_rel->issue = $related_issue;
$other_rel->verb = $other_verb;
$other_rel->other_issue = $issue;
$other_rel->submitter = $this->user;
$other_rel->create();
}
}
// add the first comment // add the first comment
$comment = new IDF_IssueComment(); $comment = new IDF_IssueComment();
$comment->issue = $issue; $comment->issue = $issue;

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -72,12 +72,29 @@ Performance = Performance issue
Usability = Affects program usability Usability = Affects program usability
Maintainability = Hinders future changes'; Maintainability = Hinders future changes';
const init_one_max = 'Type, Priority, Milestone'; const init_one_max = 'Type, Priority, Milestone';
// ATTENTION: if you change something here, change the values below as well!
const init_relations = 'is related to
blocks, is blocked by
duplicates, is duplicated by';
// These are actually all noop's, but we have no other chance to
// tell IDF's translation mechanism to mark the strings as translatable
// FIXME: IDF should get a internal translation system for strings like
// that, that can also be easily expanded by users
private function noop()
{
__('is related to');
__('blocks');
__('is blocked by');
__('duplicates');
__('is duplicated by');
}
public function initFields($extra=array()) public function initFields($extra=array())
{ {
$this->fields['labels_issue_template'] = new Pluf_Form_Field_Varchar( $this->fields['labels_issue_template'] = new Pluf_Form_Field_Varchar(
array('required' => false, array('required' => false,
'label' => __('Define an issue template to hint to the reporter to provide certain information'), 'label' => __('Define an issue template to hint the reporter to provide certain information'),
'initial' => self::init_template, 'initial' => self::init_template,
'widget_attrs' => array('rows' => 7, 'widget_attrs' => array('rows' => 7,
'cols' => 75), 'cols' => 75),
@@ -114,10 +131,19 @@ Maintainability = Hinders future changes';
$this->fields['labels_issue_one_max'] = new Pluf_Form_Field_Varchar( $this->fields['labels_issue_one_max'] = new Pluf_Form_Field_Varchar(
array('required' => false, array('required' => false,
'label' => __('Each issue may have at most one label with each of these classes'), 'label' => __('Each issue may have at most one label with each of these classes'),
'initial' => self::init_one_max, 'initial' => self::init_one_max,
'widget_attrs' => array('size' => 60), 'widget_attrs' => array('size' => 60),
)); ));
$this->fields['issue_relations'] = new Pluf_Form_Field_Varchar(
array('required' => true,
'label' => __('Issue relations'),
'initial' => self::init_relations,
'help_text' => __('You can define bidirectional relations like "is related to" or "blocks, is blocked by".'),
'widget_attrs' => array('rows' => 7,
'cols' => 75),
'widget' => 'Pluf_Form_Widget_TextareaInput',
));
} }
} }

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -39,6 +39,7 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
or $this->user->hasPerm('IDF.project-member', $this->project)) { or $this->user->hasPerm('IDF.project-member', $this->project)) {
$this->show_full = true; $this->show_full = true;
} }
$this->relation_types = $this->project->getRelationsFromConfig();
if ($this->show_full) { if ($this->show_full) {
$this->fields['summary'] = new Pluf_Form_Field_Varchar( $this->fields['summary'] = new Pluf_Form_Field_Varchar(
array('required' => true, array('required' => true,
@@ -69,11 +70,11 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
// case of someone allowing the upload path to be accessible // case of someone allowing the upload path to be accessible
// to everybody. // to everybody.
for ($i=1;$i<4;$i++) { for ($i=1;$i<4;$i++) {
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
$this->fields['attachment'.$i] = new Pluf_Form_Field_File( $this->fields['attachment'.$i] = new Pluf_Form_Field_File(
array('required' => false, array('required' => false,
'label' => __('Attach a file'), 'label' => __('Attach a file'),
'move_function_params' => 'move_function_params' =>
array('upload_path' => $upload_path, array('upload_path' => $upload_path,
'upload_path_create' => true, 'upload_path_create' => true,
'file_name' => $filename, 'file_name' => $filename,
@@ -102,6 +103,52 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
'size' => 15, 'size' => 15,
), ),
)); ));
$idx = 0;
// note: clean_relation_type0 and clean_relation_issue0 already
// exist in the base class
$this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('This issue'),
'initial' => current($this->relation_types),
'widget_attrs' => array('size' => 15),
));
$this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => null,
'initial' => '',
'widget_attrs' => array('size' => 10),
));
++$idx;
$relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true);
foreach ($relatedIssues as $verb => $ids) {
$this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => __('This issue'),
'initial' => $verb,
'widget_attrs' => array('size' => 15),
));
$m = 'clean_relation_type'.$idx;
$this->$m = create_function('$form', '
return $form->clean_relation_type($form->cleaned_data["relation_type'.$idx.'"]);
');
$this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar(
array('required' => false,
'label' => null,
'initial' => implode(', ', $ids),
'widget_attrs' => array('size' => 10),
));
$m = 'clean_relation_issue'.$idx;
$this->$m = create_function('$form', '
return $form->clean_relation_issue($form->cleaned_data["relation_issue'.$idx.'"]);
');
++$idx;
}
$tags = $this->issue->get_tags_list(); $tags = $this->issue->get_tags_list();
for ($i=1;$i<7;$i++) { for ($i=1;$i<7;$i++) {
$initial = ''; $initial = '';
@@ -155,6 +202,51 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
public function clean() public function clean()
{ {
$this->cleaned_data = parent::clean(); $this->cleaned_data = parent::clean();
// normalize the user's input by removing dublettes and by combining
// ids from identical verbs in different input fields into one array
$normRelatedIssues = array();
for ($idx = 0; isset($this->cleaned_data['relation_type'.$idx]); ++$idx) {
$verb = $this->cleaned_data['relation_type'.$idx];
if (empty($verb))
continue;
$ids = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue'.$idx],
-1, PREG_SPLIT_NO_EMPTY);
if (count($ids) == 0)
continue;
if (!array_key_exists($verb, $normRelatedIssues))
$normRelatedIssues[$verb] = array();
foreach ($ids as $id) {
if (!in_array($id, $normRelatedIssues[$verb]))
$normRelatedIssues[$verb][] = $id;
}
}
// now look at any added / removed ids
$added = $removed = array();
$relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true);
$added = array_diff_key($normRelatedIssues, $relatedIssues);
$removed = array_diff_key($relatedIssues, $normRelatedIssues);
$keysToLookAt = array_keys(
array_intersect_key($relatedIssues, $normRelatedIssues)
);
foreach ($keysToLookAt as $key) {
$a = array_diff($normRelatedIssues[$key], $relatedIssues[$key]);
if (count($a) > 0)
$added[$key] = $a;
$r = array_diff($relatedIssues[$key], $normRelatedIssues[$key]);
if (count($r) > 0)
$removed[$key] = $r;
}
// cache the added / removed data, so we do not have to
// calculate that again
$this->cleaned_data['_added_issue_relations'] = $added;
$this->cleaned_data['_removed_issue_relations'] = $removed;
// As soon as we know that at least one change was done, we // As soon as we know that at least one change was done, we
// return the cleaned data and do not go further. // return the cleaned data and do not go further.
if (strlen(trim($this->cleaned_data['content']))) { if (strlen(trim($this->cleaned_data['content']))) {
@@ -214,6 +306,11 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
return $this->cleaned_data; return $this->cleaned_data;
} }
} }
if (count($this->cleaned_data['_added_issue_relations']) != 0 ||
count($this->cleaned_data['_removed_issue_relations']) != 0) {
return $this->cleaned_data;
}
} }
// no changes! // no changes!
throw new Pluf_Form_Invalid(__('No changes were entered.')); throw new Pluf_Form_Invalid(__('No changes were entered.'));
@@ -255,20 +352,22 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
foreach ($tags as $tag) { foreach ($tags as $tag) {
if (!Pluf_Model_InArray($tag, $oldtags)) { if (!Pluf_Model_InArray($tag, $oldtags)) {
if (!isset($changes['lb'])) $changes['lb'] = array(); if (!isset($changes['lb'])) $changes['lb'] = array();
if (!isset($changes['lb']['add'])) $changes['lb']['add'] = array();
if ($tag->class != 'Other') { if ($tag->class != 'Other') {
$changes['lb'][] = (string) $tag; //new tag $changes['lb']['add'][] = (string) $tag; //new tag
} else { } else {
$changes['lb'][] = (string) $tag->name; $changes['lb']['add'][] = (string) $tag->name;
} }
} }
} }
foreach ($oldtags as $tag) { foreach ($oldtags as $tag) {
if (!Pluf_Model_InArray($tag, $tags)) { if (!Pluf_Model_InArray($tag, $tags)) {
if (!isset($changes['lb'])) $changes['lb'] = array(); if (!isset($changes['lb'])) $changes['lb'] = array();
if (!isset($changes['lb']['rem'])) $changes['lb']['rem'] = array();
if ($tag->class != 'Other') { if ($tag->class != 'Other') {
$changes['lb'][] = '-'.(string) $tag; //new tag $changes['lb']['rem'][] = (string) $tag; //new tag
} else { } else {
$changes['lb'][] = '-'.(string) $tag->name; $changes['lb']['rem'][] = (string) $tag->name;
} }
} }
} }
@@ -286,6 +385,47 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) { or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) {
$changes['ow'] = (is_null($owner)) ? '---' : $owner->login; $changes['ow'] = (is_null($owner)) ? '---' : $owner->login;
} }
// Issue relations - additions
foreach ($this->cleaned_data['_added_issue_relations'] as $verb => $ids) {
$other_verb = $this->relation_types[$verb];
foreach ($ids as $id) {
$related_issue = new IDF_Issue($id);
$rel = new IDF_IssueRelation();
$rel->issue = $this->issue;
$rel->verb = $verb;
$rel->other_issue = $related_issue;
$rel->submitter = $this->user;
$rel->create();
$other_rel = new IDF_IssueRelation();
$other_rel->issue = $related_issue;
$other_rel->verb = $other_verb;
$other_rel->other_issue = $this->issue;
$other_rel->submitter = $this->user;
$other_rel->create();
}
if (!isset($changes['rel'])) $changes['rel'] = array();
if (!isset($changes['rel']['add'])) $changes['rel']['add'] = array();
$changes['rel']['add'][] = $verb.' '.implode(', ', $ids);
}
// Issue relations - removals
foreach ($this->cleaned_data['_removed_issue_relations'] as $verb => $ids) {
foreach ($ids as $id) {
$db = &Pluf::db();
$table = Pluf::factory('IDF_IssueRelation')->getSqlTable();
$sql = new Pluf_SQL('verb=%s AND (
(issue=%s AND other_issue=%s) OR
(other_issue=%s AND issue=%s))',
array($verb,
$this->issue->id, $id,
$this->issue->id, $id));
$db->execute('DELETE FROM '.$table.' WHERE '.$sql->gen());
}
if (!isset($changes['rel'])) $changes['rel'] = array();
if (!isset($changes['rel']['rem'])) $changes['rel']['rem'] = array();
$changes['rel']['rem'][] = $verb.' '.implode(', ', $ids);
}
// Update the issue // Update the issue
$this->issue->batchAssoc('IDF_Tag', $tagids); $this->issue->batchAssoc('IDF_Tag', $tagids);
$this->issue->summary = trim($this->cleaned_data['summary']); $this->issue->summary = trim($this->cleaned_data['summary']);

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -0,0 +1,140 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright(C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Configuration of the project.
*/
class IDF_Form_ProjectConf extends Pluf_Form
{
public $project = null;
public function initFields($extra=array())
{
$this->project = $extra['project'];
// Basic part
$this->fields['name'] = new Pluf_Form_Field_Varchar(array('required' => true,
'label' => __('Name'),
'initial' => $this->project->name,
));
$this->fields['shortdesc'] = new Pluf_Form_Field_Varchar(array('required' => true,
'label' => __('Short Description'),
'initial' => $this->project->shortdesc,
'widget_attrs' => array('size' => '68'),
));
$this->fields['description'] = new Pluf_Form_Field_Varchar(array('required' => true,
'label' => __('Description'),
'initial' => $this->project->description,
'widget_attrs' => array('cols' => 68,
'rows' => 26,
),
'widget' => 'Pluf_Form_Widget_TextareaInput',
));
// Logo part
$upload_path = Pluf::f('upload_path', false);
if (false === $upload_path) {
throw new Pluf_Exception_SettingError(__('The "upload_path" configuration variable was not set.'));
}
$upload_path .= '/' . $this->project->shortname;
$filename = '/%s';
$this->fields['logo'] = new Pluf_Form_Field_File(array('required' => false,
'label' => __('Update the logo'),
'initial' => '',
'help_text' => __('The logo must be a picture with a size of 32 by 32.'),
'max_size' => Pluf::f('max_upload_size', 5 * 1024),
'move_function_params' =>
array('upload_path' => $upload_path,
'upload_path_create' => true,
'file_name' => $filename,
)
));
$this->fields['logo_remove'] = new Pluf_Form_Field_Boolean(array('required' => false,
'label' => __('Remove the current logo'),
'initial' => false,
'widget' => 'Pluf_Form_Widget_CheckboxInput',
));
}
/**
* If we have uploaded a file, but the form failed remove it.
*
*/
function failed()
{
if (!empty($this->cleaned_data['logo'])
&& file_exists(Pluf::f('upload_path').'/'.$this->cleaned_data['logo'])) {
unlink(Pluf::f('upload_path').'/'.$this->cleaned_data['logo']);
}
}
public function clean()
{
if (!isset($this->cleaned_data['logo_remove'])) {
$this->cleaned_data['logo_remove'] = false;
}
return $this->cleaned_data;
}
public function clean_logo()
{
if (empty($this->cleaned_data['logo'])) {
return '';
}
$meta = getimagesize(Pluf::f('upload_path') . '/' . $this->project->shortname . $this->cleaned_data['logo']);
if ($meta === false) {
throw new Pluf_Form_Invalid(__('Could not determine the size of the uploaded picture.'));
}
if ($meta[0] !== 32 || $meta[1] !== 32) {
throw new Pluf_Form_Invalid(__('The picture must have a size of 32 by 32.'));
}
return $this->cleaned_data['logo'];
}
public function save($commit=true)
{
$conf = $this->project->getConf();
// Basic part
$this->project->name = $this->cleaned_data['name'];
$this->project->shortdesc = $this->cleaned_data['shortdesc'];
$this->project->description = $this->cleaned_data['description'];
$this->project->update();
// Logo part
if ($this->cleaned_data['logo'] !== "") {
$conf->setVal('logo', $this->cleaned_data['logo']);
}
if ($this->cleaned_data['logo_remove'] === true) {
@unlink(Pluf::f('upload_path') . '/' . $this->project->shortname . $conf->getVal('logo'));
$conf->delVal('logo');
}
}
}

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -52,7 +52,7 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
)); ));
} }
$this->fields['content'] = new Pluf_Form_Field_Varchar( $this->fields['content'] = new Pluf_Form_Field_Varchar(
array('required' => true, array('required' => false,
'label' => __('General comment'), 'label' => __('General comment'),
'initial' => '', 'initial' => '',
'widget' => 'Pluf_Form_Widget_TextareaInput', 'widget' => 'Pluf_Form_Widget_TextareaInput',
@@ -96,24 +96,40 @@ class IDF_Form_ReviewFileComment extends Pluf_Form
*/ */
public function clean() public function clean()
{ {
foreach ($this->files as $filename => $def) { $isOk = false;
if (!empty($this->cleaned_data[md5($filename)])) {
return $this->cleaned_data; foreach($this->files as $filename => $def) {
$this->cleaned_data[md5($filename)] = trim($this->cleaned_data[md5($filename)]);
if(!empty($this->cleaned_data[md5($filename)])) {
$isOk = true;
} }
} }
throw new Pluf_Form_Invalid(__('You need to provide comments on at least one file.'));
if(!empty($this->cleaned_data['content'])) {
$isOk = true;
}
if (!$isOk) {
throw new Pluf_Form_Invalid(__('You need to provide your general comment about the proposal, or comments on at least one file.'));
}
return $this->cleaned_data;
} }
function clean_content() function clean_content()
{ {
$content = trim($this->cleaned_data['content']); $content = trim($this->cleaned_data['content']);
if (!$this->show_full and strlen($content) == 0) { if(empty($content)) {
throw new Pluf_Form_Invalid(__('You need to provide your general comment about the proposal.')); if ($this->fields['status']->initial != $this->fields['status']->value) {
return __('The status have been updated.');
}
} else {
return $content;
} }
return $content;
throw new Pluf_Form_Invalid(__('This field is required.'));
} }
/** /**
* Save the model in the database. * Save the model in the database.
* *

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -317,8 +317,15 @@ class IDF_Form_UserAccount extends Pluf_Form
return ''; return '';
} }
if (preg_match('#^ssh\-[a-z]{3}\s\S+(\s\S+)?$#', $key)) { $keysearch = '';
$key = str_replace(array("\n", "\r"), '', $key); if (preg_match('#^(ssh\-(?:dss|rsa)\s+\S+)(.*)#', $key, $m)) {
$basekey = preg_replace('/\s+/', ' ', $m[1]);
$comment = trim(preg_replace('/[\r\n]/', ' ', $m[2]));
$keysearch = $basekey.'%';
$key = $basekey;
if (!empty($comment))
$key .= ' '.$comment;
if (Pluf::f('idf_strong_key_check', false)) { if (Pluf::f('idf_strong_key_check', false)) {
@@ -337,7 +344,9 @@ class IDF_Form_UserAccount extends Pluf_Form
} }
} }
} }
else if (preg_match('#^\[pubkey [^\]]+\]\s*\S+\s*\[end\]$#', $key)) { else if (preg_match('#^\[pubkey [^\]]+\]\s*(\S+)\s*\[end\]$#', $key, $m)) {
$keysearch = '%'.$m[1].'%';
if (Pluf::f('idf_strong_key_check', false)) { if (Pluf::f('idf_strong_key_check', false)) {
// if monotone can read it, it should be valid // if monotone can read it, it should be valid
@@ -367,7 +376,7 @@ class IDF_Form_UserAccount extends Pluf_Form
if ($user) { if ($user) {
$ruser = Pluf::factory('Pluf_User', $user); $ruser = Pluf::factory('Pluf_User', $user);
if ($ruser->id > 0) { if ($ruser->id > 0) {
$sql = new Pluf_SQL('content=%s', array($key)); $sql = new Pluf_SQL('content LIKE %s AND user=%s', array($keysearch, $ruser->id));
$keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen())); $keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen()));
if (count($keys) > 0) { if (count($keys) > 0) {
throw new Pluf_Form_Invalid( throw new Pluf_Form_Invalid(

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -169,6 +169,24 @@ class IDF_Issue extends Pluf_Model
} }
} }
function getGroupedRelatedIssues($opts = array(), $idsOnly = false)
{
$rels = $this->get_related_issues_list(array_merge($opts, array(
'view' => 'with_other_issue',
)));
$res = array();
foreach ($rels as $rel) {
$verb = $rel->verb;
if (!array_key_exists($verb, $res)) {
$res[$verb] = array();
}
$res[$verb][] = $idsOnly ? $rel->other_issue : $rel;
}
return $res;
}
/** /**
* Returns an HTML fragment used to display this issue in the * Returns an HTML fragment used to display this issue in the
* timeline. * timeline.

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -155,10 +155,19 @@ class IDF_IssueComment extends Pluf_Model
$out .= __('Owner:'); break; $out .= __('Owner:'); break;
case 'lb': case 'lb':
$out .= __('Labels:'); break; $out .= __('Labels:'); break;
case 'rel':
$out .= __('Relations:'); break;
} }
$out .= '</strong>&nbsp;'; $out .= '</strong>&nbsp;';
if ($w == 'lb') { if ($w == 'lb' || $w == 'rel') {
$out .= Pluf_esc(implode(', ', $v)); foreach ($v as $t => $ls) {
foreach ($ls as $l) {
if ($t == 'rem') $out .= '<s>';
$out .= Pluf_esc($l);
if ($t == 'rem') $out .= '</s>';
$out .= ' ';
}
}
} else { } else {
$out .= Pluf_esc($v); $out .= Pluf_esc($v);
} }

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

100
src/IDF/IssueRelation.php Normal file
View File

@@ -0,0 +1,100 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* A relation of one issue to another
*/
class IDF_IssueRelation extends Pluf_Model
{
public $_model = __CLASS__;
function init()
{
$this->_a['table'] = 'idf_issuerelations';
$this->_a['model'] = __CLASS__;
$this->_a['cols'] = array(
// It is mandatory to have an "id" column.
'id' =>
array(
'type' => 'Pluf_DB_Field_Sequence',
'blank' => true,
),
'issue' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'IDF_Issue',
'blank' => false,
'verbose' => __('issue'),
'relate_name' => 'related_issues',
),
'verb' =>
array(
'type' => 'Pluf_DB_Field_Text',
'blank' => false,
'verbose' => __('verb'),
),
'other_issue' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'IDF_Issue',
'blank' => false,
'verbose' => __('other issue'),
'relate_name' => 'related_other_issues',
),
'submitter' =>
array(
'type' => 'Pluf_DB_Field_Foreignkey',
'model' => 'Pluf_User',
'blank' => false,
'verbose' => __('submitter'),
),
'creation_dtime' =>
array(
'type' => 'Pluf_DB_Field_Datetime',
'blank' => true,
'verbose' => __('creation date'),
),
);
$this->_a['idx'] = array(
'creation_dtime_idx' =>
array(
'col' => 'creation_dtime',
'type' => 'normal',
),
);
$issuetbl = $this->_con->pfx.'idf_issues';
$this->_a['views'] = array(
'with_other_issue' => array(
'join' => 'INNER JOIN '.$issuetbl.' ON other_issue='.$issuetbl.'.id',
'select' => $this->getSelect().', summary',
'props' => array('summary' => 'other_summary'),
));
}
function preSave($create=false)
{
if ($this->id == '') {
$this->creation_dtime = gmdate('Y-m-d H:i:s');
}
}
}

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -80,7 +80,7 @@ class IDF_Key extends Pluf_Model
if (preg_match('#^\[pubkey ([^\]]+)\]\s*(\S+)\s*\[end\]$#', $this->content, $m)) { if (preg_match('#^\[pubkey ([^\]]+)\]\s*(\S+)\s*\[end\]$#', $this->content, $m)) {
return array('mtn', $m[1], $m[2]); return array('mtn', $m[1], $m[2]);
} }
else if (preg_match('#^ssh\-[a-z]{3}\s(\S+)(?:\s(\S*))?$#', $this->content, $m)) { else if (preg_match('#^ssh\-(?:dss|rsa)\s(\S+)(?:\s(.*))?$#', $this->content, $m)) {
if (!isset($m[2])) { if (!isset($m[2])) {
$m[2] = ""; $m[2] = "";
} }

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -0,0 +1,90 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Add the new IDF_IssueRelation model.
*
*/
function IDF_Migrations_17AddIssueRelations_up($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_IssueRelation();
$schema->createTables();
// change the serialization format for added / removed labels in IDF_IssueComment
$comments = Pluf::factory('IDF_IssueComment')->getList();
foreach ($comments as $comment) {
if (!isset($comment->changes['lb'])) continue;
$changes = $comment->changes;
$adds = $removals = array();
foreach ($comment->changes['lb'] as $lb) {
if (substr($lb, 0, 1) == '-')
$removals[] = substr($lb, 1);
else
$adds[] = $lb;
}
$changes['lb'] = array();
if (count($adds) > 0)
$changes['lb']['add'] = $adds;
if (count($removals) > 0)
$changes['lb']['rem'] = $removals;
$comment->changes = $changes;
$comment->update();
}
}
function IDF_Migrations_17AddIssueRelations_down($params=null)
{
$db = Pluf::db();
$schema = new Pluf_DB_Schema($db);
$schema->model = new IDF_IssueRelation();
$schema->dropTables();
// change the serialization format for added / removed labels in IDF_IssueComment
$comments = Pluf::factory('IDF_IssueComment')->getList();
foreach ($comments as $comment) {
$changes = $comment->changes;
if (empty($changes))
continue;
if (isset($changes['lb'])) {
$labels = array();
foreach ($changes['lb'] as $type => $lbs) {
if (!is_array($lbs)) {
$labels[] = $lbs;
continue;
}
foreach ($lbs as $lb) {
$labels[] = ($type == 'rem' ? '-' : '') . $lb;
}
}
$changes['lb'] = $labels;
}
// while we're at it, remove any 'rel' changes
unset($changes['rel']);
$comment->changes = $changes;
$comment->update();
}
}

View File

@@ -0,0 +1,63 @@
<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application.
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
#
# InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# InDefero is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# ***** END LICENSE BLOCK ***** */
/**
* Add the md5 column for the download model.
*/
function IDF_Migrations_18DownloadMD5_up($params=null)
{
// Add the row
$table = Pluf::factory('IDF_Upload')->getSqlTable();
$sql = array();
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "md5" VARCHAR(32) DEFAULT \'\'';
$sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `md5` VARCHAR(32) DEFAULT \'\'';
$db = Pluf::db();
$engine = Pluf::f('db_engine');
if (!isset($sql[$engine])) {
throw new Exception('SQLite complex migration not supported.');
}
$db->execute($sql[$engine]);
// Process md5 of already uploaded file
$files = Pluf::factory('IDF_Upload')->getList();
foreach ($files as $f) {
$f->md5 = md5_file (Pluf::f('upload_path') . '/' . $f->get_project()->shortname . '/files/' . $f->file);
$f->update();
}
}
function IDF_Migrations_18DownloadMD5_down($params=null)
{
// Remove the row
$table = Pluf::factory('IDF_Upload')->getSqlTable();
$sql = array();
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "md5"';
$sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `md5`';
$db = Pluf::db();
$engine = Pluf::f('db_engine');
if (!isset($sql[$engine])) {
throw new Exception('SQLite complex migration not supported.');
}
$db->execute($sql[$engine]);
}

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@ function IDF_Migrations_Backup_run($folder, $name=null)
'IDF_Queue', 'IDF_Queue',
'IDF_Gconf', 'IDF_Gconf',
'IDF_EmailAddress', 'IDF_EmailAddress',
'IDF_IssueRelation',
); );
$db = Pluf::db(); $db = Pluf::db();
// Now, for each table, we dump the content in json, this is a // Now, for each table, we dump the content in json, this is a
@@ -100,6 +101,7 @@ function IDF_Migrations_Backup_restore($folder, $name)
'IDF_Queue', 'IDF_Queue',
'IDF_Gconf', 'IDF_Gconf',
'IDF_EmailAddress', 'IDF_EmailAddress',
'IDF_IssueRelation',
); );
$db = Pluf::db(); $db = Pluf::db();
$schema = new Pluf_DB_Schema($db); $schema = new Pluf_DB_Schema($db);

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -51,6 +51,7 @@ function IDF_Migrations_Install_setup($params=null)
'IDF_Queue', 'IDF_Queue',
'IDF_Gconf', 'IDF_Gconf',
'IDF_EmailAddress', 'IDF_EmailAddress',
'IDF_IssueRelation',
); );
$db = Pluf::db(); $db = Pluf::db();
$schema = new Pluf_DB_Schema($db); $schema = new Pluf_DB_Schema($db);
@@ -109,6 +110,7 @@ function IDF_Migrations_Install_teardown($params=null)
'IDF_Commit', 'IDF_Commit',
'IDF_Project', 'IDF_Project',
'IDF_EmailAddress', 'IDF_EmailAddress',
'IDF_IssueRelation',
); );
$db = Pluf::db(); $db = Pluf::db();
$schema = new Pluf_DB_Schema($db); $schema = new Pluf_DB_Schema($db);

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -59,6 +59,16 @@ class IDF_Plugin_SyncGit_Cron
$out .= sprintf($template, $cmd, $key->login, $content)."\n"; $out .= sprintf($template, $cmd, $key->login, $content)."\n";
} }
} }
$out = "# indefero start" . PHP_EOL . $out . "# indefero end" . PHP_EOL;
// We update only the part of the file between IDF_START / IDF_END comment
$original_keys = file_get_contents($authorized_keys);
if (strstr($original_keys, "# indefero start") && strstr($original_keys, "# indefero end")) {
$out = preg_replace('/(#\sindefero\sstart).+(#\sindefero\send\s\s?)/isU',
$out, $original_keys);
} else {
$out .= $original_keys;
}
file_put_contents($authorized_keys, $out, LOCK_EX); file_put_contents($authorized_keys, $out, LOCK_EX);
} }

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2010 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -27,6 +27,18 @@
*/ */
class IDF_Plugin_SyncMonotone class IDF_Plugin_SyncMonotone
{ {
private $old_err_rep = 0;
public function __construct()
{
$this->old_err_rep = error_reporting(0);
}
public function __destruct()
{
error_reporting($this->old_err_rep);
}
/** /**
* Entry point of the plugin. * Entry point of the plugin.
*/ */
@@ -80,24 +92,33 @@ class IDF_Plugin_SyncMonotone
return; return;
} }
// This guard cleans up on any kind of error, and here is how it works:
// As long as the guard is not committed, it keeps a reference to
// the given project. When the guard is destroyed and the reference
// is still present, it deletes the object. The deletion indirectly
// also calls into this plugin again, as the project delete hook
// will be called, that removes any changes we've made during the
// process.
$projectGuard = new IDF_Plugin_SyncMonotone_ModelGuard($project);
$projecttempl = Pluf::f('mtn_repositories', false); $projecttempl = Pluf::f('mtn_repositories', false);
if ($projecttempl === false) { if ($projecttempl === false) {
throw new IDF_Scm_Exception( $this->_diagnoseProblem(
__('"mtn_repositories" must be defined in your configuration file.') __('"mtn_repositories" must be defined in your configuration file')
); );
} }
$usher_config = Pluf::f('mtn_usher_conf', false); $usher_config = Pluf::f('mtn_usher_conf', false);
if (!$usher_config || !is_writable($usher_config)) { if (!$usher_config || !is_writable($usher_config)) {
throw new IDF_Scm_Exception( $this->_diagnoseProblem(
__('"mtn_usher_conf" does not exist or is not writable.') __('"mtn_usher_conf" does not exist or is not writable')
); );
} }
$mtnpostpush = realpath(dirname(__FILE__) . '/../../../scripts/mtn-post-push'); $mtnpostpush = realpath(dirname(__FILE__) . '/../../../scripts/mtn-post-push');
if (!file_exists($mtnpostpush)) { if (!file_exists($mtnpostpush)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not find mtn-post-push script "%s".'), $mtnpostpush __('Could not find mtn-post-push script "%s"'), $mtnpostpush
)); ));
} }
@@ -110,13 +131,12 @@ class IDF_Plugin_SyncMonotone
'monotonerc.in', 'monotonerc.in',
'remote-automate-permissions.in', 'remote-automate-permissions.in',
'hooks.d/', 'hooks.d/',
// this is linked and not copied to be able to update
// the list of read-only commands on upgrades
'hooks.d/indefero_authorize_remote_automate.conf',
'hooks.d/indefero_authorize_remote_automate.lua', 'hooks.d/indefero_authorize_remote_automate.lua',
'hooks.d/indefero_post_push.conf.in', 'hooks.d/indefero_post_push.conf.in',
'hooks.d/indefero_post_push.lua', 'hooks.d/indefero_post_push.lua',
); );
// enable remote command execution of read-only commands
// only for public projects
if (!$project->private) { if (!$project->private) {
// this is linked and not copied to be able to update // this is linked and not copied to be able to update
// the list of read-only commands on upgrades // the list of read-only commands on upgrades
@@ -131,8 +151,8 @@ class IDF_Plugin_SyncMonotone
} }
foreach ($confdir_contents as $content) { foreach ($confdir_contents as $content) {
if (!file_exists($confdir.$content)) { if (!file_exists($confdir.$content)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('The configuration file %s is missing.'), $content __('The configuration file "%s" is missing'), $content
)); ));
} }
} }
@@ -140,14 +160,15 @@ class IDF_Plugin_SyncMonotone
$shortname = $project->shortname; $shortname = $project->shortname;
$projectpath = sprintf($projecttempl, $shortname); $projectpath = sprintf($projecttempl, $shortname);
if (file_exists($projectpath)) { if (file_exists($projectpath)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('The project path %s already exists.'), $projectpath __('The project path "%s" already exists'), $projectpath
)); ));
} }
if (!mkdir($projectpath)) { if (!@mkdir($projectpath)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('The project path %s could not be created.'), $projectpath __('The project path "%s" could not be created'),
$projectpath
)); ));
} }
@@ -156,7 +177,7 @@ class IDF_Plugin_SyncMonotone
// //
$dbfile = $projectpath.'/database.mtn'; $dbfile = $projectpath.'/database.mtn';
$cmd = sprintf('db init -d %s', escapeshellarg($dbfile)); $cmd = sprintf('db init -d %s', escapeshellarg($dbfile));
self::_mtn_exec($cmd); $this->_mtn_exec($cmd);
// //
// step 2) create a server key // step 2) create a server key
@@ -175,16 +196,17 @@ class IDF_Plugin_SyncMonotone
escapeshellarg($projectpath), escapeshellarg($projectpath),
escapeshellarg($serverkey) escapeshellarg($serverkey)
); );
self::_mtn_exec($cmd); $this->_mtn_exec($cmd);
// //
// step 3) create a client key, and save it in IDF // step 3) create a client key, and save it in IDF
// //
$keydir = Pluf::f('tmp_folder').'/mtn-client-keys'; $keydir = Pluf::f('tmp_folder').'/mtn-client-keys';
if (!file_exists($keydir)) { if (!file_exists($keydir)) {
if (!mkdir($keydir)) { if (!@mkdir($keydir)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('The key directory %s could not be created.'), $keydir __('The key directory "%s" could not be created'),
$keydir
)); ));
} }
} }
@@ -194,14 +216,14 @@ class IDF_Plugin_SyncMonotone
escapeshellarg($keydir), escapeshellarg($keydir),
escapeshellarg($clientkey_name) escapeshellarg($clientkey_name)
); );
$keyinfo = self::_mtn_exec($cmd); $keyinfo = $this->_mtn_exec($cmd);
$parsed_keyinfo = array(); $parsed_keyinfo = array();
try { try {
$parsed_keyinfo = IDF_Scm_Monotone_BasicIO::parse($keyinfo); $parsed_keyinfo = IDF_Scm_Monotone_BasicIO::parse($keyinfo);
} }
catch (Exception $e) { catch (Exception $e) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not parse key information: %s'), $e->getMessage() __('Could not parse key information: %s'), $e->getMessage()
)); ));
} }
@@ -219,13 +241,13 @@ class IDF_Plugin_SyncMonotone
escapeshellarg($keydir), escapeshellarg($keydir),
escapeshellarg($clientkey_hash) escapeshellarg($clientkey_hash)
); );
$clientkey_pubdata = self::_mtn_exec($cmd); $clientkey_pubdata = $this->_mtn_exec($cmd);
$cmd = sprintf('au put_public_key --db=%s %s', $cmd = sprintf('au put_public_key --db=%s %s',
escapeshellarg($dbfile), escapeshellarg($dbfile),
escapeshellarg($clientkey_pubdata) escapeshellarg($clientkey_pubdata)
); );
self::_mtn_exec($cmd); $this->_mtn_exec($cmd);
// //
// step 4) setup the configuration // step 4) setup the configuration
@@ -238,18 +260,20 @@ class IDF_Plugin_SyncMonotone
foreach ($confdir_contents as $content) { foreach ($confdir_contents as $content) {
$filepath = $projectpath.'/'.$content; $filepath = $projectpath.'/'.$content;
if (substr($content, -1) == '/') { if (substr($content, -1) == '/') {
if (!mkdir($filepath)) { if (!@mkdir($filepath)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not create configuration directory "%s"'), $filepath __('Could not create configuration directory "%s"'),
$filepath
)); ));
} }
continue; continue;
} }
if (substr($content, -3) != '.in') { if (substr($content, -3) != '.in') {
if (!symlink($confdir.$content, $filepath)) { if (!@symlink($confdir.$content, $filepath)) {
IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not create symlink "%s"'), $filepath __('Could not create symlink for configuration file "%s"'),
$filepath
)); ));
} }
continue; continue;
@@ -264,9 +288,10 @@ class IDF_Plugin_SyncMonotone
// remove the .in // remove the .in
$filepath = substr($filepath, 0, -3); $filepath = substr($filepath, 0, -3);
if (file_put_contents($filepath, $filecontents, LOCK_EX) === false) { if (@file_put_contents($filepath, $filecontents, LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write configuration file "%s"'), $filepath __('Could not write configuration file "%s"'),
$filepath
)); ));
} }
} }
@@ -280,7 +305,7 @@ class IDF_Plugin_SyncMonotone
$parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc); $parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc);
} }
catch (Exception $e) { catch (Exception $e) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not parse usher configuration in "%s": %s'), __('Could not parse usher configuration in "%s": %s'),
$usher_config, $e->getMessage() $usher_config, $e->getMessage()
)); ));
@@ -291,7 +316,7 @@ class IDF_Plugin_SyncMonotone
foreach ($stanzas as $stanza_line) { foreach ($stanzas as $stanza_line) {
if ($stanza_line['key'] == 'server' && if ($stanza_line['key'] == 'server' &&
$stanza_line['values'][0] == $shortname) { $stanza_line['values'][0] == $shortname) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('usher configuration already contains a server '. __('usher configuration already contains a server '.
'entry named "%s"'), 'entry named "%s"'),
$shortname $shortname
@@ -315,9 +340,10 @@ class IDF_Plugin_SyncMonotone
// FIXME: more sanity - what happens on failing writes? we do not // FIXME: more sanity - what happens on failing writes? we do not
// have a backup copy of usher.conf around... // have a backup copy of usher.conf around...
if (file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) { if (@file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write usher configuration file "%s"'), $usher_config __('Could not write usher configuration file "%s"'),
$usher_config
)); ));
} }
@@ -325,6 +351,9 @@ class IDF_Plugin_SyncMonotone
// step 6) reload usher to pick up the new configuration // step 6) reload usher to pick up the new configuration
// //
IDF_Scm_Monotone_Usher::reload(); IDF_Scm_Monotone_Usher::reload();
// commit the guard, so the newly created project is not deleted
$projectGuard->commit();
} }
/** /**
@@ -345,8 +374,8 @@ class IDF_Plugin_SyncMonotone
$mtn = IDF_Scm_Monotone::factory($project); $mtn = IDF_Scm_Monotone::factory($project);
$stdio = $mtn->getStdio(); $stdio = $mtn->getStdio();
$projectpath = self::_get_project_path($project); $projectpath = $this->_get_project_path($project);
$auth_ids = self::_get_authorized_user_ids($project); $auth_ids = $this->_get_authorized_user_ids($project);
$key_ids = array(); $key_ids = array();
foreach ($auth_ids as $auth_id) { foreach ($auth_ids as $auth_id) {
$sql = new Pluf_SQL('user=%s', array($auth_id)); $sql = new Pluf_SQL('user=%s', array($auth_id));
@@ -361,9 +390,10 @@ class IDF_Plugin_SyncMonotone
$write_permissions = implode("\n", $key_ids); $write_permissions = implode("\n", $key_ids);
$rcfile = $projectpath.'/write-permissions'; $rcfile = $projectpath.'/write-permissions';
if (file_put_contents($rcfile, $write_permissions, LOCK_EX) === false) { if (@file_put_contents($rcfile, $write_permissions, LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write write-permissions file "%s"'), $rcfile __('Could not write write-permissions file "%s"'),
$rcfile
)); ));
} }
@@ -382,11 +412,13 @@ class IDF_Plugin_SyncMonotone
array('key' => 'allow', 'values' => array('*')), array('key' => 'allow', 'values' => array('*')),
); );
} }
$read_permissions = IDF_Scm_Monotone_BasicIO::compile(array($stanza)); $read_permissions = IDF_Scm_Monotone_BasicIO::compile(array($stanza));
$rcfile = $projectpath.'/read-permissions'; $rcfile = $projectpath.'/read-permissions';
if (file_put_contents($rcfile, $read_permissions, LOCK_EX) === false) { if (@file_put_contents($rcfile, $read_permissions, LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write read-permissions file "%s"'), $rcfile __('Could not write read-permissions file "%s"'),
$rcfile
)); ));
} }
@@ -401,16 +433,16 @@ class IDF_Plugin_SyncMonotone
$serverRestartRequired = false; $serverRestartRequired = false;
if ($project->private && file_exists($projectfile) && is_link($projectfile)) { if ($project->private && file_exists($projectfile) && is_link($projectfile)) {
if (!unlink($projectfile)) { if (!@unlink($projectfile)) {
IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not remove symlink "%s"'), $projectfile __('Could not remove symlink "%s"'), $projectfile
)); ));
} }
$serverRestartRequired = true; $serverRestartRequired = true;
} else } else
if (!$project->private && !file_exists($projectfile)) { if (!$project->private && !file_exists($projectfile)) {
if (!symlink($templatefile, $projectfile)) { if (!@symlink($templatefile, $projectfile)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not create symlink "%s"'), $projectfile __('Could not create symlink "%s"'), $projectfile
)); ));
} }
@@ -422,6 +454,9 @@ class IDF_Plugin_SyncMonotone
// seems to be ignored when the server should be started // seems to be ignored when the server should be started
// again immediately afterwards // again immediately afterwards
IDF_Scm_Monotone_Usher::killServer($project->shortname); IDF_Scm_Monotone_Usher::killServer($project->shortname);
// give usher some time to cool down, otherwise it might hang
// (see https://code.monotone.ca/p/contrib/issues/175/)
sleep(2);
IDF_Scm_Monotone_Usher::startServer($project->shortname); IDF_Scm_Monotone_Usher::startServer($project->shortname);
} }
} }
@@ -443,8 +478,8 @@ class IDF_Plugin_SyncMonotone
$usher_config = Pluf::f('mtn_usher_conf', false); $usher_config = Pluf::f('mtn_usher_conf', false);
if (!$usher_config || !is_writable($usher_config)) { if (!$usher_config || !is_writable($usher_config)) {
throw new IDF_Scm_Exception( $this->_diagnoseProblem(
__('"mtn_usher_conf" does not exist or is not writable.') __('"mtn_usher_conf" does not exist or is not writable')
); );
} }
@@ -453,16 +488,16 @@ class IDF_Plugin_SyncMonotone
$projecttempl = Pluf::f('mtn_repositories', false); $projecttempl = Pluf::f('mtn_repositories', false);
if ($projecttempl === false) { if ($projecttempl === false) {
throw new IDF_Scm_Exception( $this->_diagnoseProblem(
__('"mtn_repositories" must be defined in your configuration file.') __('"mtn_repositories" must be defined in your configuration file')
); );
} }
$projectpath = sprintf($projecttempl, $shortname); $projectpath = sprintf($projecttempl, $shortname);
if (file_exists($projectpath)) { if (file_exists($projectpath)) {
if (!self::_delete_recursive($projectpath)) { if (!$this->_delete_recursive($projectpath)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('One or more paths underknees %s could not be deleted.'), $projectpath __('One or more paths underneath %s could not be deleted'), $projectpath
)); ));
} }
} }
@@ -473,8 +508,9 @@ class IDF_Plugin_SyncMonotone
if ($keyname && $keyhash && if ($keyname && $keyhash &&
file_exists($keydir .'/'. $keyname . '.' . $keyhash)) { file_exists($keydir .'/'. $keyname . '.' . $keyhash)) {
if (!@unlink($keydir .'/'. $keyname . '.' . $keyhash)) { if (!@unlink($keydir .'/'. $keyname . '.' . $keyhash)) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not delete client private key %s'), $keyname __('Could not delete client private key "%s"'),
$keyname
)); ));
} }
} }
@@ -485,7 +521,7 @@ class IDF_Plugin_SyncMonotone
$parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc); $parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc);
} }
catch (Exception $e) { catch (Exception $e) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not parse usher configuration in "%s": %s'), __('Could not parse usher configuration in "%s": %s'),
$usher_config, $e->getMessage() $usher_config, $e->getMessage()
)); ));
@@ -505,9 +541,10 @@ class IDF_Plugin_SyncMonotone
// FIXME: more sanity - what happens on failing writes? we do not // FIXME: more sanity - what happens on failing writes? we do not
// have a backup copy of usher.conf around... // have a backup copy of usher.conf around...
if (file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) { if (@file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write usher configuration file "%s"'), $usher_config __('Could not write usher configuration file "%s"'),
$usher_config
)); ));
} }
@@ -528,6 +565,8 @@ class IDF_Plugin_SyncMonotone
return; return;
} }
$keyGuard = new IDF_Plugin_SyncMonotone_ModelGuard($key);
foreach (Pluf::factory('IDF_Project')->getList() as $project) { foreach (Pluf::factory('IDF_Project')->getList() as $project) {
$conf = new IDF_Conf(); $conf = new IDF_Conf();
$conf->setProject($project); $conf->setProject($project);
@@ -535,8 +574,8 @@ class IDF_Plugin_SyncMonotone
if ($scm != 'mtn') if ($scm != 'mtn')
continue; continue;
$projectpath = self::_get_project_path($project); $projectpath = $this->_get_project_path($project);
$auth_ids = self::_get_authorized_user_ids($project); $auth_ids = $this->_get_authorized_user_ids($project);
if (!in_array($key->user, $auth_ids)) if (!in_array($key->user, $auth_ids))
continue; continue;
@@ -556,7 +595,7 @@ class IDF_Plugin_SyncMonotone
$parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms); $parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms);
} }
catch (Exception $e) { catch (Exception $e) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not parse read-permissions for project "%s": %s'), __('Could not parse read-permissions for project "%s": %s'),
$shortname, $e->getMessage() $shortname, $e->getMessage()
)); ));
@@ -598,10 +637,11 @@ class IDF_Plugin_SyncMonotone
$read_perms = IDF_Scm_Monotone_BasicIO::compile($parsed_read_perms); $read_perms = IDF_Scm_Monotone_BasicIO::compile($parsed_read_perms);
if (file_put_contents($projectpath.'/read-permissions', if (@file_put_contents($projectpath.'/read-permissions',
$read_perms, LOCK_EX) === false) { $read_perms, LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write read-permissions for project "%s"'), $shortname __('Could not write read-permissions for project "%s"'),
$shortname
)); ));
} }
} }
@@ -611,9 +651,9 @@ class IDF_Plugin_SyncMonotone
if (!in_array('*', $lines) && !in_array($mtn_key_id, $lines)) { if (!in_array('*', $lines) && !in_array($mtn_key_id, $lines)) {
$lines[] = $mtn_key_id; $lines[] = $mtn_key_id;
} }
if (file_put_contents($projectpath.'/write-permissions', if (@file_put_contents($projectpath.'/write-permissions',
implode("\n", $lines) . "\n", LOCK_EX) === false) { implode("\n", $lines) . "\n", LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write write-permissions file for project "%s"'), __('Could not write write-permissions file for project "%s"'),
$shortname $shortname
)); ));
@@ -623,6 +663,8 @@ class IDF_Plugin_SyncMonotone
$stdio = $mtn->getStdio(); $stdio = $mtn->getStdio();
$stdio->exec(array('put_public_key', $key->content)); $stdio->exec(array('put_public_key', $key->content));
} }
$keyGuard->commit();
} }
/** /**
@@ -651,8 +693,8 @@ class IDF_Plugin_SyncMonotone
if ($scm != 'mtn') if ($scm != 'mtn')
continue; continue;
$projectpath = self::_get_project_path($project); $projectpath = $this->_get_project_path($project);
$auth_ids = self::_get_authorized_user_ids($project); $auth_ids = $this->_get_authorized_user_ids($project);
if (!in_array($key->user, $auth_ids)) if (!in_array($key->user, $auth_ids))
continue; continue;
@@ -672,7 +714,7 @@ class IDF_Plugin_SyncMonotone
$parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms); $parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms);
} }
catch (Exception $e) { catch (Exception $e) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not parse read-permissions for project "%s": %s'), __('Could not parse read-permissions for project "%s": %s'),
$shortname, $e->getMessage() $shortname, $e->getMessage()
)); ));
@@ -693,10 +735,11 @@ class IDF_Plugin_SyncMonotone
$read_perms = IDF_Scm_Monotone_BasicIO::compile($parsed_read_perms); $read_perms = IDF_Scm_Monotone_BasicIO::compile($parsed_read_perms);
if (file_put_contents($projectpath.'/read-permissions', if (@file_put_contents($projectpath.'/read-permissions',
$read_perms, LOCK_EX) === false) { $read_perms, LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write read-permissions for project "%s"'), $shortname __('Could not write read-permissions for project "%s"'),
$shortname
)); ));
} }
} }
@@ -711,9 +754,9 @@ class IDF_Plugin_SyncMonotone
continue; continue;
} }
} }
if (file_put_contents($projectpath.'/write-permissions', if (@file_put_contents($projectpath.'/write-permissions',
implode("\n", $lines) . "\n", LOCK_EX) === false) { implode("\n", $lines) . "\n", LOCK_EX) === false) {
throw new IDF_Scm_Exception(sprintf( $this->_diagnoseProblem(sprintf(
__('Could not write write-permissions file for project "%s"'), __('Could not write write-permissions file for project "%s"'),
$shortname $shortname
)); ));
@@ -762,7 +805,43 @@ class IDF_Plugin_SyncMonotone
)); ));
} }
private static function _get_authorized_user_ids($project) private function _get_project_path($project)
{
$projecttempl = Pluf::f('mtn_repositories', false);
if ($projecttempl === false) {
$this->_diagnoseProblem(
__('"mtn_repositories" must be defined in your configuration file.')
);
}
$projectpath = sprintf($projecttempl, $project->shortname);
if (!file_exists($projectpath)) {
$this->_diagnoseProblem(sprintf(
__('The project path %s does not exists.'), $projectpath
));
}
return $projectpath;
}
private function _mtn_exec($cmd)
{
$fullcmd = sprintf('%s %s %s',
Pluf::f('idf_exec_cmd_prefix', ''),
Pluf::f('mtn_path', 'mtn'),
$cmd
);
$output = $return = null;
exec($fullcmd, $output, $return);
if ($return != 0) {
$this->_diagnoseProblem(sprintf(
__('The command "%s" could not be executed.'), $cmd
));
}
return implode("\n", $output);
}
private function _get_authorized_user_ids($project)
{ {
$mem = $project->getMembershipData(); $mem = $project->getMembershipData();
$members = array_merge((array)$mem['members'], $members = array_merge((array)$mem['members'],
@@ -775,43 +854,7 @@ class IDF_Plugin_SyncMonotone
return $userids; return $userids;
} }
private static function _get_project_path($project) private function _delete_recursive($path)
{
$projecttempl = Pluf::f('mtn_repositories', false);
if ($projecttempl === false) {
throw new IDF_Scm_Exception(
__('"mtn_repositories" must be defined in your configuration file.')
);
}
$projectpath = sprintf($projecttempl, $project->shortname);
if (!file_exists($projectpath)) {
throw new IDF_Scm_Exception(sprintf(
__('The project path %s does not exists.'), $projectpath
));
}
return $projectpath;
}
private static function _mtn_exec($cmd)
{
$fullcmd = sprintf('%s %s %s',
Pluf::f('idf_exec_cmd_prefix', ''),
Pluf::f('mtn_path', 'mtn'),
$cmd
);
$output = $return = null;
exec($fullcmd, $output, $return);
if ($return != 0) {
throw new IDF_Scm_Exception(sprintf(
__('The command "%s" could not be executed.'), $cmd
));
}
return implode("\n", $output);
}
private static function _delete_recursive($path)
{ {
if (is_file($path) || is_link($path)) { if (is_file($path) || is_link($path)) {
return @unlink($path); return @unlink($path);
@@ -821,10 +864,48 @@ class IDF_Plugin_SyncMonotone
$scan = glob(rtrim($path, '/') . '/*'); $scan = glob(rtrim($path, '/') . '/*');
$status = 0; $status = 0;
foreach ($scan as $subpath) { foreach ($scan as $subpath) {
$status |= self::_delete_recursive($subpath); $status |= $this->_delete_recursive($subpath);
} }
$status |= rmdir($path); $status |= @rmdir($path);
return $status; return $status;
} }
} }
private function _diagnoseProblem($msg)
{
$system_err = error_get_last();
if (!empty($system_err)) {
$msg .= ': '.$system_err['message'];
}
error_reporting($this->old_err_rep);
throw new IDF_Scm_Exception($msg);
}
} }
/**
* A simple helper class that deletes the model instance if
* it is not committed
*/
class IDF_Plugin_SyncMonotone_ModelGuard
{
private $model;
public function __construct(Pluf_Model $m)
{
$this->model = $m;
}
public function __destruct()
{
if ($this->model == null)
return;
$this->model->delete();
}
public function commit()
{
$this->model = null;
}
}

View File

@@ -1,6 +1,6 @@
-- ***** BEGIN LICENSE BLOCK ***** -- ***** BEGIN LICENSE BLOCK *****
-- This file is part of InDefero, an open source project management application. -- This file is part of InDefero, an open source project management application.
-- Copyright (C) 2011 Céondo Ltd and contributors. -- Copyright (C) 2008-2011 Céondo Ltd and contributors.
-- Copyright (C) 2010 Thomas Keller <me@thomaskeller.biz> -- Copyright (C) 2010 Thomas Keller <me@thomaskeller.biz>
-- Richard Levitte <richard@levitte.org> -- Richard Levitte <richard@levitte.org>
-- --

View File

@@ -1,6 +1,6 @@
-- ***** BEGIN LICENSE BLOCK ***** -- ***** BEGIN LICENSE BLOCK *****
-- This file is part of InDefero, an open source project management application. -- This file is part of InDefero, an open source project management application.
-- Copyright (C) 2011 Céondo Ltd and contributors. -- Copyright (C) 2008-2011 Céondo Ltd and contributors.
-- --
-- InDefero is free software; you can redistribute it and/or modify -- InDefero is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by -- it under the terms of the GNU General Public License as published by

View File

@@ -1,6 +1,6 @@
-- ***** BEGIN LICENSE BLOCK ***** -- ***** BEGIN LICENSE BLOCK *****
-- This file is part of InDefero, an open source project management application. -- This file is part of InDefero, an open source project management application.
-- Copyright (C) 2011 Céondo Ltd and contributors. -- Copyright (C) 2008-2011 Céondo Ltd and contributors.
-- --
-- InDefero is free software; you can redistribute it and/or modify -- InDefero is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by -- it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -132,6 +132,46 @@ class IDF_Project extends Pluf_Model
} }
return $projects[0]; return $projects[0];
} }
/**
* Returns the number of open/closed issues.
*
* @param string Status ('open'), 'closed'
* @param IDF_Tag Subfilter with a label (null)
* @return int Count
*/
public function getIssueCountByOwner($status='open')
{
switch ($status) {
case 'open':
$tags = implode(',', $this->getTagIdsByStatus('open'));
break;
case 'closed':
default:
$tags = implode(',', $this->getTagIdsByStatus('closed'));
break;
}
$sqlIssueTable = Pluf::factory('IDF_Issue')->getSqlTable();
$query = "SELECT uid AS id,COUNT(uid) AS nb
FROM (
SELECT COALESCE(owner, -1) AS uid
FROM $sqlIssueTable
WHERE status IN ($tags)
) AS ff
GROUP BY uid";
$db = Pluf::db();
$dbData = $db->select($query);
$ownerStatistics = array();
foreach ($dbData as $k => $v) {
$key = ($v['id'] === '-1') ? null : $v['id'];
$ownerStatistics[$key] = (int)$v['nb'];
}
arsort($ownerStatistics);
return $ownerStatistics;
}
/** /**
* Returns the number of open/closed issues. * Returns the number of open/closed issues.
@@ -233,6 +273,29 @@ class IDF_Project extends Pluf_Model
return $tags; return $tags;
} }
/**
* Returns a list of relations which are available in this project as
* associative array. Each key-value pair marks a set of orthogonal
* relations. To ease processing, each of these pairs is included twice
* in the array, once as key1 => key2 and once as key2 => key1.
*
* @return array List of relation names
*/
public function getRelationsFromConfig()
{
$conf = $this->getConf();
$rel = $conf->getVal('issue_relations', IDF_Form_IssueTrackingConf::init_relations);
$relations = array();
foreach (preg_split("/\015\012|\015|\012/", $rel, -1, PREG_SPLIT_NO_EMPTY) as $s) {
$verbs = preg_split("/\s*,\s*/", $s, 2);
if (count($verbs) == 1)
$relations += array($verbs[0] => $verbs[0]);
else
$relations += array($verbs[0] => $verbs[1], $verbs[1] => $verbs[0]);
}
return $relations;
}
/** /**
* Return membership data. * Return membership data.
* *

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -88,22 +88,36 @@ class IDF_Scm
} }
/** /**
* Run exec and log some information. * Runs the given command and log some information.
*
* A previous version used plain exec(), but this should not be used
* for various reasons, one being that this command does not preserve
* trailing whitespace, which is essential for proper diff parsing.
* *
* @param $caller Calling method * @param $caller Calling method
* @param $cmd Command to run * @param $cmd Command to run
* @param &$out Array of output * @param &$out Array of output
* @param &$return Return value * @param &$return Return value
* @return string Last line of the command
*/ */
public static function exec($caller, $cmd, &$out=null, &$return=null) public static function exec($caller, $cmd, &$out=null, &$return=null)
{ {
$return = -1;
Pluf_Log::stime('timer'); Pluf_Log::stime('timer');
$ret = exec($cmd, $out, $return); $fp = popen($cmd, 'r');
$buf = '';
if ($fp !== false) {
while (!feof($fp)) {
$buf .= fread($fp, 1024);
}
$return = pclose($fp);
}
$out = preg_split('/\r\n|\r|\n/', $buf);
$elem = count($out);
if ($elem > 0 && $out[$elem-1] === '')
unset($out[$elem-1]);
Pluf_Log::perf(array($caller, $cmd, Pluf_Log::etime('timer', 'total_exec'))); Pluf_Log::perf(array($caller, $cmd, Pluf_Log::etime('timer', 'total_exec')));
Pluf_Log::debug(array($caller, $cmd, $out)); Pluf_Log::debug(array($caller, $cmd, $out));
Pluf_Log::inc('exec_calls'); Pluf_Log::inc('exec_calls');
return $ret;
} }
/** /**
@@ -325,7 +339,8 @@ class IDF_Scm
* stdClass object { * stdClass object {
* 'additions' => array('path/to/file', 'path/to/directory', ...), * 'additions' => array('path/to/file', 'path/to/directory', ...),
* 'deletions' => array('path/to/file', 'path/to/directory', ...), * 'deletions' => array('path/to/file', 'path/to/directory', ...),
* 'renames' => array('old/path/to/file' => 'new/path/to/file', ...) * 'renames' => array('old/path/to/file' => 'new/path/to/file', ...),
* 'copies' => array('path/to/source' => 'path/to/target', ...),
* 'patches' => array('path/to/file', ...), * 'patches' => array('path/to/file', ...),
* 'properties' => array('path/to/file' => array( * 'properties' => array('path/to/file' => array(
* 'propname' => 'propvalue', 'deletedprop' => null, ...) * 'propname' => 'propvalue', 'deletedprop' => null, ...)

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

View File

@@ -3,7 +3,7 @@
/* /*
# ***** BEGIN LICENSE BLOCK ***** # ***** BEGIN LICENSE BLOCK *****
# This file is part of InDefero, an open source project management application. # This file is part of InDefero, an open source project management application.
# Copyright (C) 2008 Céondo Ltd and contributors. # Copyright (C) 2008-2011 Céondo Ltd and contributors.
# #
# InDefero is free software; you can redistribute it and/or modify # InDefero is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by

Some files were not shown because too many files have changed in this diff Show More