Merge lp:~jameinel/launchpad/lp-service into lp:launchpad
- lp-service
- Merge into devel
Status: | Rejected |
---|---|
Rejected by: | Martin Pool |
Proposed branch: | lp:~jameinel/launchpad/lp-service |
Merge into: | lp:launchpad |
Diff against target: |
10039 lines (+6605/-777) 133 files modified
Makefile (+1/-1) bzrplugins/lpserve/__init__.py (+743/-4) bzrplugins/lpserve/test_lpserve.py (+541/-0) configs/development/launchpad-lazr.conf (+1/-0) database/replication/Makefile (+15/-7) database/replication/slon_ctl.py (+4/-2) database/sampledata/current-dev.sql (+105/-70) database/sampledata/current.sql (+269/-162) database/schema/comments.sql (+45/-2) database/schema/launchpad_session.sql (+3/-4) database/schema/patch-2208-08-1.sql (+9/-0) database/schema/patch-2208-08-2.sql (+8/-0) database/schema/patch-2208-08-3.sql (+8/-0) database/schema/patch-2208-09-0.sql (+38/-0) database/schema/patch-2208-10-0.sql (+25/-0) database/schema/patch-2208-11-0.sql (+30/-0) database/schema/patch-2208-12-0.sql (+17/-0) database/schema/patch-2208-13-0.sql (+17/-0) database/schema/patch-2208-14-0.sql (+9/-0) database/schema/patch-2208-15-0.sql (+7/-0) database/schema/patch-2208-16-0.sql (+8/-0) database/schema/patch-2208-17-0.sql (+18/-0) database/schema/security.cfg (+57/-1) lib/canonical/config/schema-lazr.conf (+17/-0) lib/canonical/launchpad/icing/style-3-0.css.in (+1/-1) lib/canonical/launchpad/interfaces/__init__.py (+2/-0) lib/canonical/launchpad/interfaces/_schema_circular_imports.py (+10/-0) lib/canonical/launchpad/scripts/runlaunchpad.py (+50/-0) lib/canonical/launchpad/webapp/interfaces.py (+4/-0) lib/canonical/launchpad/webapp/servers.py (+23/-19) lib/canonical/launchpad/webapp/tests/test_servers.py (+14/-0) lib/canonical/launchpad/zcml/librarian.zcml (+1/-1) lib/lp/app/templates/base-layout-macros.pt (+2/-0) lib/lp/bugs/browser/bugattachment.py (+11/-20) lib/lp/bugs/browser/tests/test_bugattachment_edit_view.py (+107/-0) lib/lp/bugs/configure.zcml (+46/-0) lib/lp/bugs/doc/initial-bug-contacts.txt (+1/-1) lib/lp/bugs/interfaces/bugtracker.py (+89/-0) lib/lp/bugs/model/bugmessage.py (+2/-0) lib/lp/bugs/model/bugsubscriptionfilter.py (+36/-0) lib/lp/bugs/model/bugsubscriptionfilterimportance.py (+29/-0) lib/lp/bugs/model/bugsubscriptionfilterstatus.py (+29/-0) lib/lp/bugs/model/bugsubscriptionfiltertag.py (+29/-0) lib/lp/bugs/model/bugtracker.py (+140/-7) lib/lp/bugs/model/tests/test_bugsubscriptionfilter.py (+66/-0) lib/lp/bugs/model/tests/test_bugsubscriptionfilterimportance.py (+54/-0) lib/lp/bugs/model/tests/test_bugsubscriptionfilterstatus.py (+52/-0) lib/lp/bugs/model/tests/test_bugsubscriptionfiltertag.py (+51/-0) lib/lp/bugs/tests/has-bug-supervisor.txt (+1/-1) lib/lp/bugs/tests/test_bugtracker_components.py (+176/-0) lib/lp/buildmaster/interfaces/buildfarmjob.py (+10/-1) lib/lp/buildmaster/interfaces/packagebuild.py (+0/-6) lib/lp/buildmaster/model/buildfarmjob.py (+5/-2) lib/lp/code/browser/branch.py (+14/-0) lib/lp/code/browser/branchmergeproposal.py (+9/-2) lib/lp/code/browser/codereviewcomment.py (+39/-35) lib/lp/code/browser/configure.zcml (+10/-3) lib/lp/code/browser/tests/test_branchmergeproposal.py (+21/-2) lib/lp/code/browser/tests/test_codereviewcomment.py (+26/-9) lib/lp/code/doc/branch.txt (+1/-0) lib/lp/code/interfaces/branchrevision.py (+0/-2) lib/lp/code/model/branch.py (+11/-3) lib/lp/code/model/branchmergeproposal.py (+1/-1) lib/lp/code/model/branchrevision.py (+1/-2) lib/lp/code/model/tests/test_branchjob.py (+1/-3) lib/lp/code/templates/codereviewcomment-body.pt (+2/-2) lib/lp/code/templates/codereviewcomment-header.pt (+3/-3) lib/lp/codehosting/sshserver/session.py (+289/-11) lib/lp/codehosting/sshserver/tests/test_session.py (+73/-0) lib/lp/codehosting/tests/test_lpserve.py (+11/-60) lib/lp/registry/browser/configure.zcml (+25/-0) lib/lp/registry/browser/distroseries.py (+9/-8) lib/lp/registry/browser/distroseriesdifference.py (+160/-0) lib/lp/registry/browser/tests/test_distroseriesdifference_views.py (+293/-0) lib/lp/registry/browser/tests/test_distroseriesdifference_webservice.py (+99/-0) lib/lp/registry/browser/tests/test_series_views.py (+35/-7) lib/lp/registry/browser/tests/test_sourcepackage_views.py (+1/-1) lib/lp/registry/configure.zcml (+30/-97) lib/lp/registry/enum.py (+4/-4) lib/lp/registry/interfaces/distroseriesdifference.py (+54/-5) lib/lp/registry/interfaces/distroseriesdifferencecomment.py (+19/-2) lib/lp/registry/interfaces/productseries.py (+1/-10) lib/lp/registry/interfaces/structuralsubscription.py (+48/-30) lib/lp/registry/javascript/distroseriesdifferences_details.js (+304/-0) lib/lp/registry/model/distroseriesdifference.py (+102/-27) lib/lp/registry/model/distroseriesdifferencecomment.py (+28/-3) lib/lp/registry/model/milestone.py (+5/-3) lib/lp/registry/model/structuralsubscription.py (+20/-31) lib/lp/registry/stories/packaging/xx-sourcepackage-packaging.txt (+1/-1) lib/lp/registry/templates/distroseries-localdifferences.pt (+16/-7) lib/lp/registry/templates/distroseriesdifference-listing-extra.pt (+62/-0) lib/lp/registry/templates/distroseriesdifferencecomment-fragment.pt (+2/-0) lib/lp/registry/tests/test_distroseriesdifference.py (+168/-20) lib/lp/registry/tests/test_distroseriesdifferencecomment.py (+26/-2) lib/lp/registry/windmill/tests/test_distroseriesdifference_expander.py (+86/-0) lib/lp/services/comments/browser/configure.zcml (+12/-4) lib/lp/services/comments/interfaces/conversation.py (+18/-0) lib/lp/services/comments/templates/comment-body.pt (+8/-0) lib/lp/services/comments/templates/comment-header.pt (+9/-0) lib/lp/soyuz/browser/configure.zcml (+0/-7) lib/lp/soyuz/browser/distroarchseries.py (+2/-1) lib/lp/soyuz/browser/tests/test_distroarchseries_view.py (+51/-0) lib/lp/soyuz/configure.zcml (+12/-0) lib/lp/soyuz/doc/distroarchseries.txt (+10/-0) lib/lp/soyuz/doc/package-arch-specific.txt (+11/-0) lib/lp/soyuz/interfaces/distributionjob.py (+66/-0) lib/lp/soyuz/interfaces/distroarchseries.py (+6/-0) lib/lp/soyuz/model/distributionjob.py (+112/-0) lib/lp/soyuz/model/distroarchseries.py (+1/-0) lib/lp/soyuz/model/initialisedistroseriesjob.py (+48/-0) lib/lp/soyuz/model/publishing.py (+7/-1) lib/lp/soyuz/model/queue.py (+18/-8) lib/lp/soyuz/pas.py (+2/-1) lib/lp/soyuz/scripts/initialise_distroseries.py (+2/-1) lib/lp/soyuz/scripts/tests/test_copypackage.py (+38/-0) lib/lp/soyuz/scripts/tests/test_initialise_distroseries.py (+21/-0) lib/lp/soyuz/tests/test_initialisedistroseriesjob.py (+74/-0) lib/lp/soyuz/tests/test_publishing.py (+22/-20) lib/lp/soyuz/tests/test_publishing_top_level_api.py (+40/-1) lib/lp/testing/__init__.py (+40/-4) lib/lp/testing/factory.py (+58/-1) lib/lp/testing/tests/test_testing.py (+43/-0) lib/lp/translations/browser/configure.zcml (+17/-0) lib/lp/translations/browser/tests/test_translationtemplatesbuild.py (+84/-0) lib/lp/translations/browser/translationtemplatesbuild.py (+63/-0) lib/lp/translations/configure.zcml (+17/-0) lib/lp/translations/interfaces/translationtemplatesbuild.py (+49/-0) lib/lp/translations/model/translationtemplatesbuild.py (+117/-0) lib/lp/translations/model/translationtemplatesbuildbehavior.py (+4/-2) lib/lp/translations/model/translationtemplatesbuildjob.py (+21/-14) lib/lp/translations/stories/buildfarm/xx-build-summary.txt (+89/-4) lib/lp/translations/templates/translationtemplatesbuild-index.pt (+133/-0) lib/lp/translations/tests/test_translationtemplatesbuild.py (+134/-0) |
To merge this branch: | bzr merge lp:~jameinel/launchpad/lp-service |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
John A Meinel (community) | Needs Resubmitting | ||
Andrew Bennetts (community) | Needs Resubmitting | ||
Jonathan Lange | Pending | ||
Review via email: mp+35877@code.launchpad.net |
Commit message
Implement LaunchpadForkin
Description of the change
I'm pretty sure this code is based on the 'launchpad/devel' branch, but it might be db-devel.
The goal of this submission is to improve the time for "bzr+ssh" to connect and be useful. The new method must be activated by setting:
[codehosting]
use_forking_
It is set to be enabled in "development" mode, but the default is still disabled. I can't give a recommendation for the production config, because the branch is private.
This implements a new service (LaunchpadForki
The benefit is seen with: time echo hello | ssh localhost bzr serve --inet ...
Without this patch, it is 2.5s to serve on the loopback. With this patch, it is 0.25s.
I'm very happy to work with someone to smooth out the finer points of this submission. I tried to be explicit about places in the code that I had a decision to make, and why I chose the method I did.
I didn't use the FeatureFlag system, because setting it up via the config file was a lot more straightforward. (globally enabling/disabling the functionality).
As near as I can tell, there should be no impact of rolling this code out on production, if use_forking_daemon: False.
(The make run_codehosting will not actually spawn the daemon, and the twisted Conch code just gets an 'if ' check to see that it should use the old code path.)
I haven't run the full test suite, but I have:
1) Run all of the locally relevant tests "bzr selftest -s bt.lp_serve' and 'bin/test
lp.
2) Manually started the sftp service and run commands through the local instance. Both with
and without the forking service enabled. (And I have confirmed that it isn't used when
disabled, and is used when enabled, etc.)
John A Meinel (jameinel) wrote : | # |
Martin Pool (mbp) wrote : | # |
That's a great improvement in time.
I think (per your decision 1) it would be good to change it to a unix-domain socket, for the sake of a bit more security, and better reusability as a per-user thing.
Per http://
> System programs that maintain transient UNIX-domain sockets must place them in this directory.
which will require sysadmins making a directory under there that's writable by this process. That can be in the config file. You should just need socket.
Having a config option to turn this on is great. We could make it active only on staging at first and see the effect.
481 + while not self._should_
482 + try:
483 + conn, client_addr = self._server_
484 + except self._socket_
485 + pass # run shutdown and children checks
486 + except self._socket_error, e:
487 + if e.args[0] == errno.EINTR:
488 + pass # run shutdown and children checks
489 + elif e.args[0] != errno.EBADF:
490 + # We can get EBADF here while we are shutting down
491 + # So we just ignore it for now
492 + pass
It seems like this might spin if the server socket's closed and there are no dead children.
+ fifos on the filesystem, and start running the requseted command. The
typo
We should do some kind of plan or review with LOSAs on how to deploy and support this. We should configure it to log to a file, and for that to be synced to devpad. Putting the pid in the log file would be nice.
John A Meinel (jameinel) wrote : | # |
First off, my apologies for accidentally including some db changes in this patch.
I went for a default socket location of '/var/run/
...
> It seems like this might spin if the server socket's closed and there are no dead children.
I'm not sure how you would get the server socket closed inside this process. Regardless, children shouldn't affect whether it spins or not. We just need a way to set '_should_
So, yes, if self._server_
I suppose I could put a "self._
I do put PID into the log file, but bzr does not for each mutter() request. So when spawning I indicate that PID started, etc. But each individual message doesn't. mutter() does its own formatting, so it is a matter of changing these lines:
=== modified file 'bzrlib/trace.py'
--- bzrlib/trace.py 2010-06-28 02:41:22 +0000
+++ bzrlib/trace.py 2010-09-22 20:15:56 +0000
@@ -183,7 +183,7 @@
else:
out = fmt
now = time.time()
- timestamp = '%0.3f ' % (now - _bzr_log_
+ timestamp = '%0.3f [%d] ' % (now - _bzr_log_
out = timestamp + out + '\n'
_trace_
# there's no explicit flushing; the file is typically line buffered.
Andrew Bennetts (spiv) wrote : | # |
There are many unrelated changes in this diff, which is part of why the line
count is so enormous. I guess the target branch isn't the one you branched
from? It does make the review harder than it should be, and certainly much
more intimidating at a glance than it deserves, so it'd be worth fixing :)
SIGCHLD: is this handler uninstalled in the child? If not, there's a risk of
EINTR issues if the child spawns its own subprocesses. Ah, yes, it is. Good :)
> + # [Decision #4]
> + # Exit information
> + # How do we inform the client process that the child has exited?
This section seems to describe the questions without clearly stating what the
answer was. I have to read through the wall of text fairly carefully to see
what the choice was.
> + # There is some possibility that files won't get flushed, etc. So we
> + # may want to be calling sys.exitfunc() first. Note that bzr itself
Yes, I think it would be good to call sys.exitfunc() for the reasons you give.
I'd be particularly worried about incompletely written log files... it would be
a shame to have the most interesting log content never get flushed! (The end of
the log is often the most interesting bit.)
> + # [Decision #8]
> + # env vars
This section doesn't make clear what the issue is, nor what the conclusion is.
What does “this data” refer to? Are env vars the problem, or solution to some
problem?
> + # [Decision #9]
> + # nicer errors to clients
> + # This service is meant to be run only on the local system. As such,
> + # we don't try to be extra defensive about leaking information to
> + # clients. Instead we try to be helpful, and tell them as much as we
> + # know about what went wrong.
The client is connected to a remote user though. So the information returned
here won't be repeated back to that remote client?
I'm worried about this becase we already echo more information back to the
remote client than really makes sense, e.g. random warnings on stderr are sent
to the remote client, and tend to confuse users.
> + _fork_function = os.fork
I assume this is to make unit testing easier, which is fine. Peeking ahead in
the diff I see that you test this at least in part by subclassing, which isn't
so great: I feel it violates the “Use the front door first” guideline for tests,
because this isn't a class intended for subclassing in production code, so the
tests are assuming a more intimate (and not sharply defined) interface with this
code than is ideal. I'm not sure it's worth spending effort trying to find a
better way, but hopefully you finding this interesting food for thought.
> + # XXX: Cheap hack. by this point bzrlib has opened stderr for logging
> + # (as part of starting the service process in the first place). As
> + # such, it has a stream handler that writes to stderr. logging
> + # tries to flush and close that, but the file is already closed.
> + # This just supresses that exception
> + logging.
IIRC the Launchpad coding standard requires XXX comments to have a name and date
a...
Martin Pool (mbp) wrote : | # |
>> === added file 'lp_service_
> I don't think this belongs in the root of the tree.
fwiw, my inclination is to add docstrings, not comments or text files, because they more easily show up in <http://
Martin Pool (mbp) wrote : | # |
<mwhudson> poolie: the branch has conflicts with db-devel it seems
<mwhudson> jam: can you merge db-devel, fix the conflicts and repropose it against db-devel?
John A Meinel (jameinel) wrote : | # |
I've done the changes, but I'm rejecting this in favor of an updated merge w/ db-devel and proposing against db-devel directly.
John A Meinel (jameinel) wrote : | # |
(note that I'm not authorized to reject my own submission, I can only delete it, but I don't want to lose the conversation)
Andrew Bennetts (spiv) wrote : | # |
John Arbash Meinel wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Unfortunately this won't get put on the MP, because Launchpad now
> rejects all my emails. But I really wanted to reply to your comments inline.
Ok. I won't trim the quoted text for other people's benefit. Warm up those
scrolling fingers!
>
>
>
> ...
>
> >> + # [Decision #4]
> >> + # Exit information
> >> + # How do we inform the client process that the child has exited?
> >
> > This section seems to describe the questions without clearly stating what the
> > answer was. I have to read through the wall of text fairly carefully to see
> > what the choice was.
>
> New summary.
>
> >
> >> + # There is some possibility that files won't get flushed, etc. So we
> >> + # may want to be calling sys.exitfunc() first. Note that bzr itself
> >
> > Yes, I think it would be good to call sys.exitfunc() for the reasons you give.
> > I'd be particularly worried about incompletely written log files... it would be
> > a shame to have the most interesting log content never get flushed! (The end of
> > the log is often the most interesting bit.)
>
> I switched to this, though I'm not really sure it is the right thing.
> (When *do* buffered files get synced to disk? It seems that it might be
> during stack unwinding, which we explicitly avoid via os._exitfunc(),
> which bzr has been doing for a long time now...)
We call os._exitfunc from the outermost frame, so we don't avoid any stack
unwinding.
We do it to avoid wasting time that would be spent garbage collecting perhaps
100000s of objects when the OS can free that memory for us more cheaply.
>
>
> >
> >> + # [Decision #8]
> >> + # env vars
> >
> > This section doesn't make clear what the issue is, nor what the conclusion is.
> > What does “this data” refer to? Are env vars the problem, or solution to some
> > problem?
>
> Removed. Passing env vars from the Twisted process to the spawned child
> is a bit tricky. I did end up going with a syntax that can be parsed
> without ambiguity, though it is limited to 8-bit without encoding
> information. (AFAIK, so are real env vars)
>
> >
> >> + # [Decision #9]
> >> + # nicer errors to clients
> >> + # This service is meant to be run only on the local system. As such,
> >> + # we don't try to be extra defensive about leaking information to
> >> + # clients. Instead we try to be helpful, and tell them as much as we
> >> + # know about what went wrong.
> >
> > The client is connected to a remote user though. So the information returned
> > here won't be repeated back to that remote client?
>
> Wrong client. The 'client' here is twisted. I clarified it with:
> nicer errors on the request socket
Ok.
>
> >
> > I'm worried about this becase we already echo more information back to the
> > remote client than really makes sense, e.g. random warnings on stderr are sent
> > to the remote client, and tend to confuse users.
>
> That is true, though often the alternative would be to tell them
> nothing, which would have been worse. (Getting Permission Error can be
> confusing when i...
Martin Pool (mbp) wrote : | # |
This is replaced by https:/
Preview Diff
1 | === modified file 'Makefile' |
2 | --- Makefile 2010-09-07 18:15:01 +0000 |
3 | +++ Makefile 2010-10-04 22:08:24 +0000 |
4 | @@ -253,7 +253,7 @@ |
5 | |
6 | run_codehosting: check_schema inplace stop |
7 | $(RM) thread*.request |
8 | - bin/run -r librarian,sftp,codebrowse -i $(LPCONFIG) |
9 | + bin/run -r librarian,sftp,forker,codebrowse -i $(LPCONFIG) |
10 | |
11 | |
12 | start_librarian: compile |
13 | |
14 | === added directory 'bzrplugins/lpserve' |
15 | === renamed file 'bzrplugins/lpserve.py' => 'bzrplugins/lpserve/__init__.py' |
16 | --- bzrplugins/lpserve.py 2010-04-19 06:35:23 +0000 |
17 | +++ bzrplugins/lpserve/__init__.py 2010-10-04 22:08:24 +0000 |
18 | @@ -8,15 +8,33 @@ |
19 | |
20 | __metaclass__ = type |
21 | |
22 | -__all__ = ['cmd_launchpad_server'] |
23 | - |
24 | - |
25 | +__all__ = ['cmd_launchpad_server', |
26 | + 'cmd_launchpad_forking_service', |
27 | + ] |
28 | + |
29 | + |
30 | +import errno |
31 | +import os |
32 | import resource |
33 | +import shlex |
34 | +import shutil |
35 | +import signal |
36 | +import socket |
37 | import sys |
38 | +import tempfile |
39 | +import threading |
40 | +import time |
41 | |
42 | from bzrlib.commands import Command, register_command |
43 | from bzrlib.option import Option |
44 | -from bzrlib import lockdir, ui |
45 | +from bzrlib import ( |
46 | + commands, |
47 | + errors, |
48 | + lockdir, |
49 | + osutils, |
50 | + trace, |
51 | + ui, |
52 | + ) |
53 | |
54 | from bzrlib.smart import medium, server |
55 | from bzrlib.transport import get_transport |
56 | @@ -110,3 +128,724 @@ |
57 | |
58 | |
59 | register_command(cmd_launchpad_server) |
60 | + |
61 | + |
62 | +class LPForkingService(object): |
63 | + """A service that can be asked to start a new bzr subprocess via fork. |
64 | + |
65 | + The basic idea is that python startup is very expensive. For example, the |
66 | + original 'lp-serve' command could take 2.5s just to start up, before any |
67 | + actual actions could be performed. |
68 | + |
69 | + This class provides a service sitting on a socket, which can then be |
70 | + requested to fork and run a given bzr command. |
71 | + |
72 | + Clients connect to the socket and make a simple request, which then |
73 | + receives a response. The possible requests are: |
74 | + |
75 | + "hello\n": Trigger a heartbeat to report that the program is still |
76 | + running, and write status information to the log file. |
77 | + "quit\n": Stop the service, but do so 'nicely', waiting for children |
78 | + to exit, etc. Once this is received the service will stop |
79 | + taking new requests on the port. |
80 | + "fork <command>\n": Request a new subprocess to be started. |
81 | + <command> is the bzr command to be run, such as "rocks" or |
82 | + "lp-serve --inet 12". |
83 | + The immediate response will be the path-on-disk to a directory full |
84 | + of named pipes (fifos) that will be the stdout/stderr/stdin of the |
85 | + new process. |
86 | + If a client holds the socket open, when the child process exits, |
87 | + the exit status (as given by 'wait()') will be written to the |
88 | + socket. |
89 | + |
90 | + Note that one of the key bits is that the client will not be |
91 | + started with exec*, we just call 'commands.run_bzr*()' directly. |
92 | + This way, any modules that are already loaded will not need to be |
93 | + loaded again. However, care must be taken with any global-state |
94 | + that should be reset. |
95 | + """ |
96 | + |
97 | + # Design decisions. These are bits where we could have chosen a different |
98 | + # method/implementation and weren't sure what would be best. Documenting |
99 | + # the current decision, and the alternatives. |
100 | + # |
101 | + # [Decision #1] |
102 | + # Serve on a named AF_UNIX socket. |
103 | + # 1) It doesn't make sense to serve to arbitrary hosts, we only want |
104 | + # the local host to make requests. (Since the client needs to |
105 | + # access the named fifos on the current filesystem.) |
106 | + # 2) You can set security parameters on a filesystem path (g+rw, |
107 | + # a-rw). |
108 | + # [Decision #2] |
109 | + # SIGCHLD |
110 | + # We want to quickly detect that children have exited so that we can |
111 | + # inform the client process quickly. At the moment, we register a |
112 | + # SIGCHLD handler that doesn't do anything. However, it means that |
113 | + # when we get the signal, if we are currently blocked in something |
114 | + # like '.accept()', we will jump out temporarily. At that point the |
115 | + # main loop will check if any children have exited. We could have |
116 | + # done this work as part of the signal handler, but that felt 'racy' |
117 | + # doing any serious work in a signal handler. |
118 | + # If we just used socket.timeout as the indicator to go poll for |
119 | + # children exiting, it slows the disconnect by as much as the full |
120 | + # timeout. (So a timeout of 1.0s will cause the process to hang by |
121 | + # that long until it determines that a child has exited, and can |
122 | + # close the connection.) |
123 | + # The current flow means that we'll notice exited children whenever |
124 | + # we finish the current work. |
125 | + # [Decision #3] |
126 | + # Child vs Parent actions. |
127 | + # There are several actions that are done when we get a new request. |
128 | + # We have to create the fifos on disk, fork a new child, connect the |
129 | + # child to those handles, and inform the client of the new path (not |
130 | + # necessarily in that order.) It makes sense to wait to send the path |
131 | + # message until after the fifos have been created. That way the |
132 | + # client can just try to open them immediately, and the |
133 | + # client-and-child will be synchronized by the open() calls. |
134 | + # However, should the client be the one doing the mkfifo, should the |
135 | + # server? Who should be sending the message? Should we fork after the |
136 | + # mkfifo or before. |
137 | + # The current thoughts: |
138 | + # 1) Try to do work in the child when possible. This should allow |
139 | + # for 'scaling' because the server is single-threaded. |
140 | + # 2) We create the directory itself in the server, because that |
141 | + # allows the server to monitor whether the client failed to |
142 | + # clean up after itself or not. |
143 | + # 3) Otherwise we create the fifos in the client, and then send |
144 | + # the message back. |
145 | + # [Decision #4] |
146 | + # Exit information |
147 | + # Inform the client that the child has exited on the socket they used |
148 | + # to request the fork. |
149 | + # 1) Arguably they could see that stdout and stderr have been closed, |
150 | + # and thus stop reading. In testing, I wrote a client which uses |
151 | + # select.poll() over stdin/stdout/stderr and used that to ferry |
152 | + # the content to the appropriate local handle. However for the |
153 | + # FIFOs, when the remote end closed, I wouldn't see any |
154 | + # corresponding information on the local end. There obviously |
155 | + # wasn't any data to be read, so they wouldn't show up as |
156 | + # 'readable' (for me to try to read, and get 0 bytes, indicating |
157 | + # it was closed). I also wasn't seeing POLLHUP, which seemed to be |
158 | + # the correct indicator. As such, we decided to inform the client |
159 | + # on the socket that they originally made the fork request, rather |
160 | + # than just closing the socket immediately. |
161 | + # 2) We could have had the forking server close the socket, and only |
162 | + # the child hold the socket open. When the child exits, then the |
163 | + # OS naturally closes the socket. |
164 | + # If we want the returncode, then we should put that as bytes on |
165 | + # the socket before we exit. Having the child do the work means |
166 | + # that in error conditions, it could easily die before being able to |
167 | + # write anything (think SEGFAULT, etc). The forking server is |
168 | + # already 'wait'() ing on its children. So that we don't get |
169 | + # zombies, and with wait3() we can get the rusage (user time, |
170 | + # memory consumption, etc.) |
171 | + # As such, it seems reasonable that the server can then also |
172 | + # report back when a child is seen as exiting. |
173 | + # [Decision #5] |
174 | + # cleanup once connected |
175 | + # The child process blocks during 'open()' waiting for the client to |
176 | + # connect to its fifos. Once the client has connected, the child then |
177 | + # deletes the temporary directory and the fifos from disk. This means |
178 | + # that there isn't much left for diagnosis, but it also means that |
179 | + # the client won't leave garbage around if it crashes, etc. |
180 | + # Note that the forking service itself still monitors the paths |
181 | + # created, and will delete garbage if it sees that a child failed to |
182 | + # do so. |
183 | + # [Decision #6] |
184 | + # os._exit(retcode) in the child |
185 | + # Calling sys.exit(retcode) raises an exception, which then bubbles |
186 | + # up the stack and runs exit functions (and finally statements). When |
187 | + # I tried using it originally, I would see the current child bubble |
188 | + # all the way up the stack (through the server code that it fork() |
189 | + # through), and then get to main() returning code 0. The process |
190 | + # would still exit nonzero. My guess is that something in the atexit |
191 | + # functions was failing, but that it was happening after logging, etc |
192 | + # had been shut down. |
193 | + # Any global state from the child process should be flushed before |
194 | + # run_bzr_* has exited (which we *do* wait for), and any other global |
195 | + # state is probably a remnant from the service process. Which will be |
196 | + # cleaned up by the service itself, rather than the child. |
197 | + # There is some concern that log files may not get flushed, so we |
198 | + # currently call sys.exitfunc() first. The main problem is that I |
199 | + # don't know any way to *remove* a function registered via 'atexit()' |
200 | + # so if the forking service has some state, we my try to clean it up |
201 | + # incorrectly. |
202 | + # Note that the bzr script itself uses sys.exitfunc(); os._exit() in |
203 | + # the 'bzr' main script, as the teardown time of all the python state |
204 | + # was quite noticeable in real-world runtime. As such, bzrlib should |
205 | + # be pretty safe, or it would have been failing for people already. |
206 | + # [Decision #7] |
207 | + # prefork vs max children vs ? |
208 | + # For simplicity it seemed easiest to just fork when requested. Over |
209 | + # time, I realized it would be easy to allow running an arbitrary |
210 | + # command (no harder than just running one command), so it seemed |
211 | + # reasonable to switch over. If we go the prefork route, then we'll |
212 | + # need a way to tell the pre-forked children what command to run. |
213 | + # This could be as easy as just adding one more fifo that they wait |
214 | + # on in the same directory. |
215 | + # For now, I've chosen not to limit the number of forked children. I |
216 | + # don't know what a reasonable value is, and probably there are |
217 | + # already limitations at play. (If Conch limits connections, then it |
218 | + # will already be doing all the work, etc.) |
219 | + # [Decision #8] |
220 | + # nicer errors on the request socket |
221 | + # This service is meant to be run only on the local system. As such, |
222 | + # we don't try to be extra defensive about leaking information to |
223 | + # the one connecting to the socket. (We should still watch out what |
224 | + # we send across the per-child fifos, since those are connected to |
225 | + # remote clients.) Instead we try to be helpful, and tell them as |
226 | + # much as we know about what went wrong. |
227 | + |
228 | + DEFAULT_PATH = '/var/run/launchpad_forking_service.sock' |
229 | + DEFAULT_PERMISSIONS = 00660 # Permissions on the master socket (rw-rw----) |
230 | + WAIT_FOR_CHILDREN_TIMEOUT = 5*60 # Wait no more than 5 min for children |
231 | + SOCKET_TIMEOUT = 1.0 |
232 | + SLEEP_FOR_CHILDREN_TIMEOUT = 1.0 |
233 | + WAIT_FOR_REQUEST_TIMEOUT = 1.0 # No request should take longer than this to |
234 | + # be read |
235 | + |
236 | + _fork_function = os.fork |
237 | + |
238 | + def __init__(self, path=DEFAULT_PATH, perms=DEFAULT_PERMISSIONS): |
239 | + self.master_socket_path = path |
240 | + self._perms = perms |
241 | + self._start_time = time.time() |
242 | + self._should_terminate = threading.Event() |
243 | + # We address these locally, in case of shutdown socket may be gc'd |
244 | + # before we are |
245 | + self._socket_timeout = socket.timeout |
246 | + self._socket_error = socket.error |
247 | + self._socket_timeout = socket.timeout |
248 | + self._socket_error = socket.error |
249 | + # Map from pid => information |
250 | + self._child_processes = {} |
251 | + self._children_spawned = 0 |
252 | + |
253 | + def _create_master_socket(self): |
254 | + self._server_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
255 | + self._server_socket.bind(self.master_socket_path) |
256 | + if self._perms is not None: |
257 | + os.chmod(self.master_socket_path, self._perms) |
258 | + self._server_socket.setsockopt(socket.SOL_SOCKET, |
259 | + socket.SO_REUSEADDR, 1) |
260 | + self._sockname = self._server_socket.getsockname() |
261 | + # self.host = self._sockname[0] |
262 | + self.port = self._sockname[1] |
263 | + self._server_socket.listen(5) |
264 | + self._server_socket.settimeout(self.SOCKET_TIMEOUT) |
265 | + trace.mutter('set socket timeout to: %s' % (self.SOCKET_TIMEOUT,)) |
266 | + |
267 | + def _cleanup_master_socket(self): |
268 | + self._server_socket.close() |
269 | + try: |
270 | + os.remove(self.master_socket_path) |
271 | + except (OSError, IOError), e: |
272 | + # If we don't delete it, then we get 'address already in |
273 | + # use' failures |
274 | + trace.mutter('failed to cleanup: %s' |
275 | + % (self.master_socket_path,)) |
276 | + |
277 | + def _handle_sigchld(self, signum, frm): |
278 | + # We don't actually do anything here, we just want an interrupt (EINTR) |
279 | + # on socket.accept() when SIGCHLD occurs. |
280 | + pass |
281 | + |
282 | + def _handle_sigterm(self, signum, frm): |
283 | + # Unregister this as the default handler, 2 SIGTERMs will exit us. |
284 | + signal.signal(signal.SIGTERM, signal.SIG_DFL) |
285 | + # SIGTERM should also generate EINTR on our wait loop, so this should |
286 | + # be enough |
287 | + self._should_terminate.set() |
288 | + |
289 | + def _register_signals(self): |
290 | + """Register a SIGCHILD and SIGTERM handler. |
291 | + |
292 | + If we have a trigger for SIGCHILD then we can quickly respond to |
293 | + clients when their process exits. The main risk is getting more EAGAIN |
294 | + errors elsewhere. |
295 | + |
296 | + SIGTERM allows us to cleanup nicely before we exit. |
297 | + """ |
298 | + signal.signal(signal.SIGCHLD, self._handle_sigchld) |
299 | + signal.signal(signal.SIGTERM, self._handle_sigterm) |
300 | + |
301 | + def _unregister_signals(self): |
302 | + signal.signal(signal.SIGCHLD, signal.SIG_DFL) |
303 | + signal.signal(signal.SIGTERM, signal.SIG_DFL) |
304 | + |
305 | + def _create_child_file_descriptors(self, base_path): |
306 | + stdin_path = os.path.join(base_path, 'stdin') |
307 | + stdout_path = os.path.join(base_path, 'stdout') |
308 | + stderr_path = os.path.join(base_path, 'stderr') |
309 | + os.mkfifo(stdin_path) |
310 | + os.mkfifo(stdout_path) |
311 | + os.mkfifo(stderr_path) |
312 | + |
313 | + def _bind_child_file_descriptors(self, base_path): |
314 | + import logging |
315 | + from bzrlib import ui |
316 | + stdin_path = os.path.join(base_path, 'stdin') |
317 | + stdout_path = os.path.join(base_path, 'stdout') |
318 | + stderr_path = os.path.join(base_path, 'stderr') |
319 | + # Opening for writing blocks (or fails), so do those last |
320 | + # TODO: Consider buffering, though that might interfere with reading |
321 | + # and writing the smart protocol |
322 | + stdin_fid = os.open(stdin_path, os.O_RDONLY) |
323 | + stdout_fid = os.open(stdout_path, os.O_WRONLY) |
324 | + stderr_fid = os.open(stderr_path, os.O_WRONLY) |
325 | + # Note: by this point bzrlib has opened stderr for logging |
326 | + # (as part of starting the service process in the first place). As |
327 | + # such, it has a stream handler that writes to stderr. logging |
328 | + # tries to flush and close that, but the file is already closed. |
329 | + # This just supresses that exception |
330 | + logging.raiseExceptions = False |
331 | + sys.stdin.close() |
332 | + sys.stdout.close() |
333 | + sys.stderr.close() |
334 | + os.dup2(stdin_fid, 0) |
335 | + os.dup2(stdout_fid, 1) |
336 | + os.dup2(stderr_fid, 2) |
337 | + sys.stdin = os.fdopen(stdin_fid, 'rb') |
338 | + sys.stdout = os.fdopen(stdout_fid, 'wb') |
339 | + sys.stderr = os.fdopen(stderr_fid, 'wb') |
340 | + ui.ui_factory.stdin = sys.stdin |
341 | + ui.ui_factory.stdout = sys.stdout |
342 | + ui.ui_factory.stderr = sys.stderr |
343 | + # Now that we've opened the handles, delete everything so that we don't |
344 | + # leave garbage around. Because the open() is done in blocking mode, we |
345 | + # know that someone has already connected to them, and we don't want |
346 | + # anyone else getting confused and connecting. |
347 | + # See [Decision #5] |
348 | + os.remove(stderr_path) |
349 | + os.remove(stdout_path) |
350 | + os.remove(stdin_path) |
351 | + os.rmdir(base_path) |
352 | + |
353 | + def _close_child_file_descriptons(self): |
354 | + sys.stdin.close() |
355 | + sys.stderr.close() |
356 | + sys.stdout.close() |
357 | + |
358 | + def become_child(self, command_argv, path): |
359 | + """We are in the spawned child code, do our magic voodoo.""" |
360 | + # Stop tracking new signals |
361 | + self._unregister_signals() |
362 | + # Reset the start time |
363 | + trace._bzr_log_start_time = time.time() |
364 | + trace.mutter('%d starting %r' |
365 | + % (os.getpid(), command_argv,)) |
366 | + self.host = None |
367 | + self.port = None |
368 | + self._sockname = None |
369 | + self._bind_child_file_descriptors(path) |
370 | + self._run_child_command(command_argv) |
371 | + |
372 | + def _run_child_command(self, command_argv): |
373 | + # This is the point where we would actually want to do something with |
374 | + # our life |
375 | + # TODO: We may want to consider special-casing the 'lp-serve' command. |
376 | + # As that is the primary use-case for this service, it might be |
377 | + # interesting to have an already-instantiated instance, where we |
378 | + # can just pop on an extra argument and be ready to go. However, |
379 | + # that would probably only really be measurable if we prefork. As |
380 | + # it looks like ~200ms is 'fork()' time, but only 50ms is |
381 | + # run-the-command time. |
382 | + retcode = commands.run_bzr_catch_errors(command_argv) |
383 | + self._close_child_file_descriptons() |
384 | + trace.mutter('%d finished %r' |
385 | + % (os.getpid(), command_argv,)) |
386 | + # We force os._exit() here, because we don't want to unwind the stack, |
387 | + # which has complex results. (We can get it to unwind back to the |
388 | + # cmd_launchpad_forking_service code, and even back to main() reporting |
389 | + # thereturn code, but after that, suddenly the return code changes from |
390 | + # a '0' to a '1', with no logging of info. |
391 | + # TODO: Should we call sys.exitfunc() here? it allows atexit functions |
392 | + # to fire, however, some of those may be still around from the |
393 | + # parent process, which we don't really want. |
394 | + sys.exitfunc() |
395 | + # See [Decision #6] |
396 | + os._exit(retcode) |
397 | + |
398 | + @staticmethod |
399 | + def command_to_argv(command_str): |
400 | + """Convert a 'foo bar' style command to [u'foo', u'bar']""" |
401 | + # command_str must be a utf-8 string |
402 | + return [s.decode('utf-8') for s in shlex.split(command_str)] |
403 | + |
404 | + @staticmethod |
405 | + def parse_env(env_str): |
406 | + """Convert the environment information into a dict. |
407 | + |
408 | + :param env_str: A string full of environment variable declarations. |
409 | + Each key is simple ascii "key: value\n" |
410 | + The string must end with "end\n". |
411 | + :return: A dict of environment variables |
412 | + """ |
413 | + env = {} |
414 | + if not env_str.endswith('end\n'): |
415 | + raise ValueError('Invalid env-str: %r' % (env_str,)) |
416 | + env_str = env_str[:-5] |
417 | + if not env_str: |
418 | + return env |
419 | + env_entries = env_str.split('\n') |
420 | + for entry in env_entries: |
421 | + key, value = entry.split(': ', 1) |
422 | + env[key] = value |
423 | + return env |
424 | + |
425 | + def fork_one_request(self, conn, client_addr, command_argv, env): |
426 | + """Fork myself and serve a request.""" |
427 | + temp_name = tempfile.mkdtemp(prefix='lp-forking-service-child-') |
428 | + # Now that we've set everything up, send the response to the client we |
429 | + # create them first, so the client can start trying to connect to them, |
430 | + # while we fork and have the child do the same. |
431 | + self._children_spawned += 1 |
432 | + pid = self._fork_function() |
433 | + if pid == 0: |
434 | + pid = os.getpid() |
435 | + trace.mutter('%d spawned' % (pid,)) |
436 | + self._server_socket.close() |
437 | + for env_var, value in env.iteritems(): |
438 | + osutils.set_or_unset_env(env_var, value) |
439 | + # See [Decision #3] |
440 | + self._create_child_file_descriptors(temp_name) |
441 | + conn.sendall('ok\n%d\n%s\n' % (pid, temp_name)) |
442 | + conn.close() |
443 | + self.become_child(command_argv, temp_name) |
444 | + trace.warning('become_child returned!!!') |
445 | + sys.exit(1) |
446 | + else: |
447 | + self._child_processes[pid] = (temp_name, conn) |
448 | + self.log(client_addr, 'Spawned process %s for %r: %s' |
449 | + % (pid, command_argv, temp_name)) |
450 | + |
451 | + def main_loop(self): |
452 | + self._should_terminate.clear() |
453 | + self._register_signals() |
454 | + self._create_master_socket() |
455 | + trace.note('Listening on socket: %s' % (self.master_socket_path,)) |
456 | + try: |
457 | + try: |
458 | + self._do_loop() |
459 | + finally: |
460 | + # Stop talking to others, we are shutting down |
461 | + self._cleanup_master_socket() |
462 | + except KeyboardInterrupt: |
463 | + # SIGINT received, try to shutdown cleanly |
464 | + pass |
465 | + trace.note('Shutting down. Waiting up to %.0fs for %d child processes' |
466 | + % (self.WAIT_FOR_CHILDREN_TIMEOUT, |
467 | + len(self._child_processes),)) |
468 | + self._shutdown_children() |
469 | + trace.note('Exiting') |
470 | + |
471 | + def _do_loop(self): |
472 | + while not self._should_terminate.isSet(): |
473 | + try: |
474 | + conn, client_addr = self._server_socket.accept() |
475 | + except self._socket_timeout: |
476 | + pass # run shutdown and children checks |
477 | + except self._socket_error, e: |
478 | + if e.args[0] == errno.EINTR: |
479 | + pass # run shutdown and children checks |
480 | + elif e.args[0] != errno.EBADF: |
481 | + # We can get EBADF here while we are shutting down |
482 | + # So we just ignore it for now |
483 | + pass |
484 | + else: |
485 | + # Log any other failure mode |
486 | + trace.warning("listening socket error: %s", e) |
487 | + else: |
488 | + self.log(client_addr, 'connected') |
489 | + # TODO: We should probably trap exceptions coming out of this |
490 | + # and log them, so that we don't kill the service because |
491 | + # of an unhandled error |
492 | + # Note: settimeout is used so that a malformed request doesn't |
493 | + # cause us to hang forever. Note that the particular |
494 | + # implementation means that a malicious client could |
495 | + # probably send us one byte every Xms, and we would just |
496 | + # keep trying to read it. However, as a local service, we |
497 | + # aren't worrying about it. |
498 | + conn.settimeout(self.WAIT_FOR_REQUEST_TIMEOUT) |
499 | + try: |
500 | + self.serve_one_connection(conn, client_addr) |
501 | + except self._socket_timeout, e: |
502 | + trace.log_exception_quietly() |
503 | + self.log(client_addr, 'request timeout failure: %s' % (e,)) |
504 | + conn.sendall('FAILURE\nrequest timed out\n') |
505 | + conn.close() |
506 | + self._poll_children() |
507 | + |
508 | + def log(self, client_addr, message): |
509 | + """Log a message to the trace log. |
510 | + |
511 | + Include the information about what connection is being served. |
512 | + """ |
513 | + if client_addr is not None: |
514 | + # Note, we don't use conn.getpeername() because if a client |
515 | + # disconnects before we get here, that raises an exception |
516 | + conn_info = '[%s] ' % (client_addr,) |
517 | + else: |
518 | + conn_info = '' |
519 | + trace.mutter('%s%s' % (conn_info, message)) |
520 | + |
521 | + def log_information(self): |
522 | + """Log the status information. |
523 | + |
524 | + This includes stuff like number of children, and ... ? |
525 | + """ |
526 | + self._poll_children() |
527 | + self.log(None, 'Running for %.3fs' % (time.time() - self._start_time)) |
528 | + self.log(None, '%d children currently running (spawned %d total)' |
529 | + % (len(self._child_processes), self._children_spawned)) |
530 | + # Read the current information about memory consumption, etc. |
531 | + self.log(None, 'Self: %s' |
532 | + % (resource.getrusage(resource.RUSAGE_SELF),)) |
533 | + # This seems to be the sum of all rusage for all children that have |
534 | + # been collected (not for currently running children, or ones we |
535 | + # haven't "wait"ed on.) We may want to read /proc/PID/status, since |
536 | + # 'live' information is probably more useful. |
537 | + self.log(None, 'Finished children: %s' |
538 | + % (resource.getrusage(resource.RUSAGE_CHILDREN),)) |
539 | + |
540 | + def _poll_children(self): |
541 | + """See if children are still running, etc. |
542 | + |
543 | + One interesting hook here would be to track memory consumption, etc. |
544 | + """ |
545 | + while self._child_processes: |
546 | + try: |
547 | + c_id, exit_code, rusage = os.wait3(os.WNOHANG) |
548 | + except OSError, e: |
549 | + if e.errno == errno.ECHILD: |
550 | + # TODO: We handle this right now because the test suite |
551 | + # fakes a child, since we wanted to test some code |
552 | + # without actually forking anything |
553 | + trace.mutter('_poll_children() called, and' |
554 | + ' self._child_processes indicates there are' |
555 | + ' children, but os.wait3() says there are not.' |
556 | + ' current_children: %s' % (self._child_processes,)) |
557 | + return |
558 | + if c_id == 0: |
559 | + # No more children stopped right now |
560 | + return |
561 | + c_path, sock = self._child_processes.pop(c_id) |
562 | + trace.mutter('%s exited %s and usage: %s' |
563 | + % (c_id, exit_code, rusage)) |
564 | + # See [Decision #4] |
565 | + try: |
566 | + sock.sendall('exited\n%s\n' % (exit_code,)) |
567 | + except (self._socket_timeout, self._socket_error), e: |
568 | + # The client disconnected before we wanted them to, |
569 | + # no big deal |
570 | + trace.mutter('%s\'s socket already closed: %s' % (c_id, e)) |
571 | + else: |
572 | + sock.close() |
573 | + if os.path.exists(c_path): |
574 | + # The child failed to cleanup after itself, do the work here |
575 | + trace.warning('Had to clean up after child %d: %s\n' |
576 | + % (c_id, c_path)) |
577 | + shutil.rmtree(c_path, ignore_errors=True) |
578 | + |
579 | + def _wait_for_children(self, secs): |
580 | + start = time.time() |
581 | + end = start + secs |
582 | + while self._child_processes: |
583 | + self._poll_children() |
584 | + if secs > 0 and time.time() > end: |
585 | + break |
586 | + time.sleep(self.SLEEP_FOR_CHILDREN_TIMEOUT) |
587 | + |
588 | + def _shutdown_children(self): |
589 | + self._wait_for_children(self.WAIT_FOR_CHILDREN_TIMEOUT) |
590 | + if self._child_processes: |
591 | + trace.warning('Failed to stop children: %s' |
592 | + % ', '.join(map(str, self._child_processes))) |
593 | + for c_id in self._child_processes: |
594 | + trace.warning('sending SIGINT to %d' % (c_id,)) |
595 | + os.kill(c_id, signal.SIGINT) |
596 | + # We sent the SIGINT signal, see if they exited |
597 | + self._wait_for_children(self.SLEEP_FOR_CHILDREN_TIMEOUT) |
598 | + if self._child_processes: |
599 | + # No? Then maybe something more powerful |
600 | + for c_id in self._child_processes: |
601 | + trace.warning('sending SIGKILL to %d' % (c_id,)) |
602 | + os.kill(c_id, signal.SIGKILL) |
603 | + # We sent the SIGKILL signal, see if they exited |
604 | + self._wait_for_children(self.SLEEP_FOR_CHILDREN_TIMEOUT) |
605 | + if self._child_processes: |
606 | + for c_id, (c_path, sock) in self._child_processes.iteritems(): |
607 | + # TODO: We should probably put something into this message? |
608 | + # However, the likelyhood is very small that this isn't |
609 | + # already closed because of SIGKILL + _wait_for_children |
610 | + # And I don't really know what to say... |
611 | + sock.close() |
612 | + if os.path.exists(c_path): |
613 | + trace.warning('Cleaning up after immortal child %d: %s\n' |
614 | + % (c_id, c_path)) |
615 | + shutil.rmtree(c_path) |
616 | + |
617 | + def _parse_fork_request(self, conn, client_addr, request): |
618 | + if request.startswith('fork-env '): |
619 | + while not request.endswith('end\n'): |
620 | + request += osutils.read_bytes_from_socket(conn) |
621 | + request = request.replace('\r\n', '\n') |
622 | + command, env = request[9:].split('\n', 1) |
623 | + else: |
624 | + command = request[5:].strip() |
625 | + env = 'end\n' # No env set |
626 | + try: |
627 | + command_argv = self.command_to_argv(command) |
628 | + env = self.parse_env(env) |
629 | + except Exception, e: |
630 | + # TODO: Log the traceback? |
631 | + self.log(client_addr, 'command or env parsing failed: %r' |
632 | + % (str(e),)) |
633 | + conn.sendall('FAILURE\ncommand or env parsing failed: %r' |
634 | + % (str(e),)) |
635 | + else: |
636 | + return command_argv, env |
637 | + return None, None |
638 | + |
639 | + def serve_one_connection(self, conn, client_addr): |
640 | + request = '' |
641 | + while '\n' not in request: |
642 | + request += osutils.read_bytes_from_socket(conn) |
643 | + # telnet likes to use '\r\n' rather than '\n', and it is nice to have |
644 | + # an easy way to debug. |
645 | + request = request.replace('\r\n', '\n') |
646 | + self.log(client_addr, 'request: %r' % (request,)) |
647 | + if request == 'hello\n': |
648 | + conn.sendall('ok\nyep, still alive\n') |
649 | + self.log_information() |
650 | + elif request == 'quit\n': |
651 | + self._should_terminate.set() |
652 | + conn.sendall('ok\nquit command requested... exiting\n') |
653 | + elif request.startswith('fork ') or request.startswith('fork-env '): |
654 | + command_argv, env = self._parse_fork_request(conn, client_addr, |
655 | + request) |
656 | + if command_argv is not None: |
657 | + # See [Decision #7] |
658 | + # TODO: Do we want to limit the number of children? And/or |
659 | + # prefork additional instances? (the design will need to |
660 | + # change if we prefork and run arbitrary commands.) |
661 | + self.fork_one_request(conn, client_addr, command_argv, env) |
662 | + # We don't close the conn like other code paths, since we use |
663 | + # it again later. |
664 | + return |
665 | + else: |
666 | + self.log(client_addr, 'FAILURE: unknown request: %r' % (request,)) |
667 | + # See [Decision #8] |
668 | + conn.sendall('FAILURE\nunknown request: %r\n' % (request,)) |
669 | + conn.close() |
670 | + |
671 | + |
672 | +class cmd_launchpad_forking_service(Command): |
673 | + """Launch a long-running process, where you can ask for new processes. |
674 | + |
675 | + The process will block on a given --port waiting for requests to be made. |
676 | + When a request is made, it will fork itself and redirect stdout/in/err to |
677 | + fifos on the filesystem, and start running the requested command. The |
678 | + caller will be informed where those file handles can be found. Thus it only |
679 | + makes sense that the process connecting to the port must be on the same |
680 | + system. |
681 | + """ |
682 | + |
683 | + aliases = ['lp-service'] |
684 | + |
685 | + takes_options = [Option('path', |
686 | + help='Listen for connections at PATH', |
687 | + type=str), |
688 | + Option('perms', |
689 | + help='Set the mode bits for the socket, interpreted' |
690 | + ' as an octal integer (same as chmod)'), |
691 | + Option('preload', |
692 | + help="Do/don't preload libraries before startup."), |
693 | + Option('children-timeout', type=int, |
694 | + help="Only wait XX seconds for children to exit"), |
695 | + ] |
696 | + |
697 | + def _preload_libraries(self): |
698 | + global libraries_to_preload |
699 | + for pyname in libraries_to_preload: |
700 | + try: |
701 | + __import__(pyname) |
702 | + except ImportError, e: |
703 | + trace.mutter('failed to preload %s: %s' % (pyname, e)) |
704 | + |
705 | + def run(self, path=None, perms=None, preload=True, |
706 | + children_timeout=LPForkingService.WAIT_FOR_CHILDREN_TIMEOUT): |
707 | + if path is None: |
708 | + path = LPForkingService.DEFAULT_PATH |
709 | + if perms is None: |
710 | + perms = LPForkingService.DEFAULT_PERMISSIONS |
711 | + if preload: |
712 | + # We 'note' this because it often takes a fair amount of time. |
713 | + trace.note('Preloading %d modules' % (len(libraries_to_preload),)) |
714 | + self._preload_libraries() |
715 | + service = LPForkingService(path, perms) |
716 | + service.WAIT_FOR_CHILDREN_TIMEOUT = children_timeout |
717 | + service.main_loop() |
718 | + |
719 | +register_command(cmd_launchpad_forking_service) |
720 | + |
721 | + |
722 | +class cmd_launchpad_replay(Command): |
723 | + """Write input from stdin back to stdout or stderr. |
724 | + |
725 | + This is a hidden command, primarily available for testing |
726 | + cmd_launchpad_forking_service. |
727 | + """ |
728 | + |
729 | + hidden = True |
730 | + |
731 | + def run(self): |
732 | + # Just read line-by-line from stdin, and write out to stdout or stderr |
733 | + # depending on the prefix |
734 | + for line in sys.stdin: |
735 | + channel, contents = line.split(' ', 1) |
736 | + channel = int(channel) |
737 | + if channel == 1: |
738 | + sys.stdout.write(contents) |
739 | + sys.stdout.flush() |
740 | + elif channel == 2: |
741 | + sys.stderr.write(contents) |
742 | + sys.stderr.flush() |
743 | + else: |
744 | + raise RuntimeError('Invalid channel request.') |
745 | + return 0 |
746 | + |
747 | +register_command(cmd_launchpad_replay) |
748 | + |
749 | +# This list was generated by run lsprofing a spawned child, and looking for |
750 | +# <module ...> times, which indicate an import occured. Other possibilities are |
751 | +# to just run "bzr lp-serve --profile-imports" manually, and observe what was |
752 | +# expensive to import. It doesn't seem very easy to get this right |
753 | +# automatically. |
754 | +libraries_to_preload = [ |
755 | + 'bzrlib.errors', |
756 | + 'bzrlib.repofmt.groupcompress_repo', |
757 | + 'bzrlib.repository', |
758 | + 'bzrlib.smart', |
759 | + 'bzrlib.smart.protocol', |
760 | + 'bzrlib.smart.request', |
761 | + 'bzrlib.smart.server', |
762 | + 'bzrlib.smart.vfs', |
763 | + 'bzrlib.transport.local', |
764 | + 'bzrlib.transport.readonly', |
765 | + 'lp.codehosting.bzrutils', |
766 | + 'lp.codehosting.vfs', |
767 | + 'lp.codehosting.vfs.branchfs', |
768 | + 'lp.codehosting.vfs.branchfsclient', |
769 | + 'lp.codehosting.vfs.hooks', |
770 | + 'lp.codehosting.vfs.transport', |
771 | + ] |
772 | + |
773 | + |
774 | + |
775 | +def load_tests(standard_tests, module, loader): |
776 | + standard_tests.addTests(loader.loadTestsFromModuleNames( |
777 | + [__name__ + '.' + x for x in [ |
778 | + 'test_lpserve', |
779 | + ]])) |
780 | + return standard_tests |
781 | |
782 | === added file 'bzrplugins/lpserve/test_lpserve.py' |
783 | --- bzrplugins/lpserve/test_lpserve.py 1970-01-01 00:00:00 +0000 |
784 | +++ bzrplugins/lpserve/test_lpserve.py 2010-10-04 22:08:24 +0000 |
785 | @@ -0,0 +1,541 @@ |
786 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
787 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
788 | + |
789 | +import os |
790 | +import signal |
791 | +import socket |
792 | +import subprocess |
793 | +import tempfile |
794 | +import threading |
795 | +import time |
796 | + |
797 | +from testtools import content |
798 | + |
799 | +from bzrlib import ( |
800 | + osutils, |
801 | + tests, |
802 | + trace, |
803 | + ) |
804 | +from bzrlib.plugins import lpserve |
805 | + |
806 | +from canonical.config import config |
807 | +from lp.codehosting import get_bzr_path, get_BZR_PLUGIN_PATH_for_subprocess |
808 | + |
809 | + |
810 | +class TestingLPForkingServiceInAThread(lpserve.LPForkingService): |
811 | + """Wrap starting and stopping an LPForkingService instance in a thread.""" |
812 | + |
813 | + # For testing, we set the timeouts much lower, because we want the tests to |
814 | + # run quickly |
815 | + WAIT_FOR_CHILDREN_TIMEOUT = 0.5 |
816 | + SOCKET_TIMEOUT = 0.01 |
817 | + SLEEP_FOR_CHILDREN_TIMEOUT = 0.01 |
818 | + WAIT_FOR_REQUEST_TIMEOUT = 0.1 |
819 | + |
820 | + _fork_function = None |
821 | + |
822 | + def __init__(self, path, perms=None): |
823 | + self.service_started = threading.Event() |
824 | + self.service_stopped = threading.Event() |
825 | + self.this_thread = None |
826 | + self.fork_log = [] |
827 | + super(TestingLPForkingServiceInAThread, self).__init__( |
828 | + path=path, perms=None) |
829 | + |
830 | + def _register_signals(self): |
831 | + pass # Don't register it for the test suite |
832 | + |
833 | + def _unregister_signals(self): |
834 | + pass # We don't fork, and didn't register, so don't unregister |
835 | + |
836 | + def _create_master_socket(self): |
837 | + super(TestingLPForkingServiceInAThread, self)._create_master_socket() |
838 | + self.service_started.set() |
839 | + |
840 | + def main_loop(self): |
841 | + self.service_stopped.clear() |
842 | + super(TestingLPForkingServiceInAThread, self).main_loop() |
843 | + self.service_stopped.set() |
844 | + |
845 | + def fork_one_request(self, conn, client_addr, command, env): |
846 | + # We intentionally don't allow the test suite to request a fork, as |
847 | + # threads + forks and everything else don't exactly play well together |
848 | + self.fork_log.append((command, env)) |
849 | + conn.sendall('ok\nfake forking\n') |
850 | + conn.close() |
851 | + |
852 | + @staticmethod |
853 | + def start_service(test): |
854 | + """Start a new LPForkingService in a thread at a random path. |
855 | + |
856 | + This will block until the service has created its socket, and is ready |
857 | + to communicate. |
858 | + |
859 | + :return: A new TestingLPForkingServiceInAThread instance |
860 | + """ |
861 | + fd, path = tempfile.mkstemp(prefix='tmp-lp-forking-service-', |
862 | + suffix='.sock') |
863 | + # We don't want a temp file, we want a temp socket |
864 | + os.close(fd) |
865 | + os.remove(path) |
866 | + new_service = TestingLPForkingServiceInAThread(path=path) |
867 | + thread = threading.Thread(target=new_service.main_loop, |
868 | + name='TestingLPForkingServiceInAThread') |
869 | + new_service.this_thread = thread |
870 | + # should we be doing thread.setDaemon(True) ? |
871 | + thread.start() |
872 | + new_service.service_started.wait(10.0) |
873 | + if not new_service.service_started.isSet(): |
874 | + raise RuntimeError( |
875 | + 'Failed to start the TestingLPForkingServiceInAThread') |
876 | + test.addCleanup(new_service.stop_service) |
877 | + # what about returning new_service._sockname ? |
878 | + return new_service |
879 | + |
880 | + def stop_service(self): |
881 | + """Stop the test-server thread. This can be called multiple times.""" |
882 | + if self.this_thread is None: |
883 | + # We already stopped the process |
884 | + return |
885 | + self._should_terminate.set() |
886 | + self.service_stopped.wait(10.0) |
887 | + if not self.service_stopped.isSet(): |
888 | + raise RuntimeError( |
889 | + 'Failed to stop the TestingLPForkingServiceInAThread') |
890 | + self.this_thread.join() |
891 | + # Break any refcycles |
892 | + self.this_thread = None |
893 | + |
894 | + |
895 | +class TestTestingLPForkingServiceInAThread(tests.TestCaseWithTransport): |
896 | + |
897 | + def test_start_and_stop_service(self): |
898 | + service = TestingLPForkingServiceInAThread.start_service(self) |
899 | + service.stop_service() |
900 | + |
901 | + def test_multiple_stops(self): |
902 | + service = TestingLPForkingServiceInAThread.start_service(self) |
903 | + service.stop_service() |
904 | + service.stop_service() |
905 | + |
906 | + def test_autostop(self): |
907 | + # We shouldn't leak a thread here, as it should be part of the test |
908 | + # case teardown. |
909 | + service = TestingLPForkingServiceInAThread.start_service(self) |
910 | + |
911 | + |
912 | +class TestCaseWithLPForkingService(tests.TestCaseWithTransport): |
913 | + |
914 | + def setUp(self): |
915 | + super(TestCaseWithLPForkingService, self).setUp() |
916 | + self.service = TestingLPForkingServiceInAThread.start_service(self) |
917 | + |
918 | + def send_message_to_service(self, message, one_byte_at_a_time=False): |
919 | + client_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
920 | + client_sock.connect(self.service.master_socket_path) |
921 | + if one_byte_at_a_time: |
922 | + for byte in message: |
923 | + client_sock.send(byte) |
924 | + else: |
925 | + client_sock.sendall(message) |
926 | + response = client_sock.recv(1024) |
927 | + return response |
928 | + |
929 | + |
930 | +class TestLPForkingServiceCommandToArgv(tests.TestCase): |
931 | + |
932 | + def assertAsArgv(self, argv, command_str): |
933 | + self.assertEqual(argv, |
934 | + lpserve.LPForkingService.command_to_argv(command_str)) |
935 | + |
936 | + def test_simple(self): |
937 | + self.assertAsArgv([u'foo'], 'foo') |
938 | + self.assertAsArgv([u'foo', u'bar'], 'foo bar') |
939 | + |
940 | + def test_quoted(self): |
941 | + self.assertAsArgv([u'foo'], 'foo') |
942 | + self.assertAsArgv([u'foo bar'], '"foo bar"') |
943 | + |
944 | + def test_unicode(self): |
945 | + self.assertAsArgv([u'command', u'\xe5'], 'command \xc3\xa5') |
946 | + |
947 | + |
948 | +class TestLPForkingServiceParseEnv(tests.TestCase): |
949 | + |
950 | + def assertEnv(self, env, env_str): |
951 | + self.assertEqual(env, lpserve.LPForkingService.parse_env(env_str)) |
952 | + |
953 | + def assertInvalid(self, env_str): |
954 | + self.assertRaises(ValueError, lpserve.LPForkingService.parse_env, |
955 | + env_str) |
956 | + |
957 | + def test_no_entries(self): |
958 | + self.assertEnv({}, 'end\n') |
959 | + |
960 | + def test_one_entries(self): |
961 | + self.assertEnv({'BZR_EMAIL': 'joe@foo.com'}, |
962 | + 'BZR_EMAIL: joe@foo.com\n' |
963 | + 'end\n') |
964 | + |
965 | + def test_two_entries(self): |
966 | + self.assertEnv({'BZR_EMAIL': 'joe@foo.com', 'BAR': 'foo'}, |
967 | + 'BZR_EMAIL: joe@foo.com\n' |
968 | + 'BAR: foo\n' |
969 | + 'end\n') |
970 | + |
971 | + def test_invalid_empty(self): |
972 | + self.assertInvalid('') |
973 | + |
974 | + def test_invalid_end(self): |
975 | + self.assertInvalid("BZR_EMAIL: joe@foo.com\n") |
976 | + |
977 | + def test_invalid_entry(self): |
978 | + self.assertInvalid("BZR_EMAIL joe@foo.com\nend\n") |
979 | + |
980 | + |
981 | +class TestLPForkingService(TestCaseWithLPForkingService): |
982 | + |
983 | + def test_send_quit_message(self): |
984 | + response = self.send_message_to_service('quit\n') |
985 | + self.assertEqual('ok\nquit command requested... exiting\n', response) |
986 | + self.service.service_stopped.wait(10.0) |
987 | + self.assertTrue(self.service.service_stopped.isSet()) |
988 | + |
989 | + def test_send_invalid_message_fails(self): |
990 | + response = self.send_message_to_service('unknown\n') |
991 | + self.assertStartsWith(response, 'FAILURE') |
992 | + |
993 | + def test_send_hello_heartbeat(self): |
994 | + response = self.send_message_to_service('hello\n') |
995 | + self.assertEqual('ok\nyep, still alive\n', response) |
996 | + |
997 | + def test_hello_supports_crlf(self): |
998 | + # telnet seems to always write in text mode. It is nice to be able to |
999 | + # debug with simple telnet, so lets support it. |
1000 | + response = self.send_message_to_service('hello\r\n') |
1001 | + self.assertEqual('ok\nyep, still alive\n', response) |
1002 | + |
1003 | + def test_send_simple_fork(self): |
1004 | + response = self.send_message_to_service('fork rocks\n') |
1005 | + self.assertEqual('ok\nfake forking\n', response) |
1006 | + self.assertEqual([(['rocks'], {})], self.service.fork_log) |
1007 | + |
1008 | + def test_send_fork_env_with_empty_env(self): |
1009 | + response = self.send_message_to_service( |
1010 | + 'fork-env rocks\n' |
1011 | + 'end\n') |
1012 | + self.assertEqual('ok\nfake forking\n', response) |
1013 | + self.assertEqual([(['rocks'], {})], self.service.fork_log) |
1014 | + |
1015 | + def test_send_fork_env_with_env(self): |
1016 | + response = self.send_message_to_service( |
1017 | + 'fork-env rocks\n' |
1018 | + 'BZR_EMAIL: joe@example.com\n' |
1019 | + 'end\n') |
1020 | + self.assertEqual('ok\nfake forking\n', response) |
1021 | + self.assertEqual([(['rocks'], {'BZR_EMAIL': 'joe@example.com'})], |
1022 | + self.service.fork_log) |
1023 | + |
1024 | + def test_send_fork_env_slowly(self): |
1025 | + response = self.send_message_to_service( |
1026 | + 'fork-env rocks\n' |
1027 | + 'BZR_EMAIL: joe@example.com\n' |
1028 | + 'end\n', one_byte_at_a_time=True) |
1029 | + self.assertEqual('ok\nfake forking\n', response) |
1030 | + self.assertEqual([(['rocks'], {'BZR_EMAIL': 'joe@example.com'})], |
1031 | + self.service.fork_log) |
1032 | + # It should work with 'crlf' endings as well |
1033 | + response = self.send_message_to_service( |
1034 | + 'fork-env rocks\r\n' |
1035 | + 'BZR_EMAIL: joe@example.com\r\n' |
1036 | + 'end\r\n', one_byte_at_a_time=True) |
1037 | + self.assertEqual('ok\nfake forking\n', response) |
1038 | + self.assertEqual([(['rocks'], {'BZR_EMAIL': 'joe@example.com'}), |
1039 | + (['rocks'], {'BZR_EMAIL': 'joe@example.com'})], |
1040 | + self.service.fork_log) |
1041 | + |
1042 | + def test_send_incomplete_fork_env_timeout(self): |
1043 | + # We should get a failure message if we can't quickly read the whole |
1044 | + # content |
1045 | + response = self.send_message_to_service( |
1046 | + 'fork-env rocks\n' |
1047 | + 'BZR_EMAIL: joe@example.com\n', |
1048 | + one_byte_at_a_time=True) |
1049 | + # Note that we *don't* send a final 'end\n' |
1050 | + self.assertStartsWith(response, 'FAILURE\n') |
1051 | + |
1052 | + def test_send_incomplete_request_timeout(self): |
1053 | + # Requests end with '\n', send one without it |
1054 | + response = self.send_message_to_service('hello', |
1055 | + one_byte_at_a_time=True) |
1056 | + self.assertStartsWith(response, 'FAILURE\n') |
1057 | + |
1058 | + |
1059 | +class TestCaseWithSubprocess(tests.TestCaseWithTransport): |
1060 | + """Override the bzr start_bzr_subprocess command. |
1061 | + |
1062 | + The launchpad infrastructure requires a fair amount of configuration to get |
1063 | + paths, etc correct. So this provides that work. |
1064 | + """ |
1065 | + |
1066 | + def get_python_path(self): |
1067 | + """Return the path to the Python interpreter.""" |
1068 | + return '%s/bin/py' % config.root |
1069 | + |
1070 | + def start_bzr_subprocess(self, process_args, env_changes=None, |
1071 | + working_dir=None): |
1072 | + """Start bzr in a subprocess for testing. |
1073 | + |
1074 | + Copied and modified from `bzrlib.tests.TestCase.start_bzr_subprocess`. |
1075 | + This version removes some of the skipping stuff, some of the |
1076 | + irrelevant comments (e.g. about win32) and uses Launchpad's own |
1077 | + mechanisms for getting the path to 'bzr'. |
1078 | + |
1079 | + Comments starting with 'LAUNCHPAD' are comments about our |
1080 | + modifications. |
1081 | + """ |
1082 | + if env_changes is None: |
1083 | + env_changes = {} |
1084 | + env_changes['BZR_PLUGIN_PATH'] = get_BZR_PLUGIN_PATH_for_subprocess() |
1085 | + old_env = {} |
1086 | + |
1087 | + def cleanup_environment(): |
1088 | + for env_var, value in env_changes.iteritems(): |
1089 | + old_env[env_var] = osutils.set_or_unset_env(env_var, value) |
1090 | + |
1091 | + def restore_environment(): |
1092 | + for env_var, value in old_env.iteritems(): |
1093 | + osutils.set_or_unset_env(env_var, value) |
1094 | + |
1095 | + cwd = None |
1096 | + if working_dir is not None: |
1097 | + cwd = osutils.getcwd() |
1098 | + os.chdir(working_dir) |
1099 | + |
1100 | + # LAUNCHPAD: Because of buildout, we need to get a custom Python |
1101 | + # binary, not sys.executable. |
1102 | + python_path = self.get_python_path() |
1103 | + # LAUNCHPAD: We can't use self.get_bzr_path(), since it'll find |
1104 | + # lib/bzrlib, rather than the path to sourcecode/bzr/bzr. |
1105 | + bzr_path = get_bzr_path() |
1106 | + try: |
1107 | + cleanup_environment() |
1108 | + command = [python_path, bzr_path] |
1109 | + command.extend(process_args) |
1110 | + process = self._popen( |
1111 | + command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
1112 | + stderr=subprocess.PIPE) |
1113 | + finally: |
1114 | + restore_environment() |
1115 | + if cwd is not None: |
1116 | + os.chdir(cwd) |
1117 | + |
1118 | + return process |
1119 | + |
1120 | + |
1121 | +class TestCaseWithLPForkingServiceSubprocess(TestCaseWithSubprocess): |
1122 | + """Tests will get a separate process to communicate to. |
1123 | + |
1124 | + The number of these tests should be small, because it is expensive to start |
1125 | + and stop the daemon. |
1126 | + |
1127 | + TODO: This should probably use testresources, or layers somehow... |
1128 | + """ |
1129 | + |
1130 | + def setUp(self): |
1131 | + super(TestCaseWithLPForkingServiceSubprocess, self).setUp() |
1132 | + self.service_process, self.service_path = self.start_service_subprocess() |
1133 | + self.addCleanup(self.stop_service) |
1134 | + |
1135 | + def start_conversation(self, message, one_byte_at_a_time=False): |
1136 | + """Start talking to the service, and get the initial response.""" |
1137 | + client_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
1138 | + trace.mutter('sending %r to socket %s' % (message, self.service_path)) |
1139 | + client_sock.connect(self.service_path) |
1140 | + if one_byte_at_a_time: |
1141 | + for byte in message: |
1142 | + client_sock.send(byte) |
1143 | + else: |
1144 | + client_sock.sendall(message) |
1145 | + response = client_sock.recv(1024) |
1146 | + trace.mutter('response: %r' % (response,)) |
1147 | + if response.startswith("FAILURE"): |
1148 | + raise RuntimeError('Failed to send message: %r' % (response,)) |
1149 | + return response, client_sock |
1150 | + |
1151 | + def send_message_to_service(self, message, one_byte_at_a_time=False): |
1152 | + response, client_sock = self.start_conversation(message, |
1153 | + one_byte_at_a_time=one_byte_at_a_time) |
1154 | + client_sock.close() |
1155 | + return response |
1156 | + |
1157 | + def send_fork_request(self, command, env=None): |
1158 | + if env is not None: |
1159 | + request_lines = ['fork-env %s\n' % (command,)] |
1160 | + for key, value in env.iteritems(): |
1161 | + request_lines.append('%s: %s\n' % (key, value)) |
1162 | + request_lines.append('end\n') |
1163 | + request = ''.join(request_lines) |
1164 | + else: |
1165 | + request = 'fork %s\n' % (command,) |
1166 | + response, sock = self.start_conversation(request) |
1167 | + ok, pid, path, tail = response.split('\n') |
1168 | + self.assertEqual('ok', ok) |
1169 | + self.assertEqual('', tail) |
1170 | + # Don't really care what it is, but should be an integer |
1171 | + pid = int(pid) |
1172 | + path = path.strip() |
1173 | + self.assertContainsRe(path, '/lp-forking-service-child-') |
1174 | + return path, pid, sock |
1175 | + |
1176 | + def start_service_subprocess(self): |
1177 | + # Make sure this plugin is exposed to the subprocess |
1178 | + # SLOOWWW (~2 seconds, which is why we are doing the work anyway) |
1179 | + fd, tempname = tempfile.mkstemp(prefix='tmp-log-bzr-lp-forking-') |
1180 | + # I'm not 100% sure about when cleanup runs versus addDetail, but I |
1181 | + # think this will work. |
1182 | + self.addCleanup(os.remove, tempname) |
1183 | + def read_log(): |
1184 | + f = os.fdopen(fd) |
1185 | + f.seek(0) |
1186 | + content = f.read() |
1187 | + f.close() |
1188 | + return [content] |
1189 | + self.addDetail('server-log', content.Content( |
1190 | + content.ContentType('text', 'plain', {"charset": "utf8"}), |
1191 | + read_log)) |
1192 | + service_fd, path = tempfile.mkstemp(prefix='tmp-lp-service-', |
1193 | + suffix='.sock') |
1194 | + os.close(service_fd) |
1195 | + os.remove(path) # service wants create it as a socket |
1196 | + env_changes = {'BZR_PLUGIN_PATH': lpserve.__path__[0], |
1197 | + 'BZR_LOG': tempname} |
1198 | + proc = self.start_bzr_subprocess( |
1199 | + ['lp-service', '--path', path, '--no-preload', |
1200 | + '--children-timeout=1'], |
1201 | + env_changes=env_changes) |
1202 | + trace.mutter('started lp-service subprocess') |
1203 | + # preload_line = proc.stderr.readline() |
1204 | + # self.assertStartsWith(preload_line, 'Preloading') |
1205 | + expected = 'Listening on socket: %s\n' % (path,) |
1206 | + path_line = proc.stderr.readline() |
1207 | + trace.mutter(path_line) |
1208 | + self.assertEqual(expected, path_line) |
1209 | + # The process won't delete it, so we do |
1210 | + return proc, path |
1211 | + |
1212 | + def stop_service(self): |
1213 | + if self.service_process is None: |
1214 | + # Already stopped |
1215 | + return |
1216 | + # First, try to stop the service gracefully, by sending a 'quit' |
1217 | + # message |
1218 | + try: |
1219 | + response = self.send_message_to_service('quit\n') |
1220 | + except socket.error, e: |
1221 | + # Ignore a failure to connect, the service must be stopping/stopped |
1222 | + # already |
1223 | + response = None |
1224 | + tend = time.time() + 10.0 |
1225 | + while self.service_process.poll() is None: |
1226 | + if time.time() > tend: |
1227 | + self.finish_bzr_subprocess(process=self.service_process, |
1228 | + send_signal=signal.SIGINT, retcode=3) |
1229 | + self.fail('Failed to quit gracefully after 10.0 seconds') |
1230 | + time.sleep(0.1) |
1231 | + if response is not None: |
1232 | + self.assertEqual('ok\nquit command requested... exiting\n', |
1233 | + response) |
1234 | + |
1235 | + def _get_fork_handles(self, path): |
1236 | + trace.mutter('getting handles for: %s' % (path,)) |
1237 | + stdin_path = os.path.join(path, 'stdin') |
1238 | + stdout_path = os.path.join(path, 'stdout') |
1239 | + stderr_path = os.path.join(path, 'stderr') |
1240 | + # Consider the ordering, the other side should open 'stdin' first, but |
1241 | + # we want it to block until we open the last one, or we race and it can |
1242 | + # delete the other handles before we get to open them. |
1243 | + child_stdin = open(stdin_path, 'wb') |
1244 | + child_stdout = open(stdout_path, 'rb') |
1245 | + child_stderr = open(stderr_path, 'rb') |
1246 | + return child_stdin, child_stdout, child_stderr |
1247 | + |
1248 | + def communicate_with_fork(self, path, stdin=None): |
1249 | + child_stdin, child_stdout, child_stderr = self._get_fork_handles(path) |
1250 | + if stdin is not None: |
1251 | + child_stdin.write(stdin) |
1252 | + child_stdin.close() |
1253 | + stdout_content = child_stdout.read() |
1254 | + stderr_content = child_stderr.read() |
1255 | + return stdout_content, stderr_content |
1256 | + |
1257 | + def assertReturnCode(self, expected_code, sock): |
1258 | + """Assert that we get the expected return code as a message.""" |
1259 | + response = sock.recv(1024) |
1260 | + self.assertStartsWith(response, 'exited\n') |
1261 | + code = int(response.split('\n', 1)[1]) |
1262 | + self.assertEqual(expected_code, code) |
1263 | + |
1264 | + def test_fork_lp_serve_hello(self): |
1265 | + path, _, sock = self.send_fork_request('lp-serve --inet 2') |
1266 | + stdout_content, stderr_content = self.communicate_with_fork(path, |
1267 | + 'hello\n') |
1268 | + self.assertEqual('ok\x012\n', stdout_content) |
1269 | + self.assertEqual('', stderr_content) |
1270 | + self.assertReturnCode(0, sock) |
1271 | + |
1272 | + def test_fork_replay(self): |
1273 | + path, _, sock = self.send_fork_request('launchpad-replay') |
1274 | + stdout_content, stderr_content = self.communicate_with_fork(path, |
1275 | + '1 hello\n2 goodbye\n1 maybe\n') |
1276 | + self.assertEqualDiff('hello\nmaybe\n', stdout_content) |
1277 | + self.assertEqualDiff('goodbye\n', stderr_content) |
1278 | + self.assertReturnCode(0, sock) |
1279 | + |
1280 | + def test_just_run_service(self): |
1281 | + # Start and stop are defined in setUp() |
1282 | + pass |
1283 | + |
1284 | + def test_fork_multiple_children(self): |
1285 | + paths = [] |
1286 | + for idx in range(4): |
1287 | + paths.append(self.send_fork_request('launchpad-replay')) |
1288 | + # Do them out of order, as order shouldn't matter. |
1289 | + for idx in [3, 2, 0, 1]: |
1290 | + p, pid, sock = paths[idx] |
1291 | + stdout_msg = 'hello %d\n' % (idx,) |
1292 | + stderr_msg = 'goodbye %d\n' % (idx+1,) |
1293 | + stdout, stderr = self.communicate_with_fork(p, |
1294 | + '1 %s2 %s' % (stdout_msg, stderr_msg)) |
1295 | + self.assertEqualDiff(stdout_msg, stdout) |
1296 | + self.assertEqualDiff(stderr_msg, stderr) |
1297 | + self.assertReturnCode(0, sock) |
1298 | + |
1299 | + def test_fork_respects_env_vars(self): |
1300 | + path, pid, sock = self.send_fork_request('whoami', |
1301 | + env={'BZR_EMAIL': 'this_test@example.com'}) |
1302 | + stdout_content, stderr_content = self.communicate_with_fork(path) |
1303 | + self.assertEqual('', stderr_content) |
1304 | + self.assertEqual('this_test@example.com\n', stdout_content) |
1305 | + |
1306 | + def _check_exits_nicely(self, sig_id): |
1307 | + path, _, sock = self.send_fork_request('rocks') |
1308 | + self.assertEqual(None, self.service_process.poll()) |
1309 | + # Now when we send SIGTERM, it should wait for the child to exit, |
1310 | + # before it tries to exit itself. |
1311 | + # In python2.6+ we could use self.service_process.terminate() |
1312 | + os.kill(self.service_process.pid, sig_id) |
1313 | + self.assertEqual(None, self.service_process.poll()) |
1314 | + # Now talk to the child, so the service can close |
1315 | + stdout_content, stderr_content = self.communicate_with_fork(path) |
1316 | + self.assertEqual('It sure does!\n', stdout_content) |
1317 | + self.assertEqual('', stderr_content) |
1318 | + self.assertReturnCode(0, sock) |
1319 | + # And the process should exit cleanly |
1320 | + self.assertEqual(0, self.service_process.wait()) |
1321 | + |
1322 | + def test_sigterm_exits_nicely(self): |
1323 | + self._check_exits_nicely(signal.SIGTERM) |
1324 | + |
1325 | + def test_sigint_exits_nicely(self): |
1326 | + self._check_exits_nicely(signal.SIGINT) |
1327 | |
1328 | === modified file 'configs/development/launchpad-lazr.conf' |
1329 | --- configs/development/launchpad-lazr.conf 2010-09-20 21:35:21 +0000 |
1330 | +++ configs/development/launchpad-lazr.conf 2010-10-04 22:08:24 +0000 |
1331 | @@ -76,6 +76,7 @@ |
1332 | lp_url_hosts: dev |
1333 | access_log: /var/tmp/bazaar.launchpad.dev/codehosting-access.log |
1334 | blacklisted_hostnames: |
1335 | +use_forking_daemon: True |
1336 | |
1337 | [codeimport] |
1338 | bazaar_branch_store: file:///tmp/bazaar-branches |
1339 | |
1340 | === modified file 'database/replication/Makefile' |
1341 | --- database/replication/Makefile 2010-07-26 08:12:20 +0000 |
1342 | +++ database/replication/Makefile 2010-10-04 22:08:24 +0000 |
1343 | @@ -14,8 +14,9 @@ |
1344 | # To test the staging rebuild script: |
1345 | # |
1346 | # $ cd database/replication |
1347 | -# $ pg_dump --format=c launchpad_dev > launchpad.dump |
1348 | -# $ make stagingsetup STAGING_CONFIG=dev-staging STAGING_DUMP=launchpad.dump |
1349 | +# $ pg_dump --format=c launchpad_dev | bzip2 -c > launchpad.dump.bz2 |
1350 | +# $ make stagingsetup \ |
1351 | +# STAGING_CONFIG=dev-staging STAGING_DUMP=launchpad.dump.bz2 |
1352 | # $ make stagingswitch STAGING_CONFIG=dev-staging |
1353 | # |
1354 | # To restore a dogfood database: |
1355 | @@ -46,7 +47,12 @@ |
1356 | |
1357 | CREATEDB_83=createdb --encoding=UTF8 |
1358 | CREATEDB_84=createdb --encoding=UTF8 --locale=C --template=template0 |
1359 | -CREATEDB=${CREATEDB_83} |
1360 | +CREATEDB=${CREATEDB_84} |
1361 | + |
1362 | +# Set this to --exit-on-error once our dumps are coming from a PG 8.4 |
1363 | +# source. Currently, the PG 8.3 dumps generate some spurious errors |
1364 | +# when being restored into a PG 8.4 database. |
1365 | +EXIT_ON_ERROR= |
1366 | |
1367 | # Turn off output silencing so we can see details of staging deployments. |
1368 | # Without the timestamps, we are unable to estimate production deployment |
1369 | @@ -102,8 +108,9 @@ |
1370 | # Restore the database. We need to restore permissions, despite |
1371 | # later running security.py, to pull in permissions granted on |
1372 | # production to users not maintained by security.py. |
1373 | - bunzip2 --stdout ${STAGING_DUMP} | \ |
1374 | - pg_restore --dbname=lpmain_staging_new --no-owner --exit-on-error |
1375 | + # Stop ignoring error code after dumps come from an 8.4 system. |
1376 | + -bunzip2 --stdout ${STAGING_DUMP} | \ |
1377 | + pg_restore --dbname=lpmain_staging_new --no-owner ${EXIT_ON_ERROR} |
1378 | # Uninstall Slony-I if it is installed - a pg_dump of a DB with |
1379 | # Slony-I installed isn't usable without this step. |
1380 | LPCONFIG=${NEW_STAGING_CONFIG} ./repair-restored-db.py |
1381 | @@ -136,8 +143,9 @@ |
1382 | |
1383 | dogfood: |
1384 | ${CREATEDB} ${DOGFOOD_DBNAME} |
1385 | - pg_restore --dbname=${DOGFOOD_DBNAME} --no-acl --no-owner \ |
1386 | - --exit-on-error ${DOGFOOD_DUMP} |
1387 | + # Stop ignoring error code after are dumps come from an 8.4 system. |
1388 | + -pg_restore --dbname=${DOGFOOD_DBNAME} --no-acl --no-owner \ |
1389 | + ${EXIT_ON_ERROR} ${DOGFOOD_DUMP} |
1390 | ./repair-restored-db.py -d ${DOGFOOD_DBNAME} |
1391 | ../schema/upgrade.py -d ${DOGFOOD_DBNAME} |
1392 | ../schema/fti.py -d ${DOGFOOD_DBNAME} |
1393 | |
1394 | === modified file 'database/replication/slon_ctl.py' |
1395 | --- database/replication/slon_ctl.py 2010-05-19 18:07:56 +0000 |
1396 | +++ database/replication/slon_ctl.py 2010-10-04 22:08:24 +0000 |
1397 | @@ -88,9 +88,11 @@ |
1398 | |
1399 | |
1400 | def get_logfile(nickname): |
1401 | + logdir = config.database.replication_logdir |
1402 | + if not os.path.isabs(logdir): |
1403 | + logdir = os.path.normpath(os.path.join(config.root, logdir)) |
1404 | return os.path.join( |
1405 | - config.root, 'database', 'replication', |
1406 | - 'lpslon_%s_%s.log' % (nickname, config.instance_name)) |
1407 | + logdir, 'lpslon_%s_%s.log' % (nickname, config.instance_name)) |
1408 | |
1409 | |
1410 | def start(log, nodes, lag=None): |
1411 | |
1412 | === modified file 'database/sampledata/current-dev.sql' |
1413 | --- database/sampledata/current-dev.sql 2010-09-23 19:10:34 +0000 |
1414 | +++ database/sampledata/current-dev.sql 2010-10-04 22:08:24 +0000 |
1415 | @@ -1837,14 +1837,14 @@ |
1416 | |
1417 | ALTER TABLE distroarchseries DISABLE TRIGGER ALL; |
1418 | |
1419 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (1, 1, 1, 'i386', 1, true, 5, '2006-10-16 18:31:43.454475', true); |
1420 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (6, 3, 1, 'i386', 1, true, 1, '2006-10-16 18:31:43.456532', true); |
1421 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (7, 6, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457028', true); |
1422 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (8, 10, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457484', true); |
1423 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (9, 13, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457938', true); |
1424 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (10, 13, 3, 'amd64', 1, true, 0, '2006-10-16 18:31:43.458434', true); |
1425 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (11, 3, 4, 'hppa', 1, false, 0, '2006-10-16 18:31:43.458892', false); |
1426 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (12, 1, 4, 'hppa', 1, false, 0, '2006-10-16 18:31:43.459349', false); |
1427 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (1, 1, 1, 'i386', 1, true, 5, '2006-10-16 18:31:43.454475', true, true); |
1428 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (6, 3, 1, 'i386', 1, true, 1, '2006-10-16 18:31:43.456532', true, true); |
1429 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (7, 6, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457028', true, true); |
1430 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (8, 10, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457484', true, true); |
1431 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (9, 13, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457938', true, true); |
1432 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (10, 13, 3, 'amd64', 1, true, 0, '2006-10-16 18:31:43.458434', true, true); |
1433 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (11, 3, 4, 'hppa', 1, false, 0, '2006-10-16 18:31:43.458892', false, true); |
1434 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (12, 1, 4, 'hppa', 1, false, 0, '2006-10-16 18:31:43.459349', false, true); |
1435 | |
1436 | |
1437 | ALTER TABLE distroarchseries ENABLE TRIGGER ALL; |
1438 | @@ -3092,25 +3092,25 @@ |
1439 | |
1440 | ALTER TABLE branchrevision DISABLE TRIGGER ALL; |
1441 | |
1442 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (1, 1, 10, 1); |
1443 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (2, 1, 11, 2); |
1444 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (3, 1, 12, 3); |
1445 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (4, 1, 20, 4); |
1446 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (5, 2, 20, 5); |
1447 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (6, 3, 20, 6); |
1448 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (7, 4, 20, 7); |
1449 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (8, 5, 20, 8); |
1450 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (9, 6, 20, 9); |
1451 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (10, 1, 21, 4); |
1452 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (11, 2, 21, 5); |
1453 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (12, 3, 21, 10); |
1454 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (13, 4, 21, 11); |
1455 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (14, 5, 21, 8); |
1456 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (15, 6, 21, 9); |
1457 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (16, NULL, 20, 10); |
1458 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (17, NULL, 20, 11); |
1459 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (18, NULL, 21, 6); |
1460 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (19, NULL, 21, 7); |
1461 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 10, 1); |
1462 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 11, 2); |
1463 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 12, 3); |
1464 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 20, 4); |
1465 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 21, 4); |
1466 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (2, 20, 5); |
1467 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (2, 21, 5); |
1468 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (3, 20, 6); |
1469 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (3, 21, 10); |
1470 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (4, 20, 7); |
1471 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (4, 21, 11); |
1472 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (5, 20, 8); |
1473 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (5, 21, 8); |
1474 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (6, 20, 9); |
1475 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (6, 21, 9); |
1476 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (NULL, 20, 10); |
1477 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (NULL, 20, 11); |
1478 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (NULL, 21, 6); |
1479 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (NULL, 21, 7); |
1480 | |
1481 | |
1482 | ALTER TABLE branchrevision ENABLE TRIGGER ALL; |
1483 | @@ -3333,42 +3333,42 @@ |
1484 | |
1485 | ALTER TABLE bugmessage DISABLE TRIGGER ALL; |
1486 | |
1487 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (1, 2, 1, NULL, NULL, true); |
1488 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (2, 1, 3, NULL, NULL, true); |
1489 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (3, 1, 4, NULL, NULL, true); |
1490 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (4, 2, 5, NULL, NULL, true); |
1491 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (5, 2, 6, NULL, NULL, true); |
1492 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (6, 4, 7, NULL, NULL, true); |
1493 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (7, 5, 8, NULL, NULL, true); |
1494 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (8, 6, 9, NULL, NULL, true); |
1495 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (9, 3, 10, NULL, NULL, true); |
1496 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (10, 7, 11, NULL, NULL, true); |
1497 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (11, 8, 14, NULL, NULL, true); |
1498 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (12, 9, 15, NULL, NULL, true); |
1499 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (13, 10, 17, NULL, NULL, true); |
1500 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (14, 10, 16, NULL, NULL, true); |
1501 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (15, 11, 24, NULL, NULL, true); |
1502 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (16, 11, 25, NULL, NULL, true); |
1503 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (17, 11, 26, NULL, NULL, true); |
1504 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (18, 11, 27, NULL, NULL, true); |
1505 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (19, 11, 28, NULL, NULL, true); |
1506 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (20, 11, 29, NULL, NULL, true); |
1507 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (21, 11, 30, NULL, NULL, true); |
1508 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (22, 12, 31, NULL, NULL, true); |
1509 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (23, 12, 33, NULL, NULL, true); |
1510 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (24, 12, 34, NULL, NULL, true); |
1511 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (25, 12, 35, NULL, NULL, true); |
1512 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (26, 12, 36, NULL, NULL, true); |
1513 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (27, 13, 37, NULL, NULL, true); |
1514 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (28, 13, 38, NULL, NULL, true); |
1515 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (29, 14, 39, NULL, NULL, true); |
1516 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (30, 15, 40, NULL, NULL, true); |
1517 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (31, 15, 44, 11, '<4284D7D1.6010208@gmx.de>', true); |
1518 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (32, 15, 45, 11, '<20050517185429.GB20786@spring.luon.net>', true); |
1519 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (33, 15, 46, 11, '<428A44E9.6090802@gmx.de>', true); |
1520 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (34, 15, 47, 11, '<20050517202044.GA23231@spring.luon.net>', true); |
1521 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (35, 15, 48, 11, '<20050617140011.GA15638@piware.de>', true); |
1522 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (36, 15, 49, 11, '<42BD2E36.9090809@gmx.de>', true); |
1523 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (1, 2, 1, NULL, NULL, true, NULL); |
1524 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (2, 1, 3, NULL, NULL, true, NULL); |
1525 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (3, 1, 4, NULL, NULL, true, NULL); |
1526 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (4, 2, 5, NULL, NULL, true, NULL); |
1527 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (5, 2, 6, NULL, NULL, true, NULL); |
1528 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (6, 4, 7, NULL, NULL, true, NULL); |
1529 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (7, 5, 8, NULL, NULL, true, NULL); |
1530 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (8, 6, 9, NULL, NULL, true, NULL); |
1531 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (9, 3, 10, NULL, NULL, true, NULL); |
1532 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (10, 7, 11, NULL, NULL, true, NULL); |
1533 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (11, 8, 14, NULL, NULL, true, NULL); |
1534 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (12, 9, 15, NULL, NULL, true, NULL); |
1535 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (13, 10, 17, NULL, NULL, true, NULL); |
1536 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (14, 10, 16, NULL, NULL, true, NULL); |
1537 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (15, 11, 24, NULL, NULL, true, NULL); |
1538 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (16, 11, 25, NULL, NULL, true, NULL); |
1539 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (17, 11, 26, NULL, NULL, true, NULL); |
1540 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (18, 11, 27, NULL, NULL, true, NULL); |
1541 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (19, 11, 28, NULL, NULL, true, NULL); |
1542 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (20, 11, 29, NULL, NULL, true, NULL); |
1543 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (21, 11, 30, NULL, NULL, true, NULL); |
1544 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (22, 12, 31, NULL, NULL, true, NULL); |
1545 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (23, 12, 33, NULL, NULL, true, NULL); |
1546 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (24, 12, 34, NULL, NULL, true, NULL); |
1547 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (25, 12, 35, NULL, NULL, true, NULL); |
1548 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (26, 12, 36, NULL, NULL, true, NULL); |
1549 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (27, 13, 37, NULL, NULL, true, NULL); |
1550 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (28, 13, 38, NULL, NULL, true, NULL); |
1551 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (29, 14, 39, NULL, NULL, true, NULL); |
1552 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (30, 15, 40, NULL, NULL, true, NULL); |
1553 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (31, 15, 44, 11, '<4284D7D1.6010208@gmx.de>', true, NULL); |
1554 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (32, 15, 45, 11, '<20050517185429.GB20786@spring.luon.net>', true, NULL); |
1555 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (33, 15, 46, 11, '<428A44E9.6090802@gmx.de>', true, NULL); |
1556 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (34, 15, 47, 11, '<20050517202044.GA23231@spring.luon.net>', true, NULL); |
1557 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (35, 15, 48, 11, '<20050617140011.GA15638@piware.de>', true, NULL); |
1558 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (36, 15, 49, 11, '<42BD2E36.9090809@gmx.de>', true, NULL); |
1559 | |
1560 | |
1561 | ALTER TABLE bugmessage ENABLE TRIGGER ALL; |
1562 | @@ -3792,6 +3792,27 @@ |
1563 | ALTER TABLE bugtrackeralias ENABLE TRIGGER ALL; |
1564 | |
1565 | |
1566 | +ALTER TABLE bugtrackercomponentgroup DISABLE TRIGGER ALL; |
1567 | + |
1568 | + |
1569 | + |
1570 | +ALTER TABLE bugtrackercomponentgroup ENABLE TRIGGER ALL; |
1571 | + |
1572 | + |
1573 | +ALTER TABLE distributionsourcepackage DISABLE TRIGGER ALL; |
1574 | + |
1575 | + |
1576 | + |
1577 | +ALTER TABLE distributionsourcepackage ENABLE TRIGGER ALL; |
1578 | + |
1579 | + |
1580 | +ALTER TABLE bugtrackercomponent DISABLE TRIGGER ALL; |
1581 | + |
1582 | + |
1583 | + |
1584 | +ALTER TABLE bugtrackercomponent ENABLE TRIGGER ALL; |
1585 | + |
1586 | + |
1587 | ALTER TABLE bugtrackerperson DISABLE TRIGGER ALL; |
1588 | |
1589 | |
1590 | @@ -3993,6 +4014,13 @@ |
1591 | ALTER TABLE distributionbounty ENABLE TRIGGER ALL; |
1592 | |
1593 | |
1594 | +ALTER TABLE distributionjob DISABLE TRIGGER ALL; |
1595 | + |
1596 | + |
1597 | + |
1598 | +ALTER TABLE distributionjob ENABLE TRIGGER ALL; |
1599 | + |
1600 | + |
1601 | ALTER TABLE distributionmirror DISABLE TRIGGER ALL; |
1602 | |
1603 | INSERT INTO distributionmirror (id, distribution, name, http_base_url, ftp_base_url, rsync_base_url, displayname, description, owner, speed, country, content, official_candidate, enabled, date_created, whiteboard, status, date_reviewed, reviewer, country_dns_mirror) VALUES (1, 1, 'archive-mirror', 'http://localhost:11375/valid-mirror/', NULL, NULL, NULL, NULL, 1, 10, 75, 1, true, true, '2006-10-16 18:31:43.434567', NULL, 30, NULL, NULL, false); |
1604 | @@ -4010,13 +4038,6 @@ |
1605 | ALTER TABLE distributionmirror ENABLE TRIGGER ALL; |
1606 | |
1607 | |
1608 | -ALTER TABLE distributionsourcepackage DISABLE TRIGGER ALL; |
1609 | - |
1610 | - |
1611 | - |
1612 | -ALTER TABLE distributionsourcepackage ENABLE TRIGGER ALL; |
1613 | - |
1614 | - |
1615 | ALTER TABLE distributionsourcepackagecache DISABLE TRIGGER ALL; |
1616 | |
1617 | INSERT INTO distributionsourcepackagecache (id, distribution, sourcepackagename, name, binpkgnames, binpkgsummaries, binpkgdescriptions, fti, changelog, archive) VALUES (1, 3, 19, 'alsa-utils', '', '', '', NULL, NULL, 1); |
1618 | @@ -4567,6 +4588,13 @@ |
1619 | ALTER TABLE hwtestanswerdevice ENABLE TRIGGER ALL; |
1620 | |
1621 | |
1622 | +ALTER TABLE incrementaldiff DISABLE TRIGGER ALL; |
1623 | + |
1624 | + |
1625 | + |
1626 | +ALTER TABLE incrementaldiff ENABLE TRIGGER ALL; |
1627 | + |
1628 | + |
1629 | ALTER TABLE ircid DISABLE TRIGGER ALL; |
1630 | |
1631 | INSERT INTO ircid (id, person, network, nickname) VALUES (1, 1, 'irc.freenode.net', 'mark'); |
1632 | @@ -11141,6 +11169,13 @@ |
1633 | ALTER TABLE translationtemplateitem ENABLE TRIGGER ALL; |
1634 | |
1635 | |
1636 | +ALTER TABLE translationtemplatesbuild DISABLE TRIGGER ALL; |
1637 | + |
1638 | + |
1639 | + |
1640 | +ALTER TABLE translationtemplatesbuild ENABLE TRIGGER ALL; |
1641 | + |
1642 | + |
1643 | ALTER TABLE translator DISABLE TRIGGER ALL; |
1644 | |
1645 | INSERT INTO translator (id, translationgroup, language, translator, datecreated, style_guide_url) VALUES (1, 1, 387, 53, '2005-07-13 13:14:19.748396', NULL); |
1646 | |
1647 | === modified file 'database/sampledata/current.sql' |
1648 | --- database/sampledata/current.sql 2010-09-04 20:38:35 +0000 |
1649 | +++ database/sampledata/current.sql 2010-10-04 22:08:24 +0000 |
1650 | @@ -792,6 +792,36 @@ |
1651 | |
1652 | |
1653 | |
1654 | + |
1655 | + |
1656 | + |
1657 | + |
1658 | + |
1659 | + |
1660 | + |
1661 | + |
1662 | + |
1663 | + |
1664 | + |
1665 | + |
1666 | + |
1667 | + |
1668 | + |
1669 | + |
1670 | + |
1671 | + |
1672 | + |
1673 | + |
1674 | + |
1675 | + |
1676 | + |
1677 | + |
1678 | + |
1679 | + |
1680 | + |
1681 | + |
1682 | + |
1683 | + |
1684 | SET SESSION AUTHORIZATION DEFAULT; |
1685 | |
1686 | ALTER TABLE account DISABLE TRIGGER ALL; |
1687 | @@ -1819,14 +1849,14 @@ |
1688 | |
1689 | ALTER TABLE distroarchseries DISABLE TRIGGER ALL; |
1690 | |
1691 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (1, 1, 1, 'i386', 1, true, 5, '2006-10-16 18:31:43.454475', true); |
1692 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (6, 3, 1, 'i386', 1, true, 1, '2006-10-16 18:31:43.456532', true); |
1693 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (7, 6, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457028', true); |
1694 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (8, 10, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457484', true); |
1695 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (9, 13, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457938', true); |
1696 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (10, 13, 3, 'amd64', 1, true, 0, '2006-10-16 18:31:43.458434', true); |
1697 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (11, 3, 4, 'hppa', 1, false, 0, '2006-10-16 18:31:43.458892', false); |
1698 | -INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized) VALUES (12, 1, 4, 'hppa', 1, false, 0, '2006-10-16 18:31:43.459349', false); |
1699 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (1, 1, 1, 'i386', 1, true, 5, '2006-10-16 18:31:43.454475', true, true); |
1700 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (6, 3, 1, 'i386', 1, true, 1, '2006-10-16 18:31:43.456532', true, true); |
1701 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (7, 6, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457028', true, true); |
1702 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (8, 10, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457484', true, true); |
1703 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (9, 13, 1, 'i386', 1, true, 0, '2006-10-16 18:31:43.457938', true, true); |
1704 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (10, 13, 3, 'amd64', 1, true, 0, '2006-10-16 18:31:43.458434', true, true); |
1705 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (11, 3, 4, 'hppa', 1, false, 0, '2006-10-16 18:31:43.458892', false, true); |
1706 | +INSERT INTO distroarchseries (id, distroseries, processorfamily, architecturetag, owner, official, package_count, date_created, supports_virtualized, enabled) VALUES (12, 1, 4, 'hppa', 1, false, 0, '2006-10-16 18:31:43.459349', false, true); |
1707 | |
1708 | |
1709 | ALTER TABLE distroarchseries ENABLE TRIGGER ALL; |
1710 | @@ -2238,8 +2268,8 @@ |
1711 | |
1712 | ALTER TABLE builder DISABLE TRIGGER ALL; |
1713 | |
1714 | -INSERT INTO builder (id, processor, name, title, description, owner, speedindex, builderok, failnotes, virtualized, url, manual, date_created, vm_host, active) VALUES (1, 1, 'bob', 'Bob The Builder', 'The default build-slave', 61, NULL, true, NULL, false, 'http://localhost:8221/', false, '2006-10-16 18:31:43.226724', NULL, true); |
1715 | -INSERT INTO builder (id, processor, name, title, description, owner, speedindex, builderok, failnotes, virtualized, url, manual, date_created, vm_host, active) VALUES (2, 1, 'frog', 'The frog builder', 'The untrusted build-slave', 61, NULL, false, NULL, true, 'http://localhost:9221/', false, '2006-10-31 18:31:43.226724', 'localhost-host.ppa', true); |
1716 | +INSERT INTO builder (id, processor, name, title, description, owner, speedindex, builderok, failnotes, virtualized, url, manual, date_created, vm_host, active, failure_count) VALUES (1, 1, 'bob', 'Bob The Builder', 'The default build-slave', 61, NULL, true, NULL, false, 'http://localhost:8221/', false, '2006-10-16 18:31:43.226724', NULL, true, 0); |
1717 | +INSERT INTO builder (id, processor, name, title, description, owner, speedindex, builderok, failnotes, virtualized, url, manual, date_created, vm_host, active, failure_count) VALUES (2, 1, 'frog', 'The frog builder', 'The untrusted build-slave', 61, NULL, false, NULL, true, 'http://localhost:9221/', false, '2006-10-31 18:31:43.226724', 'localhost-host.ppa', true, 0); |
1718 | |
1719 | |
1720 | ALTER TABLE builder ENABLE TRIGGER ALL; |
1721 | @@ -2247,30 +2277,30 @@ |
1722 | |
1723 | ALTER TABLE buildfarmjob DISABLE TRIGGER ALL; |
1724 | |
1725 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (2, 1, false, '2004-09-27 11:57:13', '2004-09-27 11:55:13', '2004-09-27 11:57:14', NULL, 1, 1, 1, 1); |
1726 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (6, 1, false, '2006-12-01 00:00:00', '2006-12-01 00:00:00', '2006-12-01 00:00:01', NULL, 1, 2, 1, 1); |
1727 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (7, 1, false, '2005-03-24 00:00:00', '2005-03-24 23:58:43', '2005-03-25 00:00:03', NULL, 1, 1, 1, 1); |
1728 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (8, 1, false, '2005-09-30 00:00:00', NULL, NULL, NULL, NULL, 6, NULL, 1); |
1729 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (9, 1, false, '2005-10-01 00:00:00', '2005-10-01 23:56:41', '2005-10-02 00:00:01', NULL, 1, 2, 1, 1); |
1730 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (10, 1, false, '2006-01-27 00:00:00', NULL, NULL, NULL, NULL, 1, NULL, 1); |
1731 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (11, 1, false, '2006-02-14 00:00:00', NULL, NULL, NULL, NULL, 0, NULL, 1); |
1732 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (12, 1, false, '2006-02-28 00:00:00', '2006-02-27 23:53:59', '2006-02-28 00:00:01', NULL, 1, 3, 1, 1); |
1733 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (13, 1, false, '2006-03-21 00:00:00', '2006-03-21 00:58:33', '2006-03-21 01:00:03', NULL, 1, 5, 1, 1); |
1734 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (14, 1, false, '2006-03-22 00:00:00', '2006-03-21 00:58:32', '2006-03-21 01:00:02', NULL, 1, 5, 1, 1); |
1735 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (15, 1, false, '2006-03-22 00:00:01', '2006-03-21 00:58:30', '2006-03-21 01:00:00', NULL, 1, 5, 1, 1); |
1736 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (16, 1, false, '2005-03-24 00:00:01', '2005-03-24 23:58:42', '2005-03-25 00:00:02', NULL, 1, 1, 1, 1); |
1737 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (18, 1, false, '2004-09-27 11:57:14', '2004-09-27 11:55:12', '2004-09-27 11:57:13', NULL, 1, 1, 1, 1); |
1738 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (19, 1, false, '2005-03-24 00:00:02', '2005-03-24 23:58:41', '2005-03-25 00:00:01', NULL, 1, 1, 1, 1); |
1739 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (21, 1, false, '2006-12-01 00:00:01', NULL, NULL, NULL, NULL, 2, NULL, 1); |
1740 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (22, 1, false, '2007-04-20 00:00:00', '2007-04-19 23:58:41', '2007-04-20 00:00:01', NULL, 1, 7, 1, 1); |
1741 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (23, 1, false, '2006-04-11 12:00:00', NULL, NULL, NULL, NULL, 1, NULL, 1); |
1742 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (24, 1, true, '2007-05-30 00:00:00', '2007-05-29 23:58:41', '2007-05-30 00:00:01', NULL, 1, 2, 1, 1); |
1743 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (25, 1, true, '2007-07-08 12:00:00', NULL, NULL, NULL, NULL, 1, NULL, 1); |
1744 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (26, 1, true, '2007-07-08 00:00:00', '2007-07-07 23:58:41', '2007-07-08 00:00:01', NULL, 1, 2, 1, 1); |
1745 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (27, 1, true, '2007-07-24 00:00:00', '2007-07-23 23:58:41', '2007-07-24 00:00:01', NULL, 1, 1, 1, 1); |
1746 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (28, 3, true, '2007-08-10 00:00:00', '2007-08-10 00:00:00', '2007-08-10 00:00:13', NULL, 1, 1, 1, 1); |
1747 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (29, 1, false, '2007-08-09 21:54:18.553132', '2007-08-09 23:49:59', '2007-08-09 23:59:59', NULL, NULL, 1, NULL, 1); |
1748 | -INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type) VALUES (30, 3, false, '2007-08-10 00:00:01', '2007-08-10 00:00:01', '2007-08-10 00:00:14', NULL, 1, 1, 1, 1); |
1749 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (2, 1, false, '2004-09-27 11:57:13', '2004-09-27 11:55:13', '2004-09-27 11:57:14', NULL, 1, 1, 1, 1, 0); |
1750 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (6, 1, false, '2006-12-01 00:00:00', '2006-12-01 00:00:00', '2006-12-01 00:00:01', NULL, 1, 2, 1, 1, 0); |
1751 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (7, 1, false, '2005-03-24 00:00:00', '2005-03-24 23:58:43', '2005-03-25 00:00:03', NULL, 1, 1, 1, 1, 0); |
1752 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (8, 1, false, '2005-09-30 00:00:00', NULL, NULL, NULL, NULL, 6, NULL, 1, 0); |
1753 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (9, 1, false, '2005-10-01 00:00:00', '2005-10-01 23:56:41', '2005-10-02 00:00:01', NULL, 1, 2, 1, 1, 0); |
1754 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (10, 1, false, '2006-01-27 00:00:00', NULL, NULL, NULL, NULL, 1, NULL, 1, 0); |
1755 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (11, 1, false, '2006-02-14 00:00:00', NULL, NULL, NULL, NULL, 0, NULL, 1, 0); |
1756 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (12, 1, false, '2006-02-28 00:00:00', '2006-02-27 23:53:59', '2006-02-28 00:00:01', NULL, 1, 3, 1, 1, 0); |
1757 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (13, 1, false, '2006-03-21 00:00:00', '2006-03-21 00:58:33', '2006-03-21 01:00:03', NULL, 1, 5, 1, 1, 0); |
1758 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (14, 1, false, '2006-03-22 00:00:00', '2006-03-21 00:58:32', '2006-03-21 01:00:02', NULL, 1, 5, 1, 1, 0); |
1759 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (15, 1, false, '2006-03-22 00:00:01', '2006-03-21 00:58:30', '2006-03-21 01:00:00', NULL, 1, 5, 1, 1, 0); |
1760 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (16, 1, false, '2005-03-24 00:00:01', '2005-03-24 23:58:42', '2005-03-25 00:00:02', NULL, 1, 1, 1, 1, 0); |
1761 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (18, 1, false, '2004-09-27 11:57:14', '2004-09-27 11:55:12', '2004-09-27 11:57:13', NULL, 1, 1, 1, 1, 0); |
1762 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (19, 1, false, '2005-03-24 00:00:02', '2005-03-24 23:58:41', '2005-03-25 00:00:01', NULL, 1, 1, 1, 1, 0); |
1763 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (21, 1, false, '2006-12-01 00:00:01', NULL, NULL, NULL, NULL, 2, NULL, 1, 0); |
1764 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (22, 1, false, '2007-04-20 00:00:00', '2007-04-19 23:58:41', '2007-04-20 00:00:01', NULL, 1, 7, 1, 1, 0); |
1765 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (23, 1, false, '2006-04-11 12:00:00', NULL, NULL, NULL, NULL, 1, NULL, 1, 0); |
1766 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (24, 1, true, '2007-05-30 00:00:00', '2007-05-29 23:58:41', '2007-05-30 00:00:01', NULL, 1, 2, 1, 1, 0); |
1767 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (25, 1, true, '2007-07-08 12:00:00', NULL, NULL, NULL, NULL, 1, NULL, 1, 0); |
1768 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (26, 1, true, '2007-07-08 00:00:00', '2007-07-07 23:58:41', '2007-07-08 00:00:01', NULL, 1, 2, 1, 1, 0); |
1769 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (27, 1, true, '2007-07-24 00:00:00', '2007-07-23 23:58:41', '2007-07-24 00:00:01', NULL, 1, 1, 1, 1, 0); |
1770 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (28, 3, true, '2007-08-10 00:00:00', '2007-08-10 00:00:00', '2007-08-10 00:00:13', NULL, 1, 1, 1, 1, 0); |
1771 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (29, 1, false, '2007-08-09 21:54:18.553132', '2007-08-09 23:49:59', '2007-08-09 23:59:59', NULL, NULL, 1, NULL, 1, 0); |
1772 | +INSERT INTO buildfarmjob (id, processor, virtualized, date_created, date_started, date_finished, date_first_dispatched, builder, status, log, job_type, failure_count) VALUES (30, 3, false, '2007-08-10 00:00:01', '2007-08-10 00:00:01', '2007-08-10 00:00:14', NULL, 1, 1, 1, 1, 0); |
1773 | |
1774 | |
1775 | ALTER TABLE buildfarmjob ENABLE TRIGGER ALL; |
1776 | @@ -2365,29 +2395,29 @@ |
1777 | |
1778 | ALTER TABLE sourcepackagerelease DISABLE TRIGGER ALL; |
1779 | |
1780 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (14, 1, '0.9', '2004-09-27 11:57:13', 1, NULL, 1, 'Mozilla dummy Changelog......', 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1), pmount', 'bacula-common (= 1.34.6-2), bacula-director-common (= 1.34.6-2), postgresql-client (>= 7.4), pmount', 'any', NULL, 1, 1, 1, 1, 1, 'Mark Shuttleworth <mark@canonical.com>', '3.6.2', '1.0', 'mozilla-firefox', 1, NULL, 'gcc-4.0, pmount', 'gcc-4.0-base, pmount', NULL, NULL, NULL); |
1781 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (15, 1, '1.0', '2004-09-27 11:57:13', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 2, 1, 9, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1782 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (16, 1, '1.0-1', '2005-03-10 16:30:00', 1, NULL, 1, NULL, NULL, NULL, 'any', NULL, 3, 1, 10, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1783 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (17, 1, '0.99.6-1', '2005-03-14 18:00:00', 1, NULL, 1, NULL, NULL, NULL, 'i386', NULL, 2, 1, 10, 1, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1784 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (20, 1, '0.1-1', '2005-03-24 20:59:31.439579', 1, NULL, 1, 'pmount (0.1-1) hoary; urgency=low |
1785 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (14, 1, '0.9', '2004-09-27 11:57:13', 1, NULL, 1, 'Mozilla dummy Changelog......', 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1), pmount', 'bacula-common (= 1.34.6-2), bacula-director-common (= 1.34.6-2), postgresql-client (>= 7.4), pmount', 'any', NULL, 1, 1, 1, 1, 1, 'Mark Shuttleworth <mark@canonical.com>', '3.6.2', '1.0', 'mozilla-firefox', 1, NULL, 'gcc-4.0, pmount', 'gcc-4.0-base, pmount', NULL, NULL, NULL, NULL); |
1786 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (15, 1, '1.0', '2004-09-27 11:57:13', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 2, 1, 9, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1787 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (16, 1, '1.0-1', '2005-03-10 16:30:00', 1, NULL, 1, NULL, NULL, NULL, 'any', NULL, 3, 1, 10, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1788 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (17, 1, '0.99.6-1', '2005-03-14 18:00:00', 1, NULL, 1, NULL, NULL, NULL, 'i386', NULL, 2, 1, 10, 1, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1789 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (20, 1, '0.1-1', '2005-03-24 20:59:31.439579', 1, NULL, 1, 'pmount (0.1-1) hoary; urgency=low |
1790 | |
1791 | * Fix description (Malone #1) |
1792 | * Fix debian (Debian #2000) |
1793 | * Fix warty (Warty Ubuntu #1) |
1794 | |
1795 | - -- Sample Person <test@canonical.com> Tue, 7 Feb 2006 12:10:08 +0300', NULL, NULL, 'all', NULL, 2, 1, 14, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1796 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (21, 1, '0.1-2', '2005-06-24 20:59:31.439579', 1, NULL, 1, 'This is a placeholder changelog for pmount 0.1-2', NULL, NULL, 'powerpc', NULL, 1, 1, 14, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1797 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (23, 1, '1.0.8-1ubuntu1', '2005-02-03 08:50:00', 1, NULL, 1, 'alsa-utils (1.0.8-1ubuntu1) warty; urgency=low |
1798 | - |
1799 | - * Placeholder |
1800 | - |
1801 | - -- Sample Person <test@canonical.com> Tue, 7 Feb 2006 12:10:08 +0300', NULL, NULL, 'all', NULL, 1, 1, 19, 1, 1, 'Mark Shuttleworth <mark@example.com>', '3.6.2', '1.0', 'alsa-mixer', 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1802 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (24, 1, '1.0.9a-4', '2005-07-01 22:47:00', 1, NULL, 1, 'alsa-utils (1.0.9a-4) warty; urgency=low |
1803 | - |
1804 | - * Placeholder |
1805 | - |
1806 | - -- Sample Person <test@canonical.com> Tue, 7 Feb 2006 12:10:08 +0300', NULL, NULL, 'any', NULL, 2, 1, 19, 8, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1807 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (25, 1, '1.0.9a-4ubuntu1', '2005-08-01 14:10:00', 1, NULL, 1, 'alsa-utils (1.0.9a-4ubuntu1) hoary; urgency=low |
1808 | + -- Sample Person <test@canonical.com> Tue, 7 Feb 2006 12:10:08 +0300', NULL, NULL, 'all', NULL, 2, 1, 14, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1809 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (21, 1, '0.1-2', '2005-06-24 20:59:31.439579', 1, NULL, 1, 'This is a placeholder changelog for pmount 0.1-2', NULL, NULL, 'powerpc', NULL, 1, 1, 14, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1810 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (23, 1, '1.0.8-1ubuntu1', '2005-02-03 08:50:00', 1, NULL, 1, 'alsa-utils (1.0.8-1ubuntu1) warty; urgency=low |
1811 | + |
1812 | + * Placeholder |
1813 | + |
1814 | + -- Sample Person <test@canonical.com> Tue, 7 Feb 2006 12:10:08 +0300', NULL, NULL, 'all', NULL, 1, 1, 19, 1, 1, 'Mark Shuttleworth <mark@example.com>', '3.6.2', '1.0', 'alsa-mixer', 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1815 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (24, 1, '1.0.9a-4', '2005-07-01 22:47:00', 1, NULL, 1, 'alsa-utils (1.0.9a-4) warty; urgency=low |
1816 | + |
1817 | + * Placeholder |
1818 | + |
1819 | + -- Sample Person <test@canonical.com> Tue, 7 Feb 2006 12:10:08 +0300', NULL, NULL, 'any', NULL, 2, 1, 19, 8, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1820 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (25, 1, '1.0.9a-4ubuntu1', '2005-08-01 14:10:00', 1, NULL, 1, 'alsa-utils (1.0.9a-4ubuntu1) hoary; urgency=low |
1821 | |
1822 | * Placeholder |
1823 | LP: #10 |
1824 | @@ -2396,22 +2426,22 @@ |
1825 | LP: #7, #8, |
1826 | #11 |
1827 | |
1828 | - -- Sample Person <test@canonical.com> Tue, 7 Feb 2006 12:10:08 +0300', NULL, NULL, 'all', NULL, 1, 16, 19, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1829 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (26, 1, 'cr.g7-37', '2005-12-22 18:19:00', 1, NULL, 1, NULL, NULL, NULL, 'i386', NULL, 1, 16, 20, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1830 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (27, 1, 'b8p', '2006-02-10 11:19:00', 1, NULL, 1, 'libstdc++ (9.9-1) hoary; urgency=high |
1831 | + -- Sample Person <test@canonical.com> Tue, 7 Feb 2006 12:10:08 +0300', NULL, NULL, 'all', NULL, 1, 16, 19, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1832 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (26, 1, 'cr.g7-37', '2005-12-22 18:19:00', 1, NULL, 1, NULL, NULL, NULL, 'i386', NULL, 1, 16, 20, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1833 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (27, 1, 'b8p', '2006-02-10 11:19:00', 1, NULL, 1, 'libstdc++ (9.9-1) hoary; urgency=high |
1834 | |
1835 | * Placeholder |
1836 | |
1837 | - -- Sample Person <test@canonical.com> Tue, 10 Feb 2006 10:10:08 +0300', NULL, NULL, 'powerpc i386', NULL, 1, 16, 21, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1838 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (28, 1, '2.6.15.3', '2005-12-22 18:19:00', 1, NULL, 1, NULL, NULL, NULL, 'any', NULL, 1, 16, 22, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1839 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (29, 1, '0.00', '2005-12-22 18:19:00', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 17, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1840 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (30, 1, '1.0', '2006-09-28 18:19:00', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 20, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1841 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (31, 1, '1.0', '2006-09-28 18:19:01', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 20, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1842 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (32, 1, '1.0', '2006-12-01 13:19:01', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 23, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1843 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (33, 1, '1.0', '2006-12-01 13:19:01', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 24, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1844 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (34, 1, '1.0', '2007-02-15 14:19:01', 1, NULL, 1, NULL, NULL, NULL, 'i386', NULL, 29, 16, 25, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL); |
1845 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (35, 1, '1.0', '2006-04-11 11:19:01', 1, NULL, 1, NULL, NULL, NULL, 'any', NULL, 1, 16, 26, 1, 1, NULL, NULL, '1.0', NULL, 10, NULL, NULL, NULL, NULL, NULL, NULL); |
1846 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (36, 243606, '1.0-1', '2007-08-09 21:25:37.832976', 1, NULL, 5, 'commercialpackage (1.0-1) breezy; urgency=low |
1847 | + -- Sample Person <test@canonical.com> Tue, 10 Feb 2006 10:10:08 +0300', NULL, NULL, 'powerpc i386', NULL, 1, 16, 21, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1848 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (28, 1, '2.6.15.3', '2005-12-22 18:19:00', 1, NULL, 1, NULL, NULL, NULL, 'any', NULL, 1, 16, 22, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1849 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (29, 1, '0.00', '2005-12-22 18:19:00', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 17, 3, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1850 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (30, 1, '1.0', '2006-09-28 18:19:00', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 20, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1851 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (31, 1, '1.0', '2006-09-28 18:19:01', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 20, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1852 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (32, 1, '1.0', '2006-12-01 13:19:01', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 23, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1853 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (33, 1, '1.0', '2006-12-01 13:19:01', 1, NULL, 1, NULL, NULL, NULL, 'all', NULL, 1, 16, 24, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1854 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (34, 1, '1.0', '2007-02-15 14:19:01', 1, NULL, 1, NULL, NULL, NULL, 'i386', NULL, 29, 16, 25, 10, 1, NULL, NULL, '1.0', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1855 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (35, 1, '1.0', '2006-04-11 11:19:01', 1, NULL, 1, NULL, NULL, NULL, 'any', NULL, 1, 16, 26, 1, 1, NULL, NULL, '1.0', NULL, 10, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1856 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (36, 243606, '1.0-1', '2007-08-09 21:25:37.832976', 1, NULL, 5, 'commercialpackage (1.0-1) breezy; urgency=low |
1857 | |
1858 | * Initial version |
1859 | Address for testing linkification: Foo Bar <foo.bar@canonical.com> |
1860 | @@ -2435,8 +2465,8 @@ |
1861 | iD8DBQFGtzTjWhGlTF8G/HcRAtFsAJ4hHyKhOnsUOQDI+SAk000DmFAnUgCcC84J |
1862 | 3F4bEPeRcnUjCFI/hjR0kxg= |
1863 | =Tjln |
1864 | -', 7, 243606, 27, 10, 1, 'Julian Edwards <launchpad@julian-edwards.com>', '3.6.2', '1.0', 'commercialpackage', 12, NULL, NULL, NULL, NULL, NULL, NULL); |
1865 | -INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields) VALUES (37, 1, '1.0', '2006-04-11 11:19:01', 1, NULL, 1, NULL, NULL, NULL, 'i386', NULL, 1, 16, 26, 1, 1, NULL, NULL, '1.0', NULL, 11, NULL, NULL, NULL, NULL, NULL, NULL); |
1866 | +', 7, 243606, 27, 10, 1, 'Julian Edwards <launchpad@julian-edwards.com>', '3.6.2', '1.0', 'commercialpackage', 12, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1867 | +INSERT INTO sourcepackagerelease (id, creator, version, dateuploaded, urgency, dscsigningkey, component, changelog_entry, builddepends, builddependsindep, architecturehintlist, dsc, section, maintainer, sourcepackagename, upload_distroseries, format, dsc_maintainer_rfc822, dsc_standards_version, dsc_format, dsc_binaries, upload_archive, copyright, build_conflicts, build_conflicts_indep, sourcepackage_recipe_build, changelog, user_defined_fields, homepage) VALUES (37, 1, '1.0', '2006-04-11 11:19:01', 1, NULL, 1, NULL, NULL, NULL, 'i386', NULL, 1, 16, 26, 1, 1, NULL, NULL, '1.0', NULL, 11, NULL, NULL, NULL, NULL, NULL, NULL, NULL); |
1868 | |
1869 | |
1870 | ALTER TABLE sourcepackagerelease ENABLE TRIGGER ALL; |
1871 | @@ -2490,21 +2520,21 @@ |
1872 | |
1873 | ALTER TABLE binarypackagerelease DISABLE TRIGGER ALL; |
1874 | |
1875 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (6, 6, '1.0', 'foobar is bad', 'foobar should be removed', 6, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2006-12-01 17:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1876 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (12, 8, '0.9', 'Mozilla Firefox Web Browser', 'Mozilla Firefox Web Browser is .....', 2, 1, 1, 1, 10, NULL, 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1)', 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1)', 'firefox-gnome-support (= 1.0.7-0ubuntu20), latex-xft-fonts, xprint', 'firefox, mozilla-web-browser', 'gnome-mozilla-browser', 'mozilla-firefox', false, NULL, true, NULL, '2005-10-19 17:50:10.874189', 'pmount, foo', 'pmount, bar', 'pmount, baz', NULL, NULL); |
1877 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (15, 13, '0.1-1', 'pmount shortdesc', 'pmount description', 7, 1, 1, 1, 40, NULL, 'at (>= 3.14156), linux-2.6.12, tramp-package', NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1878 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (16, 14, '2.6.12.20', 'the kernel of boom', 'this kernel is like the crystal method: a temple of boom', 14, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1879 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (17, 15, '3.14156', 'at the mountains of madness', 'lovecraft long before enunciated that the mountains were not safe, but you did not believe him', 15, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1880 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (18, 13, '2:1.9-1', 'pmount shortdesc', 'pmount description', 16, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, true, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1881 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (19, 8, '0.9', 'Mozilla Firefox Web Browser', 'Mozilla Firefox Web Browser is .....', 18, 1, 1, 1, 10, NULL, 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1)', 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1)', 'firefox-gnome-support (= 1.0.7-0ubuntu20), latex-xft-fonts, xprint', 'firefox, mozilla-web-browser', 'gnome-mozilla-browser', 'mozilla-firefox', false, NULL, true, NULL, '2005-10-19 17:50:10.874189', NULL, NULL, NULL, NULL, NULL); |
1882 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (20, 13, '0.1-1', 'pmount shortdesc', 'pmount description', 19, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1883 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (21, 16, '1.0', 'cdrkit is nice', 'cdrkit should be kept', 21, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2006-12-01 17:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1884 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (22, 8, '1.0', 'ff from iceweasel', 'iceweasel huh ?', 23, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, true, NULL, '2006-04-11 12:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1885 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (23, 13, '0.1-1', 'pmount shortdesc', 'pmount description', 27, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2007-07-24 17:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1886 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (24, 8, '1.0', 'ff from iceweasel', 'iceweasel huh ?', 28, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, true, NULL, '2006-08-10 12:50:10.878712', NULL, NULL, NULL, NULL, NULL); |
1887 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (25, 17, '1.0-1', 'Stuff for testing', ' This package is simply used for testing soyuz', 29, 1, 5, 7, 20, '', '', '', '', '', '', '', false, 8, true, NULL, '2007-08-09 21:54:18.456616', NULL, NULL, NULL, NULL, NULL); |
1888 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (26, 8, '0.9', 'Mozilla Firefox Web Browser', 'Mozilla Firefox Web Browser is .....', 30, 1, 1, 1, 10, '', '', '', '', '', '', '', false, NULL, true, NULL, '2005-10-19 17:50:10.874189', NULL, NULL, NULL, NULL, NULL); |
1889 | -INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields) VALUES (27, 18, '0.9', 'Mozilla Firefox Data', 'Mozilla Firefox Data is .....', 2, 1, 1, 1, 10, '', '', '', '', '', '', '', false, NULL, false, NULL, '2005-10-19 17:50:10.874189', NULL, NULL, NULL, NULL, NULL); |
1890 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (6, 6, '1.0', 'foobar is bad', 'foobar should be removed', 6, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2006-12-01 17:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1891 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (12, 8, '0.9', 'Mozilla Firefox Web Browser', 'Mozilla Firefox Web Browser is .....', 2, 1, 1, 1, 10, NULL, 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1)', 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1)', 'firefox-gnome-support (= 1.0.7-0ubuntu20), latex-xft-fonts, xprint', 'firefox, mozilla-web-browser', 'gnome-mozilla-browser', 'mozilla-firefox', false, NULL, true, NULL, '2005-10-19 17:50:10.874189', 'pmount, foo', 'pmount, bar', 'pmount, baz', NULL, NULL, NULL); |
1892 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (15, 13, '0.1-1', 'pmount shortdesc', 'pmount description', 7, 1, 1, 1, 40, NULL, 'at (>= 3.14156), linux-2.6.12, tramp-package', NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1893 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (16, 14, '2.6.12.20', 'the kernel of boom', 'this kernel is like the crystal method: a temple of boom', 14, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1894 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (17, 15, '3.14156', 'at the mountains of madness', 'lovecraft long before enunciated that the mountains were not safe, but you did not believe him', 15, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1895 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (18, 13, '2:1.9-1', 'pmount shortdesc', 'pmount description', 16, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, true, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1896 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (19, 8, '0.9', 'Mozilla Firefox Web Browser', 'Mozilla Firefox Web Browser is .....', 18, 1, 1, 1, 10, NULL, 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1)', 'gcc-3.4-base, libc6 (>= 2.3.2.ds1-4), gcc-3.4 (>= 3.4.1-4sarge1), gcc-3.4 (<< 3.4.2), libstdc++6-dev (>= 3.4.1-4sarge1)', 'firefox-gnome-support (= 1.0.7-0ubuntu20), latex-xft-fonts, xprint', 'firefox, mozilla-web-browser', 'gnome-mozilla-browser', 'mozilla-firefox', false, NULL, true, NULL, '2005-10-19 17:50:10.874189', NULL, NULL, NULL, NULL, NULL, NULL); |
1897 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (20, 13, '0.1-1', 'pmount shortdesc', 'pmount description', 19, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2005-10-19 17:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1898 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (21, 16, '1.0', 'cdrkit is nice', 'cdrkit should be kept', 21, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2006-12-01 17:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1899 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (22, 8, '1.0', 'ff from iceweasel', 'iceweasel huh ?', 23, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, true, NULL, '2006-04-11 12:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1900 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (23, 13, '0.1-1', 'pmount shortdesc', 'pmount description', 27, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, false, NULL, '2007-07-24 17:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1901 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (24, 8, '1.0', 'ff from iceweasel', 'iceweasel huh ?', 28, 1, 1, 1, 40, NULL, NULL, NULL, NULL, NULL, NULL, NULL, false, NULL, true, NULL, '2006-08-10 12:50:10.878712', NULL, NULL, NULL, NULL, NULL, NULL); |
1902 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (25, 17, '1.0-1', 'Stuff for testing', ' This package is simply used for testing soyuz', 29, 1, 5, 7, 20, '', '', '', '', '', '', '', false, 8, true, NULL, '2007-08-09 21:54:18.456616', NULL, NULL, NULL, NULL, NULL, NULL); |
1903 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (26, 8, '0.9', 'Mozilla Firefox Web Browser', 'Mozilla Firefox Web Browser is .....', 30, 1, 1, 1, 10, '', '', '', '', '', '', '', false, NULL, true, NULL, '2005-10-19 17:50:10.874189', NULL, NULL, NULL, NULL, NULL, NULL); |
1904 | +INSERT INTO binarypackagerelease (id, binarypackagename, version, summary, description, build, binpackageformat, component, section, priority, shlibdeps, depends, recommends, suggests, conflicts, replaces, provides, essential, installedsize, architecturespecific, fti, datecreated, pre_depends, enhances, breaks, debug_package, user_defined_fields, homepage) VALUES (27, 18, '0.9', 'Mozilla Firefox Data', 'Mozilla Firefox Data is .....', 2, 1, 1, 1, 10, '', '', '', '', '', '', '', false, NULL, false, NULL, '2005-10-19 17:50:10.874189', NULL, NULL, NULL, NULL, NULL, NULL); |
1905 | |
1906 | |
1907 | ALTER TABLE binarypackagerelease ENABLE TRIGGER ALL; |
1908 | @@ -3074,25 +3104,25 @@ |
1909 | |
1910 | ALTER TABLE branchrevision DISABLE TRIGGER ALL; |
1911 | |
1912 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (1, 1, 10, 1); |
1913 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (2, 1, 11, 2); |
1914 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (3, 1, 12, 3); |
1915 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (4, 1, 20, 4); |
1916 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (5, 2, 20, 5); |
1917 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (6, 3, 20, 6); |
1918 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (7, 4, 20, 7); |
1919 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (8, 5, 20, 8); |
1920 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (9, 6, 20, 9); |
1921 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (10, 1, 21, 4); |
1922 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (11, 2, 21, 5); |
1923 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (12, 3, 21, 10); |
1924 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (13, 4, 21, 11); |
1925 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (14, 5, 21, 8); |
1926 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (15, 6, 21, 9); |
1927 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (16, NULL, 20, 10); |
1928 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (17, NULL, 20, 11); |
1929 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (18, NULL, 21, 6); |
1930 | -INSERT INTO branchrevision (id, sequence, branch, revision) VALUES (19, NULL, 21, 7); |
1931 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 10, 1); |
1932 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 11, 2); |
1933 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 12, 3); |
1934 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 20, 4); |
1935 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (1, 21, 4); |
1936 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (2, 20, 5); |
1937 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (2, 21, 5); |
1938 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (3, 20, 6); |
1939 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (3, 21, 10); |
1940 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (4, 20, 7); |
1941 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (4, 21, 11); |
1942 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (5, 20, 8); |
1943 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (5, 21, 8); |
1944 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (6, 20, 9); |
1945 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (6, 21, 9); |
1946 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (NULL, 20, 10); |
1947 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (NULL, 20, 11); |
1948 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (NULL, 21, 6); |
1949 | +INSERT INTO branchrevision (sequence, branch, revision) VALUES (NULL, 21, 7); |
1950 | |
1951 | |
1952 | ALTER TABLE branchrevision ENABLE TRIGGER ALL; |
1953 | @@ -3315,42 +3345,42 @@ |
1954 | |
1955 | ALTER TABLE bugmessage DISABLE TRIGGER ALL; |
1956 | |
1957 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (1, 2, 1, NULL, NULL, true); |
1958 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (2, 1, 3, NULL, NULL, true); |
1959 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (3, 1, 4, NULL, NULL, true); |
1960 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (4, 2, 5, NULL, NULL, true); |
1961 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (5, 2, 6, NULL, NULL, true); |
1962 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (6, 4, 7, NULL, NULL, true); |
1963 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (7, 5, 8, NULL, NULL, true); |
1964 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (8, 6, 9, NULL, NULL, true); |
1965 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (9, 3, 10, NULL, NULL, true); |
1966 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (10, 7, 11, NULL, NULL, true); |
1967 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (11, 8, 14, NULL, NULL, true); |
1968 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (12, 9, 15, NULL, NULL, true); |
1969 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (13, 10, 17, NULL, NULL, true); |
1970 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (14, 10, 16, NULL, NULL, true); |
1971 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (15, 11, 24, NULL, NULL, true); |
1972 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (16, 11, 25, NULL, NULL, true); |
1973 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (17, 11, 26, NULL, NULL, true); |
1974 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (18, 11, 27, NULL, NULL, true); |
1975 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (19, 11, 28, NULL, NULL, true); |
1976 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (20, 11, 29, NULL, NULL, true); |
1977 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (21, 11, 30, NULL, NULL, true); |
1978 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (22, 12, 31, NULL, NULL, true); |
1979 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (23, 12, 33, NULL, NULL, true); |
1980 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (24, 12, 34, NULL, NULL, true); |
1981 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (25, 12, 35, NULL, NULL, true); |
1982 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (26, 12, 36, NULL, NULL, true); |
1983 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (27, 13, 37, NULL, NULL, true); |
1984 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (28, 13, 38, NULL, NULL, true); |
1985 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (29, 14, 39, NULL, NULL, true); |
1986 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (30, 15, 40, NULL, NULL, true); |
1987 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (31, 15, 44, 11, '<4284D7D1.6010208@gmx.de>', true); |
1988 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (32, 15, 45, 11, '<20050517185429.GB20786@spring.luon.net>', true); |
1989 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (33, 15, 46, 11, '<428A44E9.6090802@gmx.de>', true); |
1990 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (34, 15, 47, 11, '<20050517202044.GA23231@spring.luon.net>', true); |
1991 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (35, 15, 48, 11, '<20050617140011.GA15638@piware.de>', true); |
1992 | -INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible) VALUES (36, 15, 49, 11, '<42BD2E36.9090809@gmx.de>', true); |
1993 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (1, 2, 1, NULL, NULL, true, NULL); |
1994 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (2, 1, 3, NULL, NULL, true, NULL); |
1995 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (3, 1, 4, NULL, NULL, true, NULL); |
1996 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (4, 2, 5, NULL, NULL, true, NULL); |
1997 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (5, 2, 6, NULL, NULL, true, NULL); |
1998 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (6, 4, 7, NULL, NULL, true, NULL); |
1999 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (7, 5, 8, NULL, NULL, true, NULL); |
2000 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (8, 6, 9, NULL, NULL, true, NULL); |
2001 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (9, 3, 10, NULL, NULL, true, NULL); |
2002 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (10, 7, 11, NULL, NULL, true, NULL); |
2003 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (11, 8, 14, NULL, NULL, true, NULL); |
2004 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (12, 9, 15, NULL, NULL, true, NULL); |
2005 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (13, 10, 17, NULL, NULL, true, NULL); |
2006 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (14, 10, 16, NULL, NULL, true, NULL); |
2007 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (15, 11, 24, NULL, NULL, true, NULL); |
2008 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (16, 11, 25, NULL, NULL, true, NULL); |
2009 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (17, 11, 26, NULL, NULL, true, NULL); |
2010 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (18, 11, 27, NULL, NULL, true, NULL); |
2011 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (19, 11, 28, NULL, NULL, true, NULL); |
2012 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (20, 11, 29, NULL, NULL, true, NULL); |
2013 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (21, 11, 30, NULL, NULL, true, NULL); |
2014 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (22, 12, 31, NULL, NULL, true, NULL); |
2015 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (23, 12, 33, NULL, NULL, true, NULL); |
2016 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (24, 12, 34, NULL, NULL, true, NULL); |
2017 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (25, 12, 35, NULL, NULL, true, NULL); |
2018 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (26, 12, 36, NULL, NULL, true, NULL); |
2019 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (27, 13, 37, NULL, NULL, true, NULL); |
2020 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (28, 13, 38, NULL, NULL, true, NULL); |
2021 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (29, 14, 39, NULL, NULL, true, NULL); |
2022 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (30, 15, 40, NULL, NULL, true, NULL); |
2023 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (31, 15, 44, 11, '<4284D7D1.6010208@gmx.de>', true, NULL); |
2024 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (32, 15, 45, 11, '<20050517185429.GB20786@spring.luon.net>', true, NULL); |
2025 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (33, 15, 46, 11, '<428A44E9.6090802@gmx.de>', true, NULL); |
2026 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (34, 15, 47, 11, '<20050517202044.GA23231@spring.luon.net>', true, NULL); |
2027 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (35, 15, 48, 11, '<20050617140011.GA15638@piware.de>', true, NULL); |
2028 | +INSERT INTO bugmessage (id, bug, message, bugwatch, remote_comment_id, visible, index) VALUES (36, 15, 49, 11, '<42BD2E36.9090809@gmx.de>', true, NULL); |
2029 | |
2030 | |
2031 | ALTER TABLE bugmessage ENABLE TRIGGER ALL; |
2032 | @@ -3674,6 +3704,45 @@ |
2033 | ALTER TABLE bugsubscription ENABLE TRIGGER ALL; |
2034 | |
2035 | |
2036 | +ALTER TABLE structuralsubscription DISABLE TRIGGER ALL; |
2037 | + |
2038 | +INSERT INTO structuralsubscription (id, product, productseries, project, milestone, distribution, distroseries, sourcepackagename, subscriber, subscribed_by, bug_notification_level, blueprint_notification_level, date_created, date_last_updated) VALUES (1, NULL, NULL, NULL, NULL, 1, NULL, 1, 16, 16, 40, 10, '2008-01-29 15:12:34.581468', '2008-01-29 15:12:34.581468'); |
2039 | +INSERT INTO structuralsubscription (id, product, productseries, project, milestone, distribution, distroseries, sourcepackagename, subscriber, subscribed_by, bug_notification_level, blueprint_notification_level, date_created, date_last_updated) VALUES (2, NULL, NULL, NULL, NULL, 1, NULL, 14, 16, 16, 40, 10, '2008-01-29 15:12:34.581468', '2008-01-29 15:12:34.581468'); |
2040 | +INSERT INTO structuralsubscription (id, product, productseries, project, milestone, distribution, distroseries, sourcepackagename, subscriber, subscribed_by, bug_notification_level, blueprint_notification_level, date_created, date_last_updated) VALUES (3, 22, NULL, NULL, NULL, NULL, NULL, NULL, 64, 64, 40, 10, '2008-02-06 12:17:13.030376', '2008-02-06 12:17:13.030376'); |
2041 | +INSERT INTO structuralsubscription (id, product, productseries, project, milestone, distribution, distroseries, sourcepackagename, subscriber, subscribed_by, bug_notification_level, blueprint_notification_level, date_created, date_last_updated) VALUES (4, 16, NULL, NULL, NULL, NULL, NULL, NULL, 64, 64, 40, 10, '2008-02-06 12:17:13.030376', '2008-02-06 12:17:13.030376'); |
2042 | + |
2043 | + |
2044 | +ALTER TABLE structuralsubscription ENABLE TRIGGER ALL; |
2045 | + |
2046 | + |
2047 | +ALTER TABLE bugsubscriptionfilter DISABLE TRIGGER ALL; |
2048 | + |
2049 | + |
2050 | + |
2051 | +ALTER TABLE bugsubscriptionfilter ENABLE TRIGGER ALL; |
2052 | + |
2053 | + |
2054 | +ALTER TABLE bugsubscriptionfilterimportance DISABLE TRIGGER ALL; |
2055 | + |
2056 | + |
2057 | + |
2058 | +ALTER TABLE bugsubscriptionfilterimportance ENABLE TRIGGER ALL; |
2059 | + |
2060 | + |
2061 | +ALTER TABLE bugsubscriptionfilterstatus DISABLE TRIGGER ALL; |
2062 | + |
2063 | + |
2064 | + |
2065 | +ALTER TABLE bugsubscriptionfilterstatus ENABLE TRIGGER ALL; |
2066 | + |
2067 | + |
2068 | +ALTER TABLE bugsubscriptionfiltertag DISABLE TRIGGER ALL; |
2069 | + |
2070 | + |
2071 | + |
2072 | +ALTER TABLE bugsubscriptionfiltertag ENABLE TRIGGER ALL; |
2073 | + |
2074 | + |
2075 | ALTER TABLE bugtag DISABLE TRIGGER ALL; |
2076 | |
2077 | INSERT INTO bugtag (id, bug, tag) VALUES (1, 9, 'crash'); |
2078 | @@ -3735,6 +3804,27 @@ |
2079 | ALTER TABLE bugtrackeralias ENABLE TRIGGER ALL; |
2080 | |
2081 | |
2082 | +ALTER TABLE bugtrackercomponentgroup DISABLE TRIGGER ALL; |
2083 | + |
2084 | + |
2085 | + |
2086 | +ALTER TABLE bugtrackercomponentgroup ENABLE TRIGGER ALL; |
2087 | + |
2088 | + |
2089 | +ALTER TABLE distributionsourcepackage DISABLE TRIGGER ALL; |
2090 | + |
2091 | + |
2092 | + |
2093 | +ALTER TABLE distributionsourcepackage ENABLE TRIGGER ALL; |
2094 | + |
2095 | + |
2096 | +ALTER TABLE bugtrackercomponent DISABLE TRIGGER ALL; |
2097 | + |
2098 | + |
2099 | + |
2100 | +ALTER TABLE bugtrackercomponent ENABLE TRIGGER ALL; |
2101 | + |
2102 | + |
2103 | ALTER TABLE bugtrackerperson DISABLE TRIGGER ALL; |
2104 | |
2105 | |
2106 | @@ -3936,6 +4026,13 @@ |
2107 | ALTER TABLE distributionbounty ENABLE TRIGGER ALL; |
2108 | |
2109 | |
2110 | +ALTER TABLE distributionjob DISABLE TRIGGER ALL; |
2111 | + |
2112 | + |
2113 | + |
2114 | +ALTER TABLE distributionjob ENABLE TRIGGER ALL; |
2115 | + |
2116 | + |
2117 | ALTER TABLE distributionmirror DISABLE TRIGGER ALL; |
2118 | |
2119 | INSERT INTO distributionmirror (id, distribution, name, http_base_url, ftp_base_url, rsync_base_url, displayname, description, owner, speed, country, content, official_candidate, enabled, date_created, whiteboard, status, date_reviewed, reviewer, country_dns_mirror) VALUES (1, 1, 'archive-mirror', 'http://localhost:11375/valid-mirror/', NULL, NULL, NULL, NULL, 1, 10, 75, 1, true, true, '2006-10-16 18:31:43.434567', NULL, 30, NULL, NULL, false); |
2120 | @@ -3953,13 +4050,6 @@ |
2121 | ALTER TABLE distributionmirror ENABLE TRIGGER ALL; |
2122 | |
2123 | |
2124 | -ALTER TABLE distributionsourcepackage DISABLE TRIGGER ALL; |
2125 | - |
2126 | - |
2127 | - |
2128 | -ALTER TABLE distributionsourcepackage ENABLE TRIGGER ALL; |
2129 | - |
2130 | - |
2131 | ALTER TABLE distributionsourcepackagecache DISABLE TRIGGER ALL; |
2132 | |
2133 | INSERT INTO distributionsourcepackagecache (id, distribution, sourcepackagename, name, binpkgnames, binpkgsummaries, binpkgdescriptions, fti, changelog, archive) VALUES (1, 3, 19, 'alsa-utils', '', '', '', NULL, NULL, 1); |
2134 | @@ -4000,6 +4090,27 @@ |
2135 | ALTER TABLE distrocomponentuploader ENABLE TRIGGER ALL; |
2136 | |
2137 | |
2138 | +ALTER TABLE packagediff DISABLE TRIGGER ALL; |
2139 | + |
2140 | + |
2141 | + |
2142 | +ALTER TABLE packagediff ENABLE TRIGGER ALL; |
2143 | + |
2144 | + |
2145 | +ALTER TABLE distroseriesdifference DISABLE TRIGGER ALL; |
2146 | + |
2147 | + |
2148 | + |
2149 | +ALTER TABLE distroseriesdifference ENABLE TRIGGER ALL; |
2150 | + |
2151 | + |
2152 | +ALTER TABLE distroseriesdifferencemessage DISABLE TRIGGER ALL; |
2153 | + |
2154 | + |
2155 | + |
2156 | +ALTER TABLE distroseriesdifferencemessage ENABLE TRIGGER ALL; |
2157 | + |
2158 | + |
2159 | ALTER TABLE distroserieslanguage DISABLE TRIGGER ALL; |
2160 | |
2161 | INSERT INTO distroserieslanguage (id, distroseries, language, currentcount, updatescount, rosettacount, contributorcount, dateupdated, unreviewed_count) VALUES (1, 3, 68, 62, 0, 0, 1, '2007-01-15 17:58:40.839938', 0); |
2162 | @@ -4489,6 +4600,13 @@ |
2163 | ALTER TABLE hwtestanswerdevice ENABLE TRIGGER ALL; |
2164 | |
2165 | |
2166 | +ALTER TABLE incrementaldiff DISABLE TRIGGER ALL; |
2167 | + |
2168 | + |
2169 | + |
2170 | +ALTER TABLE incrementaldiff ENABLE TRIGGER ALL; |
2171 | + |
2172 | + |
2173 | ALTER TABLE ircid DISABLE TRIGGER ALL; |
2174 | |
2175 | INSERT INTO ircid (id, person, network, nickname) VALUES (1, 1, 'irc.freenode.net', 'mark'); |
2176 | @@ -5986,13 +6104,6 @@ |
2177 | ALTER TABLE packagecopyrequest ENABLE TRIGGER ALL; |
2178 | |
2179 | |
2180 | -ALTER TABLE packagediff DISABLE TRIGGER ALL; |
2181 | - |
2182 | - |
2183 | - |
2184 | -ALTER TABLE packagediff ENABLE TRIGGER ALL; |
2185 | - |
2186 | - |
2187 | ALTER TABLE packageselection DISABLE TRIGGER ALL; |
2188 | |
2189 | |
2190 | @@ -10462,17 +10573,6 @@ |
2191 | ALTER TABLE standardshipitrequest ENABLE TRIGGER ALL; |
2192 | |
2193 | |
2194 | -ALTER TABLE structuralsubscription DISABLE TRIGGER ALL; |
2195 | - |
2196 | -INSERT INTO structuralsubscription (id, product, productseries, project, milestone, distribution, distroseries, sourcepackagename, subscriber, subscribed_by, bug_notification_level, blueprint_notification_level, date_created, date_last_updated) VALUES (1, NULL, NULL, NULL, NULL, 1, NULL, 1, 16, 16, 40, 10, '2008-01-29 15:12:34.581468', '2008-01-29 15:12:34.581468'); |
2197 | -INSERT INTO structuralsubscription (id, product, productseries, project, milestone, distribution, distroseries, sourcepackagename, subscriber, subscribed_by, bug_notification_level, blueprint_notification_level, date_created, date_last_updated) VALUES (2, NULL, NULL, NULL, NULL, 1, NULL, 14, 16, 16, 40, 10, '2008-01-29 15:12:34.581468', '2008-01-29 15:12:34.581468'); |
2198 | -INSERT INTO structuralsubscription (id, product, productseries, project, milestone, distribution, distroseries, sourcepackagename, subscriber, subscribed_by, bug_notification_level, blueprint_notification_level, date_created, date_last_updated) VALUES (3, 22, NULL, NULL, NULL, NULL, NULL, NULL, 64, 64, 40, 10, '2008-02-06 12:17:13.030376', '2008-02-06 12:17:13.030376'); |
2199 | -INSERT INTO structuralsubscription (id, product, productseries, project, milestone, distribution, distroseries, sourcepackagename, subscriber, subscribed_by, bug_notification_level, blueprint_notification_level, date_created, date_last_updated) VALUES (4, 16, NULL, NULL, NULL, NULL, NULL, NULL, 64, 64, 40, 10, '2008-02-06 12:17:13.030376', '2008-02-06 12:17:13.030376'); |
2200 | - |
2201 | - |
2202 | -ALTER TABLE structuralsubscription ENABLE TRIGGER ALL; |
2203 | - |
2204 | - |
2205 | ALTER TABLE suggestivepotemplate DISABLE TRIGGER ALL; |
2206 | |
2207 | |
2208 | @@ -11081,6 +11181,13 @@ |
2209 | ALTER TABLE translationtemplateitem ENABLE TRIGGER ALL; |
2210 | |
2211 | |
2212 | +ALTER TABLE translationtemplatesbuild DISABLE TRIGGER ALL; |
2213 | + |
2214 | + |
2215 | + |
2216 | +ALTER TABLE translationtemplatesbuild ENABLE TRIGGER ALL; |
2217 | + |
2218 | + |
2219 | ALTER TABLE translator DISABLE TRIGGER ALL; |
2220 | |
2221 | INSERT INTO translator (id, translationgroup, language, translator, datecreated, style_guide_url) VALUES (1, 1, 387, 53, '2005-07-13 13:14:19.748396', NULL); |
2222 | |
2223 | === modified file 'database/schema/comments.sql' |
2224 | --- database/schema/comments.sql 2010-09-03 16:43:11 +0000 |
2225 | +++ database/schema/comments.sql 2010-10-04 22:08:24 +0000 |
2226 | @@ -346,6 +346,21 @@ |
2227 | COMMENT ON COLUMN BugTrackerPerson.name IS 'The (within the bug tracker) unique username in the external bug tracker.'; |
2228 | COMMENT ON COLUMN BugTrackerPerson.person IS 'The Person record in Launchpad this user corresponds to.'; |
2229 | |
2230 | +-- BugTrackerComponent |
2231 | + |
2232 | +COMMENT ON TABLE BugTrackerComponent IS 'A software component in a remote bug tracker, which can be linked to the corresponding source package in a distribution using this table.'; |
2233 | +COMMENT ON COLUMN BugTrackerComponent.name IS 'The name of the component as registered in the remote bug tracker.'; |
2234 | +COMMENT ON COLUMN BugTrackerComponent.is_visible IS 'Whether to display or hide the item in the Launchpad user interface.'; |
2235 | +COMMENT ON COLUMN BugTrackerComponent.is_custom IS 'Whether the item was added by a user in Launchpad or is kept in sync with the remote bug tracker.'; |
2236 | +COMMENT ON COLUMN BugTrackerComponent.component_group IS 'The product or other higher level category used by the remote bug tracker to group projects, if any.'; |
2237 | +COMMENT ON COLUMN BugTrackerComponent.distro_source_package IS 'A link to the source package in a distribution that corresponds to this component. This can be undefined if no link has been established yet.'; |
2238 | + |
2239 | +-- BugTrackerComponentGroup |
2240 | + |
2241 | +COMMENT ON TABLE BugTrackerComponentGroup IS 'A collection of components as modeled in a remote bug tracker, often referred to as a product. Some bug trackers do not categorize software components this way, so they will have a single default component group that all components belong to.'; |
2242 | +COMMENT ON COLUMN BugTrackerComponentGroup.name IS 'The product or category name used in the remote bug tracker for grouping components.'; |
2243 | +COMMENT ON COLUMN BugTrackerComponentGroup.bug_tracker IS 'The external bug tracker this component group belongs to.'; |
2244 | + |
2245 | -- BugCve |
2246 | |
2247 | COMMENT ON TABLE BugCve IS 'A table that records the link between a given malone bug number, and a CVE entry.'; |
2248 | @@ -532,9 +547,12 @@ |
2249 | COMMENT ON TABLE DistroSeriesDifference IS 'A difference of versions for a package in a derived distroseries and its parent distroseries.'; |
2250 | COMMENT ON COLUMN DistroSeriesDifference.derived_series IS 'The derived distroseries with the difference from its parent.'; |
2251 | COMMENT ON COLUMN DistroSeriesDifference.source_package_name IS 'The name of the source package which is different in the two series.'; |
2252 | -COMMENT ON COLUMN DistroSeriesDifference.package_diff IS 'The most recent package diff that was created for this difference.'; |
2253 | +COMMENT ON COLUMN DistroSeriesDifference.package_diff IS 'The most recent package diff that was created for the base version to derived version.'; |
2254 | +COMMENT ON COLUMN DistroSeriesDifference.parent_package_diff IS 'The most recent package diff that was created for the base version to the parent version.'; |
2255 | COMMENT ON COLUMN DistroSeriesDifference.status IS 'A distroseries difference can be needing attention, ignored or resolved.'; |
2256 | COMMENT ON COLUMN DistroSeriesDifference.difference_type IS 'The type of difference that this record represents - a package unique to the derived series, or missing, or in both.'; |
2257 | +COMMENT ON COLUMN DistroSeriesDifference.source_version IS 'The version of the package in the derived series.'; |
2258 | +COMMENT ON COLUMN DistroSeriesDifference.parent_source_version IS 'The version of the package in the parent series.'; |
2259 | |
2260 | -- DistroSeriesDifferenceMessage |
2261 | COMMENT ON TABLE DistroSeriesDifferenceMessage IS 'A message/comment on a distro series difference.'; |
2262 | @@ -839,6 +857,11 @@ |
2263 | COMMENT ON COLUMN TranslationRelicensingAgreement.allow_relicensing IS 'Does this person want their translations relicensed under BSD.'; |
2264 | COMMENT ON COLUMN TranslationRelicensingAgreement.date_decided IS 'Date when the last change of opinion was registered.'; |
2265 | |
2266 | +-- TranslationTemplatesBuild |
2267 | +COMMENT ON TABLE TranslationTemplatesBuild IS 'Build-farm record of a translation templates build.'; |
2268 | +COMMENT ON COLUMN TranslationTemplatesBuild.build_farm_job IS 'Associated BuildFarmJob.'; |
2269 | +COMMENT ON COLUMN TranslationTemplatesBuild.branch IS 'Branch to build templates out of.'; |
2270 | + |
2271 | -- RevisionAuthor |
2272 | COMMENT ON TABLE RevisionAuthor IS 'All distinct authors for revisions.'; |
2273 | COMMENT ON COLUMN RevisionAuthor.name IS 'The exact text extracted from the branch revision.'; |
2274 | @@ -1171,6 +1194,7 @@ |
2275 | COMMENT ON COLUMN DistroArchSeries.package_count IS 'A cache of the number of binary packages published in this distro arch release. The count only includes packages published in the release pocket.'; |
2276 | COMMENT ON COLUMN DistroArchSeries.supports_virtualized IS 'Whether or not |
2277 | virtualized build support should be provided by this specific distroarchseries'; |
2278 | +COMMENT ON COLUMN DistroArchSeries.enabled IS 'Whether to allow build creation and publishing for this DistroArchSeries.'; |
2279 | |
2280 | -- LauncpadDatabaseRevision |
2281 | COMMENT ON TABLE LaunchpadDatabaseRevision IS 'This table contains a list of the database patches that have been successfully applied to this database.'; |
2282 | @@ -1288,11 +1312,14 @@ |
2283 | |
2284 | COMMENT ON TABLE ProjectBounty IS 'This table records a simple link between a bounty and a project. This bounty will be listed on the project web page, and the project will be mentioned on the bounty web page.'; |
2285 | |
2286 | --- Messaging subsytem |
2287 | +-- BugMessages |
2288 | COMMENT ON TABLE BugMessage IS 'This table maps a message to a bug. In other words, it shows that a particular message is associated with a particular bug.'; |
2289 | COMMENT ON COLUMN BugMessage.bugwatch IS 'The external bug this bug comment was imported from.'; |
2290 | COMMENT ON COLUMN BugMessage.remote_comment_id IS 'The id this bug comment has in the external bug tracker, if it is an imported comment. If it is NULL while having a bugwatch set, this comment was added in Launchpad and needs to be pushed to the external bug tracker.'; |
2291 | COMMENT ON COLUMN BugMessage.visible IS 'If false, the bug comment is hidden and should not be shown in any UI.'; |
2292 | +COMMENT ON COLUMN BugMessage.index IS 'The index (used in urls) of the message in a particular bug.'; |
2293 | + |
2294 | +-- Messaging subsytem |
2295 | COMMENT ON TABLE Message IS 'This table stores a single RFC822-style message. Messages can be threaded (using the parent field). These messages can then be referenced from elsewhere in the system, such as the BugMessage table, integrating messageboard facilities with the rest of The Launchpad.'; |
2296 | COMMENT ON COLUMN Message.parent IS 'A "parent message". This allows for some level of threading in Messages.'; |
2297 | COMMENT ON COLUMN Message.subject IS 'The title text of the message, or the subject if it was an email.'; |
2298 | @@ -1932,6 +1959,14 @@ |
2299 | COMMENT ON COLUMN Continent.code IS 'A two-letter code for a continent.'; |
2300 | COMMENT ON COLUMN Continent.name IS 'The name of the continent.'; |
2301 | |
2302 | +-- DistributionJob |
2303 | + |
2304 | +COMMENT ON TABLE DistributionJob IS 'Contains references to jobs to be run on distributions.'; |
2305 | +COMMENT ON COLUMN DistributionJob.distribution IS 'The distribution to be acted on.'; |
2306 | +COMMENT ON COLUMN DistributionJob.distroseries IS 'The distroseries to be acted on.'; |
2307 | +COMMENT ON COLUMN DistributionJob.job_type IS 'The type of job'; |
2308 | +COMMENT ON COLUMN DistributionJob.json_data IS 'A JSON struct containing data for the job.'; |
2309 | + |
2310 | -- DistributionMirror |
2311 | COMMENT ON TABLE DistributionMirror IS 'A mirror of a given distribution.'; |
2312 | COMMENT ON COLUMN DistributionMirror.distribution IS 'The distribution to which the mirror refers to.'; |
2313 | @@ -2303,6 +2338,14 @@ |
2314 | COMMENT ON COLUMN HWDMIValue.value IS 'The value'; |
2315 | COMMENT ON COLUMN HWDMIValue.handle IS 'The handle to which this key/value pair belongs.'; |
2316 | |
2317 | +-- IncrementalDiff |
2318 | +COMMENT ON TABLE IncrementalDiff IS 'Incremental diffs for merge proposals.'; |
2319 | +COMMENT ON COLUMN IncrementalDiff.diff IS 'The contents of the diff.'; |
2320 | +COMMENT ON COLUMN IncrementalDiff.branch_merge_proposal IS 'The merge proposal the diff is for.'; |
2321 | +COMMENT ON COLUMN IncrementalDiff.old_revision IS 'The revision the diff is from.'; |
2322 | +COMMENT ON COLUMN IncrementalDiff.new_revision IS 'The revision the diff is to.'; |
2323 | + |
2324 | + |
2325 | -- Job |
2326 | |
2327 | COMMENT ON TABLE Job IS 'Common info about a job.'; |
2328 | |
2329 | === modified file 'database/schema/launchpad_session.sql' |
2330 | --- database/schema/launchpad_session.sql 2010-09-06 09:48:41 +0000 |
2331 | +++ database/schema/launchpad_session.sql 2010-10-04 22:08:24 +0000 |
2332 | @@ -17,14 +17,13 @@ |
2333 | CREATE TABLE TimeLimitedToken ( |
2334 | path text NOT NULL, |
2335 | token text NOT NULL, |
2336 | - created timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, |
2337 | - constraint timelimitedtoken_pky primary key (path, token) |
2338 | + created timestamp without time zone |
2339 | + NOT NULL DEFAULT (CURRENT_TIMESTAMP AT TIME ZONE 'UTC'), |
2340 | + constraint timelimitedtoken_pkey primary key (path, token) |
2341 | ) WITHOUT OIDS; |
2342 | COMMENT ON TABLE TimeLimitedToken IS 'stores tokens for granting access to a single path in the librarian for a short while. The garbo takes care of cleanups, and we should only have a few thousand at a time. Tokens are handed out just-in-time on the appserver, when a client attempts to dereference a private thing which we do not want to deliver in-line. OAuth tokens cannot be used for the launchpadlibrarian content because they would then be attackable. See lib.canonical.database.librarian for the python class.'; |
2343 | -- Give the garbo an efficient selection to cleanup |
2344 | CREATE INDEX timelimitedtoken_created ON TimeLimitedToken(created); |
2345 | --- Give the librarian an efficient lookup |
2346 | -CREATE INDEX timelimitedtoken_path_token ON TimeLimitedToken(path, token); |
2347 | |
2348 | -- Let the session user access file access tokens. |
2349 | GRANT SELECT, INSERT, UPDATE, DELETE ON TimeLimitedToken TO session; |
2350 | |
2351 | === added file 'database/schema/patch-2208-08-1.sql' |
2352 | --- database/schema/patch-2208-08-1.sql 1970-01-01 00:00:00 +0000 |
2353 | +++ database/schema/patch-2208-08-1.sql 2010-10-04 22:08:24 +0000 |
2354 | @@ -0,0 +1,9 @@ |
2355 | +-- Copyright 2010 Canonical Ltd. This software is licensed under the |
2356 | +-- GNU Affero General Public License version 3 (see the file LICENSE). |
2357 | + |
2358 | +SET client_min_messages=ERROR; |
2359 | + |
2360 | +ALTER TABLE distroarchseries |
2361 | + ADD COLUMN enabled bool NOT NULL DEFAULT TRUE; |
2362 | + |
2363 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 08, 1); |
2364 | |
2365 | === added file 'database/schema/patch-2208-08-2.sql' |
2366 | --- database/schema/patch-2208-08-2.sql 1970-01-01 00:00:00 +0000 |
2367 | +++ database/schema/patch-2208-08-2.sql 2010-10-04 22:08:24 +0000 |
2368 | @@ -0,0 +1,8 @@ |
2369 | +SET client_min_messages=ERROR; |
2370 | + |
2371 | +-- Permit bug searches ordered by 'importance' - the default - to serve from |
2372 | +-- index rather than doing the full search and sorting. |
2373 | + |
2374 | +CREATE INDEX bugtask_importance_idx ON BugTask (importance, id desc nulls first); |
2375 | + |
2376 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 8, 2); |
2377 | |
2378 | === added file 'database/schema/patch-2208-08-3.sql' |
2379 | --- database/schema/patch-2208-08-3.sql 1970-01-01 00:00:00 +0000 |
2380 | +++ database/schema/patch-2208-08-3.sql 2010-10-04 22:08:24 +0000 |
2381 | @@ -0,0 +1,8 @@ |
2382 | +SET client_min_messages=ERROR; |
2383 | + |
2384 | +-- Permit bug searches ordered by 'date_closed desc, id' to serve from |
2385 | +-- index rather than doing the full search and sorting. |
2386 | + |
2387 | +CREATE INDEX bugtask__date_closed__id__idx2 ON BugTask (date_closed, id desc nulls first); |
2388 | + |
2389 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 8, 3); |
2390 | |
2391 | === added file 'database/schema/patch-2208-09-0.sql' |
2392 | --- database/schema/patch-2208-09-0.sql 1970-01-01 00:00:00 +0000 |
2393 | +++ database/schema/patch-2208-09-0.sql 2010-10-04 22:08:24 +0000 |
2394 | @@ -0,0 +1,38 @@ |
2395 | +-- Copyright 2010 Canonical Ltd. This software is licensed under the |
2396 | +-- GNU Affero General Public License version 3 (see the file LICENSE). |
2397 | + |
2398 | +SET client_min_messages=ERROR; |
2399 | + |
2400 | +CREATE TABLE BugTrackerComponentGroup ( |
2401 | + id serial PRIMARY KEY, |
2402 | + name text NOT NULL, |
2403 | + bug_tracker integer NOT NULL REFERENCES BugTracker, |
2404 | + |
2405 | + CONSTRAINT valid_name CHECK (valid_name(name)) |
2406 | +); |
2407 | + |
2408 | +ALTER TABLE BugTrackerComponentGroup |
2409 | + ADD CONSTRAINT bugtrackercomponentgroup__bug_tracker__name__key |
2410 | + UNIQUE (bug_tracker, name); |
2411 | + |
2412 | + |
2413 | +CREATE TABLE BugTrackerComponent ( |
2414 | + id serial PRIMARY KEY, |
2415 | + name text NOT NULL, |
2416 | + is_visible boolean NOT NULL DEFAULT True, |
2417 | + is_custom boolean NOT NULL DEFAULT True, |
2418 | + component_group integer NOT NULL REFERENCES BugTrackerComponentGroup, |
2419 | + distro_source_package integer REFERENCES DistributionSourcePackage, |
2420 | + |
2421 | + CONSTRAINT valid_name CHECK (valid_name(name)) |
2422 | +); |
2423 | + |
2424 | +ALTER TABLE BugTrackerComponent |
2425 | + ADD CONSTRAINT bugtrackercomponent__component_group__name__key |
2426 | + UNIQUE (component_group, name); |
2427 | + |
2428 | +ALTER TABLE BugTrackerComponent |
2429 | + ADD CONSTRAINT bugtrackercomponent__distro_source_package__key |
2430 | + UNIQUE (distro_source_package); |
2431 | + |
2432 | +INSERT INTO LaunchpadDatabaseRevision VALUES(2208, 09, 0); |
2433 | |
2434 | === added file 'database/schema/patch-2208-10-0.sql' |
2435 | --- database/schema/patch-2208-10-0.sql 1970-01-01 00:00:00 +0000 |
2436 | +++ database/schema/patch-2208-10-0.sql 2010-10-04 22:08:24 +0000 |
2437 | @@ -0,0 +1,25 @@ |
2438 | +-- Copyright 2009 Canonical Ltd. This software is licensed under the |
2439 | +-- GNU Affero General Public License version 3 (see the file LICENSE). |
2440 | + |
2441 | +SET client_min_messages=ERROR; |
2442 | + |
2443 | +-- The `InitialiseDistroSeriesJob` table captures the data required for an ifp job. |
2444 | + |
2445 | +CREATE TABLE DistributionJob ( |
2446 | + id serial PRIMARY KEY, |
2447 | + -- FK to the `Job` record with the "generic" data about this archive |
2448 | + -- job. |
2449 | + job integer NOT NULL CONSTRAINT distributionjob__job__fk REFERENCES job, |
2450 | + -- FK to the associated `Distribution` record. |
2451 | + distribution integer NOT NULL REFERENCES Distribution, |
2452 | + distroseries integer REFERENCES DistroSeries, |
2453 | + -- The particular type of foo job |
2454 | + job_type integer NOT NULL, |
2455 | + -- JSON data for use by the job |
2456 | + json_data text |
2457 | +); |
2458 | + |
2459 | +ALTER TABLE DistributionJob ADD CONSTRAINT distributionjob__job__key UNIQUE (job); |
2460 | +CREATE UNIQUE INDEX distribution_job__initialise_series__distroseries ON DistributionJob (distroseries) WHERE job_type = 1; |
2461 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 10, 0); |
2462 | + |
2463 | |
2464 | === added file 'database/schema/patch-2208-11-0.sql' |
2465 | --- database/schema/patch-2208-11-0.sql 1970-01-01 00:00:00 +0000 |
2466 | +++ database/schema/patch-2208-11-0.sql 2010-10-04 22:08:24 +0000 |
2467 | @@ -0,0 +1,30 @@ |
2468 | +-- Copyright 2010 Canonical Ltd. This software is licensed under the |
2469 | +-- GNU Affero General Public License version 3 (see the file LICENSE). |
2470 | + |
2471 | +SET client_min_messages=ERROR; |
2472 | + |
2473 | +-- This constraint is useless given the current PK |
2474 | +ALTER TABLE BranchRevision |
2475 | +DROP CONSTRAINT revisionnumber_branch_id_unique; |
2476 | + |
2477 | +-- This constraint is no longer needed as it will be the new PK |
2478 | +ALTER TABLE BranchRevision |
2479 | +DROP CONSTRAINT revision__branch__revision__key ; |
2480 | + |
2481 | +-- Kill the old PK |
2482 | +ALTER TABLE BranchRevision |
2483 | +DROP CONSTRAINT revisionnumber_pkey ; |
2484 | + |
2485 | +-- Create the new PK |
2486 | +ALTER TABLE BranchRevision |
2487 | +ADD CONSTRAINT revisionnumber_pkey PRIMARY KEY (branch, revision); |
2488 | + |
2489 | +-- What was this used for? Not used now. |
2490 | +DROP VIEW RevisionNumber; |
2491 | + |
2492 | +-- Kill the old id. |
2493 | +ALTER TABLE BranchRevision |
2494 | +DROP COLUMN id; |
2495 | + |
2496 | + |
2497 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 11, 0); |
2498 | |
2499 | === added file 'database/schema/patch-2208-12-0.sql' |
2500 | --- database/schema/patch-2208-12-0.sql 1970-01-01 00:00:00 +0000 |
2501 | +++ database/schema/patch-2208-12-0.sql 2010-10-04 22:08:24 +0000 |
2502 | @@ -0,0 +1,17 @@ |
2503 | +SET client_min_messages=ERROR; |
2504 | + |
2505 | +-- Allow for package diffs against both derived and parent versions. |
2506 | +ALTER TABLE DistroSeriesDifference ADD COLUMN parent_package_diff integer CONSTRAINT distroseriesdifference__parent_package_diff__fk REFERENCES packagediff; |
2507 | +CREATE INDEX distroseriesdifference__parent_package_diff__idx ON distroseriesdifference(parent_package_diff); |
2508 | + |
2509 | +-- Add columns for source_version and parent_source_version |
2510 | +ALTER TABLE DistroSeriesDifference ADD COLUMN source_version text; |
2511 | +ALTER TABLE DistroSeriesDifference ADD CONSTRAINT valid_source_version CHECK(valid_debian_version(source_version)); |
2512 | +ALTER TABLE DistroSeriesDifference ADD COLUMN parent_source_version text; |
2513 | +ALTER TABLE DistroSeriesDifference ADD CONSTRAINT valid_parent_source_version CHECK(valid_debian_version(parent_source_version)); |
2514 | + |
2515 | +-- Add a unique constraint/index for the source_package_name/derived series combo and drop the previous index. |
2516 | +ALTER TABLE DistroSeriesDifference ADD CONSTRAINT distroseriesdifference__derived_series__source_package_name__key UNIQUE (derived_series, source_package_name); |
2517 | +DROP INDEX distroseriesdifference__derived_series__idx; |
2518 | + |
2519 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 12, 0); |
2520 | |
2521 | === added file 'database/schema/patch-2208-13-0.sql' |
2522 | --- database/schema/patch-2208-13-0.sql 1970-01-01 00:00:00 +0000 |
2523 | +++ database/schema/patch-2208-13-0.sql 2010-10-04 22:08:24 +0000 |
2524 | @@ -0,0 +1,17 @@ |
2525 | +-- Copyright 2010 Canonical Ltd. This software is licensed under the |
2526 | +-- GNU Affero General Public License version 3 (see the file LICENSE). |
2527 | + |
2528 | +SET client_min_messages=ERROR; |
2529 | + |
2530 | +CREATE TABLE TranslationTemplatesBuild ( |
2531 | + id SERIAL PRIMARY KEY, |
2532 | + build_farm_job integer NOT NULL REFERENCES BuildFarmJob(id), |
2533 | + branch integer NOT NULL REFERENCES Branch(id)); |
2534 | + |
2535 | +CREATE INDEX translationtemplatesbuild__build_farm_job__idx ON |
2536 | + TranslationTemplatesBuild(build_farm_job); |
2537 | + |
2538 | +CREATE INDEX translationtemplatesbuild__branch__idx ON |
2539 | + TranslationTemplatesBuild(branch); |
2540 | + |
2541 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 13, 0); |
2542 | |
2543 | === added file 'database/schema/patch-2208-14-0.sql' |
2544 | --- database/schema/patch-2208-14-0.sql 1970-01-01 00:00:00 +0000 |
2545 | +++ database/schema/patch-2208-14-0.sql 2010-10-04 22:08:24 +0000 |
2546 | @@ -0,0 +1,9 @@ |
2547 | +SET client_min_messages=ERROR; |
2548 | + |
2549 | +-- Store the row index of bug messages so we don't have to calculate it all the time. |
2550 | +ALTER TABLE BugMessage ADD COLUMN index integer; |
2551 | + |
2552 | +-- BugMessage.indexes must be unique per bug. |
2553 | +ALTER TABLE BugMessage ADD CONSTRAINT bugmessage__bug__index__key UNIQUE (bug, index); |
2554 | + |
2555 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 14, 0); |
2556 | |
2557 | === added file 'database/schema/patch-2208-15-0.sql' |
2558 | --- database/schema/patch-2208-15-0.sql 1970-01-01 00:00:00 +0000 |
2559 | +++ database/schema/patch-2208-15-0.sql 2010-10-04 22:08:24 +0000 |
2560 | @@ -0,0 +1,7 @@ |
2561 | +SET client_min_messages=ERROR; |
2562 | + |
2563 | +-- Delete index obsoleted by bugtask__date_closed__id__idx2 |
2564 | + |
2565 | +DROP INDEX bugtask__date_closed__id__idx; |
2566 | + |
2567 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 15, 0); |
2568 | |
2569 | === added file 'database/schema/patch-2208-16-0.sql' |
2570 | --- database/schema/patch-2208-16-0.sql 1970-01-01 00:00:00 +0000 |
2571 | +++ database/schema/patch-2208-16-0.sql 2010-10-04 22:08:24 +0000 |
2572 | @@ -0,0 +1,8 @@ |
2573 | +-- Copyright 2010 Canonical Ltd. This software is licensed under the |
2574 | +-- GNU Affero General Public License version 3 (see the file LICENSE). |
2575 | +SET client_min_messages=ERROR; |
2576 | + |
2577 | +ALTER TABLE SourcePackageRecipeBuildJob |
2578 | + ALTER COLUMN sourcepackage_recipe_build SET NOT NULL; |
2579 | + |
2580 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 16, 0); |
2581 | |
2582 | === added file 'database/schema/patch-2208-17-0.sql' |
2583 | --- database/schema/patch-2208-17-0.sql 1970-01-01 00:00:00 +0000 |
2584 | +++ database/schema/patch-2208-17-0.sql 2010-10-04 22:08:24 +0000 |
2585 | @@ -0,0 +1,18 @@ |
2586 | +-- Copyright 2010 Canonical Ltd. This software is licensed under the |
2587 | +-- GNU Affero General Public License version 3 (see the file LICENSE). |
2588 | + |
2589 | +SET client_min_messages=ERROR; |
2590 | + |
2591 | +CREATE TABLE IncrementalDiff( |
2592 | + id serial PRIMARY KEY, |
2593 | + diff integer NOT NULL CONSTRAINT diff_fk REFERENCES Diff ON DELETE CASCADE, |
2594 | + branch_merge_proposal integer NOT NULL CONSTRAINT branch_merge_proposal_fk REFERENCES BranchMergeProposal ON DELETE CASCADE, |
2595 | + old_revision integer NOT NULL CONSTRAINT old_revision_fk REFERENCES Revision ON DELETE CASCADE, |
2596 | + new_revision integer NOT NULL CONSTRAINT new_revision_fk REFERENCES Revision ON DELETE CASCADE); |
2597 | + |
2598 | +CREATE INDEX incrementaldiff__diff__idx ON IncrementalDiff(diff); |
2599 | +CREATE INDEX incrementaldiff__branch_merge_proposal__idx ON IncrementalDiff(branch_merge_proposal); |
2600 | +CREATE INDEX incrementaldiff__old_revision__idx ON IncrementalDiff(old_revision); |
2601 | +CREATE INDEX incrementaldiff__new_revision__idx ON IncrementalDiff(new_revision); |
2602 | + |
2603 | +INSERT INTO LaunchpadDatabaseRevision VALUES (2208, 17, 0); |
2604 | |
2605 | === modified file 'database/schema/security.cfg' |
2606 | --- database/schema/security.cfg 2010-09-21 23:09:59 +0000 |
2607 | +++ database/schema/security.cfg 2010-10-04 22:08:24 +0000 |
2608 | @@ -121,6 +121,8 @@ |
2609 | public.bugnotificationrecipientarchive = SELECT, UPDATE |
2610 | public.bugtag = SELECT, INSERT, DELETE |
2611 | public.bugtrackerperson = SELECT, UPDATE |
2612 | +public.bugtrackercomponent = SELECT, INSERT, UPDATE |
2613 | +public.bugtrackercomponentgroup = SELECT, INSERT, UPDATE |
2614 | public.bugwatchactivity = SELECT, INSERT, UPDATE |
2615 | public.codeimport = SELECT, INSERT, UPDATE, DELETE |
2616 | public.codeimportevent = SELECT, INSERT, UPDATE |
2617 | @@ -138,6 +140,7 @@ |
2618 | public.databasereplicationlag = SELECT |
2619 | public.diff = SELECT, INSERT, UPDATE |
2620 | public.distributionbounty = SELECT, INSERT, UPDATE |
2621 | +public.distributionjob = SELECT, INSERT |
2622 | public.distributionmirror = SELECT, INSERT, UPDATE, DELETE |
2623 | public.distributionsourcepackage = SELECT, INSERT, UPDATE, DELETE |
2624 | public.distributionsourcepackagecache = SELECT |
2625 | @@ -169,6 +172,7 @@ |
2626 | public.hwtest = SELECT |
2627 | public.hwvendorid = SELECT |
2628 | public.hwvendorname = SELECT |
2629 | +public.incrementaldiff = SELECT, INSERT, UPDATE, DELETE |
2630 | public.job = SELECT, INSERT, UPDATE, DELETE |
2631 | public.karmacache = SELECT |
2632 | public.karmacategory = SELECT |
2633 | @@ -237,7 +241,6 @@ |
2634 | public.revision = SELECT, INSERT, UPDATE |
2635 | public.revisionauthor = SELECT, INSERT, UPDATE |
2636 | public.revisioncache = SELECT, INSERT, UPDATE, DELETE |
2637 | -public.revisionnumber = SELECT, INSERT |
2638 | public.revisionparent = SELECT, INSERT |
2639 | public.scriptactivity = SELECT |
2640 | public.shipitreport = SELECT, INSERT |
2641 | @@ -276,6 +279,7 @@ |
2642 | public.translationgroup = SELECT, INSERT, UPDATE |
2643 | public.translationimportqueueentry = SELECT, INSERT, UPDATE, DELETE |
2644 | public.translationmessage = SELECT, INSERT, UPDATE |
2645 | +public.translationtemplatesbuild = SELECT, INSERT, UPDATE, DELETE |
2646 | public.translator = SELECT, INSERT, UPDATE, DELETE |
2647 | public.usertouseremail = SELECT, UPDATE |
2648 | public.validpersoncache = SELECT |
2649 | @@ -538,8 +542,14 @@ |
2650 | public.bugnotification = SELECT, INSERT |
2651 | public.bugnotificationrecipient = SELECT, INSERT |
2652 | public.bugsubscription = SELECT |
2653 | +public.bugsubscriptionfilter = SELECT |
2654 | +public.bugsubscriptionfilterstatus = SELECT |
2655 | +public.bugsubscriptionfilterimportance = SELECT |
2656 | +public.bugsubscriptionfiltertag = SELECT |
2657 | public.bugtask = SELECT, INSERT, UPDATE |
2658 | public.bugtracker = SELECT, INSERT |
2659 | +public.bugtrackercomponent = SELECT, INSERT, UPDATE, DELETE |
2660 | +public.bugtrackercomponentgroup = SELECT, INSERT, UPDATE, DELETE |
2661 | public.bugtrackeralias = SELECT |
2662 | public.bugtrackerperson = SELECT, INSERT |
2663 | public.bugwatch = SELECT, INSERT, UPDATE |
2664 | @@ -595,7 +605,9 @@ |
2665 | public.distribution = SELECT |
2666 | public.distributionsourcepackage = SELECT, UPDATE |
2667 | public.emailaddress = SELECT |
2668 | +public.incrementaldiff = SELECT |
2669 | public.job = SELECT, INSERT, UPDATE, DELETE |
2670 | +public.translationtemplatesbuild = SELECT, INSERT |
2671 | # Karma |
2672 | public.karma = SELECT, INSERT |
2673 | public.karmaaction = SELECT |
2674 | @@ -617,6 +629,10 @@ |
2675 | public.bugactivity = SELECT, INSERT |
2676 | public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE |
2677 | public.bugsubscription = SELECT |
2678 | +public.bugsubscriptionfilter = SELECT |
2679 | +public.bugsubscriptionfilterstatus = SELECT |
2680 | +public.bugsubscriptionfilterimportance = SELECT |
2681 | +public.bugsubscriptionfiltertag = SELECT |
2682 | public.bugnotification = SELECT, INSERT |
2683 | public.bugnotificationrecipient = SELECT, INSERT |
2684 | public.structuralsubscription = SELECT |
2685 | @@ -805,6 +821,10 @@ |
2686 | public.bugactivity = SELECT, INSERT |
2687 | public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE |
2688 | public.bugsubscription = SELECT |
2689 | +public.bugsubscriptionfilter = SELECT |
2690 | +public.bugsubscriptionfilterstatus = SELECT |
2691 | +public.bugsubscriptionfilterimportance = SELECT |
2692 | +public.bugsubscriptionfiltertag = SELECT |
2693 | public.bugnotification = SELECT, INSERT |
2694 | public.bugnotificationrecipient = SELECT, INSERT |
2695 | public.bugnomination = SELECT |
2696 | @@ -889,6 +909,7 @@ |
2697 | public.flatpackagesetinclusion = SELECT |
2698 | public.teamparticipation = SELECT |
2699 | public.translationimportqueueentry = SELECT, INSERT, UPDATE |
2700 | +public.translationtemplatesbuild = SELECT, INSERT |
2701 | |
2702 | [ppa-apache-log-parser] |
2703 | type=user |
2704 | @@ -929,6 +950,10 @@ |
2705 | public.bugpackageinfestation = SELECT, INSERT, UPDATE |
2706 | public.bugproductinfestation = SELECT, INSERT, UPDATE |
2707 | public.bugsubscription = SELECT, INSERT, UPDATE, DELETE |
2708 | +public.bugsubscriptionfilter = SELECT, INSERT, UPDATE, DELETE |
2709 | +public.bugsubscriptionfilterstatus = SELECT, INSERT, UPDATE, DELETE |
2710 | +public.bugsubscriptionfilterimportance = SELECT, INSERT, UPDATE, DELETE |
2711 | +public.bugsubscriptionfiltertag = SELECT, INSERT, UPDATE, DELETE |
2712 | public.bugtask = SELECT, INSERT, UPDATE, DELETE |
2713 | public.bugtracker = SELECT, INSERT, UPDATE, DELETE |
2714 | public.bugtrackeralias = SELECT, INSERT, UPDATE, DELETE |
2715 | @@ -1157,6 +1182,10 @@ |
2716 | public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE |
2717 | public.bugjob = SELECT, INSERT |
2718 | public.bugsubscription = SELECT |
2719 | +public.bugsubscriptionfilter = SELECT |
2720 | +public.bugsubscriptionfilterstatus = SELECT |
2721 | +public.bugsubscriptionfilterimportance = SELECT |
2722 | +public.bugsubscriptionfiltertag = SELECT |
2723 | public.bugnotification = SELECT, INSERT |
2724 | public.bugnotificationrecipient = SELECT, INSERT |
2725 | public.bugnomination = SELECT |
2726 | @@ -1259,6 +1288,10 @@ |
2727 | public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE |
2728 | public.bugjob = SELECT, INSERT |
2729 | public.bugsubscription = SELECT |
2730 | +public.bugsubscriptionfilter = SELECT |
2731 | +public.bugsubscriptionfilterstatus = SELECT |
2732 | +public.bugsubscriptionfilterimportance = SELECT |
2733 | +public.bugsubscriptionfiltertag = SELECT |
2734 | public.bugnotification = SELECT, INSERT |
2735 | public.bugnotificationrecipient = SELECT, INSERT |
2736 | public.bugnomination = SELECT |
2737 | @@ -1326,6 +1359,10 @@ |
2738 | public.bugnotification = SELECT, INSERT, UPDATE |
2739 | public.bugnotificationrecipient = SELECT, INSERT, UPDATE |
2740 | public.bugsubscription = SELECT, INSERT |
2741 | +public.bugsubscriptionfilter = SELECT, INSERT |
2742 | +public.bugsubscriptionfilterstatus = SELECT, INSERT |
2743 | +public.bugsubscriptionfilterimportance = SELECT, INSERT |
2744 | +public.bugsubscriptionfiltertag = SELECT, INSERT |
2745 | public.bugnomination = SELECT |
2746 | public.bug = SELECT, INSERT, UPDATE |
2747 | public.bugactivity = SELECT, INSERT |
2748 | @@ -1440,6 +1477,7 @@ |
2749 | [translationsbranchscanner] |
2750 | type=user |
2751 | groups=branchscanner,translations_approval |
2752 | +public.translationtemplatesbuild = SELECT, INSERT |
2753 | |
2754 | [translationstobranch] |
2755 | type=user |
2756 | @@ -1545,6 +1583,10 @@ |
2757 | public.bugaffectsperson = SELECT, INSERT, UPDATE, DELETE |
2758 | public.bugjob = SELECT, INSERT |
2759 | public.bugsubscription = SELECT, INSERT |
2760 | +public.bugsubscriptionfilter = SELECT, INSERT |
2761 | +public.bugsubscriptionfilterstatus = SELECT, INSERT |
2762 | +public.bugsubscriptionfilterimportance = SELECT, INSERT |
2763 | +public.bugsubscriptionfiltertag = SELECT, INSERT |
2764 | public.bugnotification = SELECT, INSERT |
2765 | public.bugnotificationattachment = SELECT |
2766 | public.bugnotificationrecipient = SELECT, INSERT |
2767 | @@ -1553,6 +1595,10 @@ |
2768 | public.bugtask = SELECT, INSERT, UPDATE |
2769 | public.bugmessage = SELECT, INSERT |
2770 | public.bugsubscription = SELECT, INSERT, UPDATE, DELETE |
2771 | +public.bugsubscriptionfilter = SELECT, INSERT, UPDATE, DELETE |
2772 | +public.bugsubscriptionfilterstatus = SELECT, INSERT, UPDATE, DELETE |
2773 | +public.bugsubscriptionfilterimportance = SELECT, INSERT, UPDATE, DELETE |
2774 | +public.bugsubscriptionfiltertag = SELECT, INSERT, UPDATE, DELETE |
2775 | public.bugtracker = SELECT, INSERT |
2776 | public.bugtrackeralias = SELECT, INSERT |
2777 | public.bugwatch = SELECT, INSERT |
2778 | @@ -1719,6 +1765,7 @@ |
2779 | public.distribution = SELECT |
2780 | public.distroseries = SELECT |
2781 | public.emailaddress = SELECT |
2782 | +public.incrementaldiff = SELECT, INSERT |
2783 | public.job = SELECT, INSERT, UPDATE |
2784 | public.karmaaction = SELECT |
2785 | public.karma = SELECT, INSERT |
2786 | @@ -1731,6 +1778,7 @@ |
2787 | public.previewdiff = SELECT, INSERT |
2788 | public.product = SELECT |
2789 | public.productseries = SELECT |
2790 | +public.revision = SELECT |
2791 | public.seriessourcepackagebranch = SELECT |
2792 | public.sourcepackagename = SELECT |
2793 | public.staticdiff = SELECT, INSERT |
2794 | @@ -1812,6 +1860,10 @@ |
2795 | public.message = SELECT, INSERT |
2796 | public.messagechunk = SELECT, INSERT |
2797 | public.bugsubscription = SELECT, INSERT |
2798 | +public.bugsubscriptionfilter = SELECT, INSERT |
2799 | +public.bugsubscriptionfilterstatus = SELECT, INSERT |
2800 | +public.bugsubscriptionfilterimportance = SELECT, INSERT |
2801 | +public.bugsubscriptionfiltertag = SELECT, INSERT |
2802 | public.bugmessage = SELECT, INSERT |
2803 | public.sourcepackagename = SELECT |
2804 | public.job = SELECT, INSERT, UPDATE |
2805 | @@ -1839,6 +1891,10 @@ |
2806 | public.bug = SELECT, UPDATE |
2807 | public.bugattachment = SELECT, DELETE |
2808 | public.bugsubscription = SELECT |
2809 | +public.bugsubscriptionfilter = SELECT |
2810 | +public.bugsubscriptionfilterstatus = SELECT |
2811 | +public.bugsubscriptionfilterimportance = SELECT |
2812 | +public.bugsubscriptionfiltertag = SELECT |
2813 | public.bugaffectsperson = SELECT |
2814 | public.bugnotification = SELECT, DELETE |
2815 | public.bugnotificationrecipientarchive = SELECT |
2816 | |
2817 | === modified file 'lib/canonical/config/schema-lazr.conf' |
2818 | --- lib/canonical/config/schema-lazr.conf 2010-09-24 14:24:06 +0000 |
2819 | +++ lib/canonical/config/schema-lazr.conf 2010-10-04 22:08:24 +0000 |
2820 | @@ -301,6 +301,18 @@ |
2821 | # datatype: string |
2822 | logfile: - |
2823 | |
2824 | +# The location of the log file used by the LaunchpadForkingService |
2825 | +# datatype: string |
2826 | +forker_logfile: - |
2827 | + |
2828 | +# Should we be using the forking daemon? Or should we be calling spawnProcess |
2829 | +# instead? |
2830 | +# datatype: boolean |
2831 | +use_forking_daemon: False |
2832 | +# What disk path will the daemon listen on |
2833 | +# datatype: string |
2834 | +forking_daemon_socket: /var/tmp/launchpad_forking_service.sock |
2835 | + |
2836 | # The prefix of the web URL for all public branches. This should end with a |
2837 | # slash. |
2838 | # |
2839 | @@ -644,6 +656,11 @@ |
2840 | # datatype: integer |
2841 | storm_cache_size: 500 |
2842 | |
2843 | +# Where database/replication/slon_ctl.py dumps its logs. Used for the |
2844 | +# staging replication environment. |
2845 | +# datatype: existing_directory |
2846 | +replication_logdir: database/replication |
2847 | + |
2848 | |
2849 | [diff] |
2850 | # The maximum size in bytes to read from the librarian to make available in |
2851 | |
2852 | === modified file 'lib/canonical/launchpad/icing/style-3-0.css.in' |
2853 | --- lib/canonical/launchpad/icing/style-3-0.css.in 2010-09-10 17:32:29 +0000 |
2854 | +++ lib/canonical/launchpad/icing/style-3-0.css.in 2010-10-04 22:08:24 +0000 |
2855 | @@ -2419,7 +2419,7 @@ |
2856 | background-repeat: no-repeat; |
2857 | background-position:right center; |
2858 | } |
2859 | -table#packages_list tr.superseded { |
2860 | +table#packages_list tr.superseded, tr.blacklisted { |
2861 | background-color: #eee; |
2862 | } |
2863 | ul.latest-ppa-updates li:nth-child(odd) { |
2864 | |
2865 | === modified file 'lib/canonical/launchpad/interfaces/__init__.py' |
2866 | --- lib/canonical/launchpad/interfaces/__init__.py 2010-09-30 17:08:50 +0000 |
2867 | +++ lib/canonical/launchpad/interfaces/__init__.py 2010-10-04 22:08:24 +0000 |
2868 | @@ -55,6 +55,8 @@ |
2869 | from lp.registry.interfaces.distribution import * |
2870 | from lp.registry.interfaces.distributionmirror import * |
2871 | from lp.registry.interfaces.distributionsourcepackage import * |
2872 | +from lp.registry.interfaces.distroseriesdifference import * |
2873 | +from lp.registry.interfaces.distroseriesdifferencecomment import * |
2874 | from lp.soyuz.interfaces.distributionsourcepackagecache import * |
2875 | from lp.soyuz.interfaces.distributionsourcepackagerelease import * |
2876 | from lp.registry.interfaces.series import * |
2877 | |
2878 | === modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py' |
2879 | --- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-08-27 11:19:54 +0000 |
2880 | +++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-10-04 22:08:24 +0000 |
2881 | @@ -77,6 +77,9 @@ |
2882 | IDistributionSourcePackage, |
2883 | ) |
2884 | from lp.registry.interfaces.distroseries import IDistroSeries |
2885 | +from lp.registry.interfaces.distroseriesdifferencecomment import ( |
2886 | + IDistroSeriesDifferenceComment, |
2887 | + ) |
2888 | from lp.registry.interfaces.person import ( |
2889 | IPerson, |
2890 | IPersonPublic, |
2891 | @@ -89,6 +92,7 @@ |
2892 | IStructuralSubscription, |
2893 | IStructuralSubscriptionTarget, |
2894 | ) |
2895 | +from lp.services.comments.interfaces.conversation import IComment |
2896 | from lp.soyuz.enums import ( |
2897 | PackagePublishingStatus, |
2898 | PackageUploadCustomFormat, |
2899 | @@ -321,6 +325,9 @@ |
2900 | IBuildFarmJob['status'].vocabulary = BuildStatus |
2901 | IBuildFarmJob['buildqueue_record'].schema = IBuildQueue |
2902 | |
2903 | +# IComment |
2904 | +IComment['comment_author'].schema = IPerson |
2905 | + |
2906 | # IDistribution |
2907 | IDistribution['series'].value_type.schema = IDistroSeries |
2908 | patch_reference_property( |
2909 | @@ -366,6 +373,9 @@ |
2910 | IDistroSeries, 'getPackageUploads', IPackageUpload) |
2911 | patch_reference_property(IDistroSeries, 'parent_series', IDistroSeries) |
2912 | |
2913 | +# IDistroSeriesDifferenceComment |
2914 | +IDistroSeriesDifferenceComment['comment_author'].schema = IPerson |
2915 | + |
2916 | # IDistroArchSeries |
2917 | patch_reference_property(IDistroArchSeries, 'main_archive', IArchive) |
2918 | |
2919 | |
2920 | === modified file 'lib/canonical/launchpad/scripts/runlaunchpad.py' |
2921 | --- lib/canonical/launchpad/scripts/runlaunchpad.py 2010-09-17 20:46:58 +0000 |
2922 | +++ lib/canonical/launchpad/scripts/runlaunchpad.py 2010-10-04 22:08:24 +0000 |
2923 | @@ -184,6 +184,53 @@ |
2924 | stop_at_exit(process) |
2925 | |
2926 | |
2927 | +class ForkingSessionService(Service): |
2928 | + """A lp-forking-service for handling ssh access.""" |
2929 | + |
2930 | + # TODO: The SFTP (and bzr+ssh) server depends fairly heavily on this |
2931 | + # service. It would seem reasonable to make one always start if the |
2932 | + # other one is started. Though this might be a way to "FeatureFlag" |
2933 | + # whether this is active or not. |
2934 | + |
2935 | + @property |
2936 | + def should_launch(self): |
2937 | + return (config.codehosting.launch and |
2938 | + config.codehosting.use_forking_daemon) |
2939 | + |
2940 | + @property |
2941 | + def logfile(self): |
2942 | + """Return the log file to use. |
2943 | + |
2944 | + Default to the value of the configuration key logfile. |
2945 | + """ |
2946 | + return config.codehosting.forker_logfile |
2947 | + |
2948 | + def launch(self): |
2949 | + # Following the logic in TacFile. Specifically, if you configure sftp |
2950 | + # to not run (and thus bzr+ssh) then we don't want to run the forking |
2951 | + # service. |
2952 | + if not self.should_launch: |
2953 | + return |
2954 | + from lp.codehosting import get_bzr_path |
2955 | + command = [config.root + '/bin/py', get_bzr_path(), |
2956 | + 'launchpad-forking-service', |
2957 | + '--path', config.codehosting.forking_daemon_socket, |
2958 | + ] |
2959 | + env = dict(os.environ) |
2960 | + env['BZR_PLUGIN_PATH'] = config.root + '/bzrplugins' |
2961 | + logfile = self.logfile |
2962 | + if logfile == '-': |
2963 | + # This process uses a different logging infrastructure from the |
2964 | + # rest of the Launchpad code. As such, it cannot trivially use '-' |
2965 | + # as the logfile. So we just ignore this setting. |
2966 | + pass |
2967 | + else: |
2968 | + env['BZR_LOG'] = logfile |
2969 | + process = subprocess.Popen(command, env=env, stdin=subprocess.PIPE) |
2970 | + process.stdin.close() |
2971 | + stop_at_exit(process) |
2972 | + |
2973 | + |
2974 | def stop_at_exit(process): |
2975 | """Create and register an atexit hook for killing a process. |
2976 | |
2977 | @@ -208,6 +255,9 @@ |
2978 | 'librarian': TacFile('librarian', 'daemons/librarian.tac', |
2979 | 'librarian_server', prepare_for_librarian), |
2980 | 'sftp': TacFile('sftp', 'daemons/sftp.tac', 'codehosting'), |
2981 | + # TODO, we probably need to run the forking service whenever somebody |
2982 | + # requests the sftp service... |
2983 | + 'forker': ForkingSessionService(), |
2984 | 'mailman': MailmanService(), |
2985 | 'codebrowse': CodebrowseService(), |
2986 | 'google-webservice': GoogleWebService(), |
2987 | |
2988 | === modified file 'lib/canonical/launchpad/webapp/interfaces.py' |
2989 | --- lib/canonical/launchpad/webapp/interfaces.py 2010-09-12 11:43:36 +0000 |
2990 | +++ lib/canonical/launchpad/webapp/interfaces.py 2010-10-04 22:08:24 +0000 |
2991 | @@ -335,6 +335,10 @@ |
2992 | query_string_params = Attribute( |
2993 | 'A dictionary of the query string parameters.') |
2994 | |
2995 | + is_ajax = Bool( |
2996 | + title=_('Is ajax'), required=False, readonly=True, |
2997 | + description=_("Indicates whether the request is an XMLHttpRequest.")) |
2998 | + |
2999 | def getRootURL(rootsite): |
3000 | """Return this request's root URL. |
3001 | |
3002 | |
3003 | === modified file 'lib/canonical/launchpad/webapp/servers.py' |
3004 | --- lib/canonical/launchpad/webapp/servers.py 2010-09-22 15:17:39 +0000 |
3005 | +++ lib/canonical/launchpad/webapp/servers.py 2010-10-04 22:08:24 +0000 |
3006 | @@ -526,7 +526,27 @@ |
3007 | return decoded_qs |
3008 | |
3009 | |
3010 | -class BasicLaunchpadRequest: |
3011 | +class LaunchpadBrowserRequestMixin: |
3012 | + """Provides methods used for both API and web browser requests.""" |
3013 | + |
3014 | + def getRootURL(self, rootsite): |
3015 | + """See IBasicLaunchpadRequest.""" |
3016 | + if rootsite is not None: |
3017 | + assert rootsite in allvhosts.configs, ( |
3018 | + "rootsite is %s. Must be in %r." % ( |
3019 | + rootsite, sorted(allvhosts.configs.keys()))) |
3020 | + root_url = allvhosts.configs[rootsite].rooturl |
3021 | + else: |
3022 | + root_url = self.getApplicationURL() + '/' |
3023 | + return root_url |
3024 | + |
3025 | + @property |
3026 | + def is_ajax(self): |
3027 | + """See `IBasicLaunchpadRequest`.""" |
3028 | + return 'XMLHttpRequest' == self.getHeader('HTTP_X_REQUESTED_WITH') |
3029 | + |
3030 | + |
3031 | +class BasicLaunchpadRequest(LaunchpadBrowserRequestMixin): |
3032 | """Mixin request class to provide stepstogo.""" |
3033 | |
3034 | implements(IBasicLaunchpadRequest) |
3035 | @@ -581,24 +601,8 @@ |
3036 | return get_query_string_params(self) |
3037 | |
3038 | |
3039 | -class LaunchpadBrowserRequestMixin: |
3040 | - """A mixin for classes that share some method implementations.""" |
3041 | - |
3042 | - def getRootURL(self, rootsite): |
3043 | - """See IBasicLaunchpadRequest.""" |
3044 | - if rootsite is not None: |
3045 | - assert rootsite in allvhosts.configs, ( |
3046 | - "rootsite is %s. Must be in %r." % ( |
3047 | - rootsite, sorted(allvhosts.configs.keys()))) |
3048 | - root_url = allvhosts.configs[rootsite].rooturl |
3049 | - else: |
3050 | - root_url = self.getApplicationURL() + '/' |
3051 | - return root_url |
3052 | - |
3053 | - |
3054 | class LaunchpadBrowserRequest(BasicLaunchpadRequest, BrowserRequest, |
3055 | - NotificationRequest, ErrorReportRequest, |
3056 | - LaunchpadBrowserRequestMixin): |
3057 | + NotificationRequest, ErrorReportRequest): |
3058 | """Integration of launchpad mixin request classes to make an uber |
3059 | launchpad request class. |
3060 | """ |
3061 | @@ -1370,7 +1374,7 @@ |
3062 | |
3063 | |
3064 | class PublicXMLRPCRequest(BasicLaunchpadRequest, XMLRPCRequest, |
3065 | - ErrorReportRequest, LaunchpadBrowserRequestMixin): |
3066 | + ErrorReportRequest): |
3067 | """Request type for doing public XML-RPC in Launchpad.""" |
3068 | |
3069 | def _createResponse(self): |
3070 | |
3071 | === modified file 'lib/canonical/launchpad/webapp/tests/test_servers.py' |
3072 | --- lib/canonical/launchpad/webapp/tests/test_servers.py 2010-08-20 20:31:18 +0000 |
3073 | +++ lib/canonical/launchpad/webapp/tests/test_servers.py 2010-10-04 22:08:24 +0000 |
3074 | @@ -358,6 +358,20 @@ |
3075 | retried_request.response.getHeader('Vary'), |
3076 | 'Cookie, Authorization') |
3077 | |
3078 | + def test_is_ajax_false(self): |
3079 | + """Normal requests do not define HTTP_X_REQUESTED_WITH.""" |
3080 | + request = LaunchpadBrowserRequest(StringIO.StringIO(''), {}) |
3081 | + |
3082 | + self.assertFalse(request.is_ajax) |
3083 | + |
3084 | + def test_is_ajax_true(self): |
3085 | + """Requests with HTTP_X_REQUESTED_WITH set are ajax requests.""" |
3086 | + request = LaunchpadBrowserRequest(StringIO.StringIO(''), { |
3087 | + 'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest', |
3088 | + }) |
3089 | + |
3090 | + self.assertTrue(request.is_ajax) |
3091 | + |
3092 | |
3093 | class IThingSet(Interface): |
3094 | """Marker interface for a set of things.""" |
3095 | |
3096 | === modified file 'lib/canonical/launchpad/zcml/librarian.zcml' |
3097 | --- lib/canonical/launchpad/zcml/librarian.zcml 2010-09-30 02:52:07 +0000 |
3098 | +++ lib/canonical/launchpad/zcml/librarian.zcml 2010-10-04 22:08:24 +0000 |
3099 | @@ -16,7 +16,7 @@ |
3100 | <allow interface="canonical.launchpad.interfaces.librarian.ILibraryFileAliasWithParent" /> |
3101 | <require |
3102 | permission="launchpad.Edit" |
3103 | - set_attributes="restricted" /> |
3104 | + set_attributes="mimetype restricted" /> |
3105 | </class> |
3106 | |
3107 | <class class="canonical.launchpad.database.librarian.LibraryFileContent"> |
3108 | |
3109 | === modified file 'lib/lp/app/templates/base-layout-macros.pt' |
3110 | --- lib/lp/app/templates/base-layout-macros.pt 2010-09-29 03:26:01 +0000 |
3111 | +++ lib/lp/app/templates/base-layout-macros.pt 2010-10-04 22:08:24 +0000 |
3112 | @@ -181,6 +181,8 @@ |
3113 | <script type="text/javascript" |
3114 | tal:attributes="src string:${lp_js}/bugs/bugtracker_overlay.js"></script> |
3115 | <script type="text/javascript" |
3116 | + tal:attributes="src string:${lp_js}/registry/distroseriesdifferences_details.js"></script> |
3117 | + <script type="text/javascript" |
3118 | tal:attributes="src string:${lp_js}/registry/milestoneoverlay.js"></script> |
3119 | <script type="text/javascript" |
3120 | tal:attributes="src string:${lp_js}/registry/milestonetable.js"></script> |
3121 | |
3122 | === modified file 'lib/lp/bugs/browser/bugattachment.py' |
3123 | --- lib/lp/bugs/browser/bugattachment.py 2010-09-06 07:44:21 +0000 |
3124 | +++ lib/lp/bugs/browser/bugattachment.py 2010-10-04 22:08:24 +0000 |
3125 | @@ -12,19 +12,21 @@ |
3126 | 'BugAttachmentURL', |
3127 | ] |
3128 | |
3129 | -from cStringIO import StringIO |
3130 | - |
3131 | -from zope.component import getUtility |
3132 | +from zope.component import ( |
3133 | + getMultiAdapter, |
3134 | + getUtility, |
3135 | + ) |
3136 | from zope.contenttype import guess_content_type |
3137 | from zope.interface import implements |
3138 | |
3139 | from canonical.launchpad.browser.librarian import ( |
3140 | FileNavigationMixin, |
3141 | ProxiedLibraryFileAlias, |
3142 | - StreamOrRedirectLibraryFileAliasView, |
3143 | SafeStreamOrRedirectLibraryFileAliasView, |
3144 | ) |
3145 | -from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet |
3146 | +from canonical.launchpad.interfaces.librarian import ( |
3147 | + ILibraryFileAliasWithParent, |
3148 | + ) |
3149 | from canonical.launchpad.webapp import ( |
3150 | canonical_url, |
3151 | custom_widget, |
3152 | @@ -163,7 +165,10 @@ |
3153 | self.context.title = data['title'] |
3154 | |
3155 | if self.context.libraryfile.mimetype != data['contenttype']: |
3156 | - self.updateContentType(data['contenttype']) |
3157 | + lfa_with_parent = getMultiAdapter( |
3158 | + (self.context.libraryfile, self.context), |
3159 | + ILibraryFileAliasWithParent) |
3160 | + lfa_with_parent.mimetype = data['contenttype'] |
3161 | |
3162 | @action('Delete Attachment', name='delete') |
3163 | def delete_action(self, action, data): |
3164 | @@ -174,20 +179,6 @@ |
3165 | url=libraryfile_url, name=self.context.title)) |
3166 | self.context.removeFromBug(user=self.user) |
3167 | |
3168 | - def updateContentType(self, new_content_type): |
3169 | - """Update the attachment content type.""" |
3170 | - filealiasset = getUtility(ILibraryFileAliasSet) |
3171 | - old_filealias = self.context.libraryfile |
3172 | - # Download the file and upload it again with the new content |
3173 | - # type. |
3174 | - # XXX: Bjorn Tillenius 2005-06-30: |
3175 | - # It should be possible to simply create a new filealias |
3176 | - # with the same content as the old one. |
3177 | - old_content = old_filealias.read() |
3178 | - self.context.libraryfile = filealiasset.create( |
3179 | - name=old_filealias.filename, size=len(old_content), |
3180 | - file=StringIO(old_content), contentType=new_content_type) |
3181 | - |
3182 | @property |
3183 | def label(self): |
3184 | return smartquote('Bug #%d - Edit attachment "%s"') % ( |
3185 | |
3186 | === added file 'lib/lp/bugs/browser/tests/test_bugattachment_edit_view.py' |
3187 | --- lib/lp/bugs/browser/tests/test_bugattachment_edit_view.py 1970-01-01 00:00:00 +0000 |
3188 | +++ lib/lp/bugs/browser/tests/test_bugattachment_edit_view.py 2010-10-04 22:08:24 +0000 |
3189 | @@ -0,0 +1,107 @@ |
3190 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
3191 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
3192 | + |
3193 | +__metaclass__ = type |
3194 | + |
3195 | +import transaction |
3196 | +from zope.security.interfaces import Unauthorized |
3197 | + |
3198 | +from canonical.testing import LaunchpadFunctionalLayer |
3199 | +from lp.testing import ( |
3200 | + login_person, |
3201 | + TestCaseWithFactory, |
3202 | + ) |
3203 | +from lp.testing.views import create_initialized_view |
3204 | + |
3205 | + |
3206 | +class TestBugAttachmentEditView(TestCaseWithFactory): |
3207 | + """Tests of traversal to and access of files of bug attachments.""" |
3208 | + |
3209 | + layer = LaunchpadFunctionalLayer |
3210 | + |
3211 | + CHANGE_FORM_DATA = { |
3212 | + 'field.title': 'new description', |
3213 | + 'field.patch': 'on', |
3214 | + 'field.contenttype': 'application/whatever', |
3215 | + 'field.actions.change': 'Change', |
3216 | + } |
3217 | + |
3218 | + def setUp(self): |
3219 | + super(TestBugAttachmentEditView, self).setUp() |
3220 | + self.bug_owner = self.factory.makePerson() |
3221 | + login_person(self.bug_owner) |
3222 | + self.bug = self.factory.makeBug(owner=self.bug_owner) |
3223 | + self.bugattachment = self.factory.makeBugAttachment( |
3224 | + bug=self.bug, filename='foo.diff', data='file content', |
3225 | + description='attachment description', content_type='text/plain', |
3226 | + is_patch=False) |
3227 | + # The Librarian server should know about the new file before |
3228 | + # we start the tests. |
3229 | + transaction.commit() |
3230 | + |
3231 | + def test_change_action_public_bug(self): |
3232 | + # Properties of attachments for public bugs can be |
3233 | + # changed by every user. |
3234 | + user = self.factory.makePerson() |
3235 | + login_person(user) |
3236 | + create_initialized_view( |
3237 | + self.bugattachment, name='+edit', form=self.CHANGE_FORM_DATA) |
3238 | + self.assertEqual('new description', self.bugattachment.title) |
3239 | + self.assertTrue(self.bugattachment.is_patch) |
3240 | + self.assertEqual( |
3241 | + 'application/whatever', self.bugattachment.libraryfile.mimetype) |
3242 | + |
3243 | + def test_change_action_private_bug(self): |
3244 | + # Subscribers of a private bug can edit attachments. |
3245 | + user = self.factory.makePerson() |
3246 | + self.bug.subscribe(user, self.bug_owner) |
3247 | + self.bug.setPrivate(True, self.bug_owner) |
3248 | + transaction.commit() |
3249 | + login_person(user) |
3250 | + create_initialized_view( |
3251 | + self.bugattachment, name='+edit', form=self.CHANGE_FORM_DATA) |
3252 | + self.assertEqual('new description', self.bugattachment.title) |
3253 | + self.assertTrue(self.bugattachment.is_patch) |
3254 | + self.assertEqual( |
3255 | + 'application/whatever', self.bugattachment.libraryfile.mimetype) |
3256 | + |
3257 | + def test_change_action_private_bug_unauthorized(self): |
3258 | + # Other users cannot edit attachments of private bugs. |
3259 | + user = self.factory.makePerson() |
3260 | + self.bug.setPrivate(True, self.bug_owner) |
3261 | + transaction.commit() |
3262 | + login_person(user) |
3263 | + self.assertRaises( |
3264 | + Unauthorized, create_initialized_view, self.bugattachment, |
3265 | + name='+edit', form=self.CHANGE_FORM_DATA) |
3266 | + |
3267 | + DELETE_FORM_DATA = { |
3268 | + 'field.actions.delete': 'Delete Attachment', |
3269 | + } |
3270 | + |
3271 | + def test_delete_action_public_bug(self): |
3272 | + # Bug attachments can be removed from a bug. |
3273 | + user = self.factory.makePerson() |
3274 | + login_person(user) |
3275 | + create_initialized_view( |
3276 | + self.bugattachment, name='+edit', form=self.DELETE_FORM_DATA) |
3277 | + self.assertEqual(0, self.bug.attachments.count()) |
3278 | + |
3279 | + def test_delete_action_private_bug(self): |
3280 | + # Subscribers of a private bug can delete attachments. |
3281 | + user = self.factory.makePerson() |
3282 | + self.bug.subscribe(user, self.bug_owner) |
3283 | + self.bug.setPrivate(True, self.bug_owner) |
3284 | + login_person(user) |
3285 | + create_initialized_view( |
3286 | + self.bugattachment, name='+edit', form=self.DELETE_FORM_DATA) |
3287 | + self.assertEqual(0, self.bug.attachments.count()) |
3288 | + |
3289 | + def test_delete_action_private_bug_unautorized(self): |
3290 | + # Other users cannot delete private bug attachments. |
3291 | + user = self.factory.makePerson() |
3292 | + self.bug.setPrivate(True, self.bug_owner) |
3293 | + login_person(user) |
3294 | + self.assertRaises( |
3295 | + Unauthorized, create_initialized_view, self.bugattachment, |
3296 | + name='+edit', form=self.DELETE_FORM_DATA) |
3297 | |
3298 | === modified file 'lib/lp/bugs/configure.zcml' |
3299 | --- lib/lp/bugs/configure.zcml 2010-09-28 14:59:25 +0000 |
3300 | +++ lib/lp/bugs/configure.zcml 2010-10-04 22:08:24 +0000 |
3301 | @@ -368,10 +368,14 @@ |
3302 | aliases |
3303 | baseurl |
3304 | bugtrackertype |
3305 | + componentForDistroSourcePackage |
3306 | + component_groups |
3307 | contactdetails |
3308 | + getAllRemoteComponentGroups |
3309 | getBugFilingAndSearchLinks |
3310 | getBugsWatching |
3311 | getLinkedPersonByName |
3312 | + getRemoteComponentGroup |
3313 | has_lp_plugin |
3314 | id |
3315 | imported_bug_messages |
3316 | @@ -394,6 +398,7 @@ |
3317 | destroySelf |
3318 | ensurePersonForSelf |
3319 | linkPersonToSelf |
3320 | + addRemoteComponentGroup |
3321 | " |
3322 | set_attributes=" |
3323 | aliases |
3324 | @@ -461,6 +466,47 @@ |
3325 | interface="lp.bugs.interfaces.bugtracker.IBugTrackerAliasSet"/> |
3326 | </securedutility> |
3327 | |
3328 | + <!--BugTrackerComponent --> |
3329 | + |
3330 | + <class |
3331 | + class="lp.bugs.model.bugtracker.BugTrackerComponent"> |
3332 | + <require |
3333 | + permission="zope.Public" |
3334 | + attributes=" |
3335 | + id |
3336 | + name |
3337 | + is_visible |
3338 | + is_custom |
3339 | + "/> |
3340 | + <require |
3341 | + permission="launchpad.AnyPerson" |
3342 | + set_attributes=" |
3343 | + is_visible |
3344 | + is_custom |
3345 | + "/> |
3346 | + <implements |
3347 | + interface="lp.bugs.interfaces.bugtracker.IBugTrackerComponent"/> |
3348 | + </class> |
3349 | + |
3350 | + <!--BugTrackerComponentGroup --> |
3351 | + |
3352 | + <class |
3353 | + class="lp.bugs.model.bugtracker.BugTrackerComponentGroup"> |
3354 | + <require |
3355 | + permission="zope.Public" |
3356 | + attributes=" |
3357 | + id |
3358 | + name |
3359 | + bug_tracker |
3360 | + components |
3361 | + getComponent |
3362 | + addComponent |
3363 | + addCustomComponent |
3364 | + "/> |
3365 | + <implements |
3366 | + interface="lp.bugs.interfaces.bugtracker.IBugTrackerComponentGroup"/> |
3367 | + </class> |
3368 | + |
3369 | <!-- RemoteBug --> |
3370 | |
3371 | <class |
3372 | |
3373 | === modified file 'lib/lp/bugs/doc/initial-bug-contacts.txt' |
3374 | --- lib/lp/bugs/doc/initial-bug-contacts.txt 2010-08-20 01:29:08 +0000 |
3375 | +++ lib/lp/bugs/doc/initial-bug-contacts.txt 2010-10-04 22:08:24 +0000 |
3376 | @@ -16,7 +16,7 @@ |
3377 | >>> debian = getUtility(IDistributionSet).getByName("debian") |
3378 | >>> debian_firefox = debian.getSourcePackage("mozilla-firefox") |
3379 | |
3380 | - >>> debian_firefox.bug_subscriptions |
3381 | + >>> list(debian_firefox.bug_subscriptions) |
3382 | [] |
3383 | |
3384 | Adding a package subscription is done with the |
3385 | |
3386 | === modified file 'lib/lp/bugs/interfaces/bugtracker.py' |
3387 | --- lib/lp/bugs/interfaces/bugtracker.py 2010-09-19 23:52:49 +0000 |
3388 | +++ lib/lp/bugs/interfaces/bugtracker.py 2010-10-04 22:08:24 +0000 |
3389 | @@ -12,6 +12,8 @@ |
3390 | 'IBugTracker', |
3391 | 'IBugTrackerAlias', |
3392 | 'IBugTrackerAliasSet', |
3393 | + 'IBugTrackerComponent', |
3394 | + 'IBugTrackerComponentGroup', |
3395 | 'IBugTrackerSet', |
3396 | 'IRemoteBug', |
3397 | 'SINGLE_PRODUCT_BUGTRACKERTYPES', |
3398 | @@ -29,6 +31,7 @@ |
3399 | export_as_webservice_entry, |
3400 | export_factory_operation, |
3401 | export_read_operation, |
3402 | + export_write_operation, |
3403 | exported, |
3404 | operation_parameters, |
3405 | operation_returns_entry, |
3406 | @@ -353,6 +356,26 @@ |
3407 | point between now and 24 hours hence. |
3408 | """ |
3409 | |
3410 | + @operation_parameters( |
3411 | + component_group_name=TextLine( |
3412 | + title=u"The name of the remote component group", required=True)) |
3413 | + @export_write_operation() |
3414 | + def addRemoteComponentGroup(component_group_name): |
3415 | + """Adds a new component group to the bug tracker""" |
3416 | + |
3417 | + def getAllRemoteComponentGroups(): |
3418 | + """Return collection of all component groups for this bug tracker""" |
3419 | + |
3420 | + @operation_parameters( |
3421 | + component_group_name=TextLine( |
3422 | + title=u"The name of the remote component group", required=True)) |
3423 | + @export_read_operation() |
3424 | + def getRemoteComponentGroup(component_group_name): |
3425 | + """Retrieve a given component group registered with the bug tracker. |
3426 | + |
3427 | + :param component_group_name: Name of the component group to retrieve. |
3428 | + """ |
3429 | + |
3430 | |
3431 | class IBugTrackerSet(Interface): |
3432 | """A set of IBugTracker's. |
3433 | @@ -465,6 +488,72 @@ |
3434 | """Query IBugTrackerAliases by BugTracker.""" |
3435 | |
3436 | |
3437 | +class IBugTrackerComponent(Interface): |
3438 | + """The software component in the remote bug tracker. |
3439 | + |
3440 | + Most bug trackers organize bug reports by the software 'component' |
3441 | + they affect. This class provides a mapping of this upstream component |
3442 | + to the corresponding source package in the distro. |
3443 | + """ |
3444 | + export_as_webservice_entry() |
3445 | + |
3446 | + id = Int(title=_('ID'), required=True, readonly=True) |
3447 | + is_visible = Bool( |
3448 | + title=_('Is Visible?'), |
3449 | + description=_("Should the component be shown in " |
3450 | + "the Launchpad web interface?"), |
3451 | + readonly=True) |
3452 | + is_custom = Bool( |
3453 | + title=_('Is Custom?'), |
3454 | + description=_("Was the component added locally in " |
3455 | + "Launchpad? If it was, we must retain " |
3456 | + "it across updates of bugtracker data."), |
3457 | + readonly=True) |
3458 | + |
3459 | + name = exported( |
3460 | + Text( |
3461 | + title=_('Name'), |
3462 | + constraint=name_validator, |
3463 | + description=_('The name of a software component' |
3464 | + 'in a remote bug tracker'))) |
3465 | + |
3466 | +# XXX: Bug 644794 will implement this link |
3467 | +# distro_source_package = exported( |
3468 | +# Reference( |
3469 | +# title=_('Distribution Source Package'), |
3470 | +# schema=Interface, |
3471 | +# description=_('The distribution source package for this ' |
3472 | +# 'component, if one has been defined.'))) |
3473 | + |
3474 | + |
3475 | +class IBugTrackerComponentGroup(Interface): |
3476 | + """A collection of components in a remote bug tracker. |
3477 | + |
3478 | + Some bug trackers organize sets of components into higher level groups, |
3479 | + such as Bugzilla's 'product'. |
3480 | + """ |
3481 | + export_as_webservice_entry() |
3482 | + |
3483 | + id = Int(title=_('ID')) |
3484 | + name = exported( |
3485 | + Text( |
3486 | + title=_('Name'), |
3487 | + constraint=name_validator, |
3488 | + description=_('The name of the bug tracker product.'))) |
3489 | + components = exported( |
3490 | + Reference(title=_('Components'), schema=IBugTrackerComponent)) |
3491 | + bug_tracker = exported( |
3492 | + Reference(title=_('BugTracker'), schema=IBugTracker)) |
3493 | + |
3494 | + @operation_parameters( |
3495 | + component_name=TextLine( |
3496 | + title=u"The name of the remote software component to be added", |
3497 | + required=True)) |
3498 | + @export_write_operation() |
3499 | + def addComponent(component_name): |
3500 | + """Adds a component to be tracked as part of this component group""" |
3501 | + |
3502 | + |
3503 | class IRemoteBug(Interface): |
3504 | """A remote bug for a given bug tracker.""" |
3505 | |
3506 | |
3507 | === modified file 'lib/lp/bugs/model/bugmessage.py' |
3508 | --- lib/lp/bugs/model/bugmessage.py 2010-08-20 20:31:18 +0000 |
3509 | +++ lib/lp/bugs/model/bugmessage.py 2010-10-04 22:08:24 +0000 |
3510 | @@ -44,6 +44,8 @@ |
3511 | notNull=False, default=None) |
3512 | remote_comment_id = StringCol(notNull=False, default=None) |
3513 | visible = BoolCol(notNull=True, default=True) |
3514 | + # -- Uncomment when deployed. |
3515 | + # index = IntCol() |
3516 | |
3517 | |
3518 | class BugMessageSet: |
3519 | |
3520 | === added file 'lib/lp/bugs/model/bugsubscriptionfilter.py' |
3521 | --- lib/lp/bugs/model/bugsubscriptionfilter.py 1970-01-01 00:00:00 +0000 |
3522 | +++ lib/lp/bugs/model/bugsubscriptionfilter.py 2010-10-04 22:08:24 +0000 |
3523 | @@ -0,0 +1,36 @@ |
3524 | +# Copyright 2009 Canonical Ltd. This software is licensed under the |
3525 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
3526 | + |
3527 | +# pylint: disable-msg=E0611,W0212 |
3528 | + |
3529 | +__metaclass__ = type |
3530 | +__all__ = ['BugSubscriptionFilter'] |
3531 | + |
3532 | +from storm.base import Storm |
3533 | +from storm.locals import ( |
3534 | + Bool, |
3535 | + Int, |
3536 | + Reference, |
3537 | + Unicode, |
3538 | + ) |
3539 | + |
3540 | + |
3541 | +class BugSubscriptionFilter(Storm): |
3542 | + """A filter to specialize a *structural* subscription.""" |
3543 | + |
3544 | + __storm_table__ = "BugSubscriptionFilter" |
3545 | + |
3546 | + id = Int(primary=True) |
3547 | + |
3548 | + structural_subscription_id = Int( |
3549 | + "structuralsubscription", allow_none=False) |
3550 | + structural_subscription = Reference( |
3551 | + structural_subscription_id, "StructuralSubscription.id") |
3552 | + |
3553 | + find_all_tags = Bool(allow_none=False, default=False) |
3554 | + include_any_tags = Bool(allow_none=False, default=False) |
3555 | + exclude_any_tags = Bool(allow_none=False, default=False) |
3556 | + |
3557 | + other_parameters = Unicode() |
3558 | + |
3559 | + description = Unicode() |
3560 | |
3561 | === added file 'lib/lp/bugs/model/bugsubscriptionfilterimportance.py' |
3562 | --- lib/lp/bugs/model/bugsubscriptionfilterimportance.py 1970-01-01 00:00:00 +0000 |
3563 | +++ lib/lp/bugs/model/bugsubscriptionfilterimportance.py 2010-10-04 22:08:24 +0000 |
3564 | @@ -0,0 +1,29 @@ |
3565 | +# Copyright 2009 Canonical Ltd. This software is licensed under the |
3566 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
3567 | + |
3568 | +# pylint: disable-msg=E0611,W0212 |
3569 | + |
3570 | +__metaclass__ = type |
3571 | +__all__ = ['BugSubscriptionFilterImportance'] |
3572 | + |
3573 | +from storm.base import Storm |
3574 | +from storm.locals import ( |
3575 | + Int, |
3576 | + Reference, |
3577 | + ) |
3578 | + |
3579 | +from canonical.database.enumcol import DBEnum |
3580 | +from lp.bugs.interfaces.bugtask import BugTaskImportance |
3581 | + |
3582 | + |
3583 | +class BugSubscriptionFilterImportance(Storm): |
3584 | + """Importances to filter.""" |
3585 | + |
3586 | + __storm_table__ = "BugSubscriptionFilterImportance" |
3587 | + |
3588 | + id = Int(primary=True) |
3589 | + |
3590 | + filter_id = Int("filter", allow_none=False) |
3591 | + filter = Reference(filter_id, "BugSubscriptionFilter.id") |
3592 | + |
3593 | + importance = DBEnum(enum=BugTaskImportance, allow_none=False) |
3594 | |
3595 | === added file 'lib/lp/bugs/model/bugsubscriptionfilterstatus.py' |
3596 | --- lib/lp/bugs/model/bugsubscriptionfilterstatus.py 1970-01-01 00:00:00 +0000 |
3597 | +++ lib/lp/bugs/model/bugsubscriptionfilterstatus.py 2010-10-04 22:08:24 +0000 |
3598 | @@ -0,0 +1,29 @@ |
3599 | +# Copyright 2009 Canonical Ltd. This software is licensed under the |
3600 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
3601 | + |
3602 | +# pylint: disable-msg=E0611,W0212 |
3603 | + |
3604 | +__metaclass__ = type |
3605 | +__all__ = ['BugSubscriptionFilterStatus'] |
3606 | + |
3607 | +from storm.base import Storm |
3608 | +from storm.locals import ( |
3609 | + Int, |
3610 | + Reference, |
3611 | + ) |
3612 | + |
3613 | +from canonical.database.enumcol import DBEnum |
3614 | +from lp.bugs.interfaces.bugtask import BugTaskStatus |
3615 | + |
3616 | + |
3617 | +class BugSubscriptionFilterStatus(Storm): |
3618 | + """Statuses to filter.""" |
3619 | + |
3620 | + __storm_table__ = "BugSubscriptionFilterStatus" |
3621 | + |
3622 | + id = Int(primary=True) |
3623 | + |
3624 | + filter_id = Int("filter", allow_none=False) |
3625 | + filter = Reference(filter_id, "BugSubscriptionFilter.id") |
3626 | + |
3627 | + status = DBEnum(enum=BugTaskStatus, allow_none=False) |
3628 | |
3629 | === added file 'lib/lp/bugs/model/bugsubscriptionfiltertag.py' |
3630 | --- lib/lp/bugs/model/bugsubscriptionfiltertag.py 1970-01-01 00:00:00 +0000 |
3631 | +++ lib/lp/bugs/model/bugsubscriptionfiltertag.py 2010-10-04 22:08:24 +0000 |
3632 | @@ -0,0 +1,29 @@ |
3633 | +# Copyright 2009 Canonical Ltd. This software is licensed under the |
3634 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
3635 | + |
3636 | +# pylint: disable-msg=E0611,W0212 |
3637 | + |
3638 | +__metaclass__ = type |
3639 | +__all__ = ['BugSubscriptionFilterTag'] |
3640 | + |
3641 | +from storm.base import Storm |
3642 | +from storm.locals import ( |
3643 | + Bool, |
3644 | + Int, |
3645 | + Reference, |
3646 | + Unicode, |
3647 | + ) |
3648 | + |
3649 | + |
3650 | +class BugSubscriptionFilterTag(Storm): |
3651 | + """Tags to filter.""" |
3652 | + |
3653 | + __storm_table__ = "BugSubscriptionFilterTag" |
3654 | + |
3655 | + id = Int(primary=True) |
3656 | + |
3657 | + filter_id = Int("filter", allow_none=False) |
3658 | + filter = Reference(filter_id, "BugSubscriptionFilter.id") |
3659 | + |
3660 | + include = Bool(allow_none=False) |
3661 | + tag = Unicode(allow_none=False) |
3662 | |
3663 | === modified file 'lib/lp/bugs/model/bugtracker.py' |
3664 | --- lib/lp/bugs/model/bugtracker.py 2010-09-19 00:35:22 +0000 |
3665 | +++ lib/lp/bugs/model/bugtracker.py 2010-10-04 22:08:24 +0000 |
3666 | @@ -6,12 +6,14 @@ |
3667 | __metaclass__ = type |
3668 | __all__ = [ |
3669 | 'BugTracker', |
3670 | + 'BugTrackerSet', |
3671 | 'BugTrackerAlias', |
3672 | 'BugTrackerAliasSet', |
3673 | + 'BugTrackerComponent', |
3674 | + 'BugTrackerComponentGroup', |
3675 | 'BugTrackerSet', |
3676 | ] |
3677 | |
3678 | - |
3679 | from datetime import datetime |
3680 | from itertools import chain |
3681 | # splittype is not formally documented, but is in urllib.__all__, is |
3682 | @@ -22,9 +24,15 @@ |
3683 | splittype, |
3684 | ) |
3685 | |
3686 | +from storm.base import Storm |
3687 | +from storm.locals import ( |
3688 | + Int, |
3689 | + Reference, |
3690 | + ReferenceSet, |
3691 | + Unicode, |
3692 | + ) |
3693 | from zope.component import getUtility |
3694 | from zope.interface import implements |
3695 | -from zope.security.interfaces import Unauthorized |
3696 | |
3697 | from lazr.uri import URI |
3698 | from pytz import timezone |
3699 | @@ -45,8 +53,6 @@ |
3700 | ) |
3701 | from storm.locals import Bool |
3702 | from storm.store import Store |
3703 | -from zope.component import getUtility |
3704 | -from zope.interface import implements |
3705 | |
3706 | from canonical.database.enumcol import EnumCol |
3707 | from canonical.database.sqlbase import ( |
3708 | @@ -64,6 +70,8 @@ |
3709 | IBugTracker, |
3710 | IBugTrackerAlias, |
3711 | IBugTrackerAliasSet, |
3712 | + IBugTrackerComponent, |
3713 | + IBugTrackerComponentGroup, |
3714 | IBugTrackerSet, |
3715 | SINGLE_PRODUCT_BUGTRACKERTYPES, |
3716 | ) |
3717 | @@ -518,6 +526,41 @@ |
3718 | next_check=new_next_check, lastchecked=None, |
3719 | last_error_type=None) |
3720 | |
3721 | + def addRemoteComponentGroup(self, component_group_name): |
3722 | + """See `IBugTracker`.""" |
3723 | + |
3724 | + if component_group_name is None: |
3725 | + component_group_name = "default" |
3726 | + component_group = BugTrackerComponentGroup() |
3727 | + component_group.name = component_group_name |
3728 | + component_group.bug_tracker = self |
3729 | + |
3730 | + store = IStore(BugTrackerComponentGroup) |
3731 | + store.add(component_group) |
3732 | + store.commit() |
3733 | + |
3734 | + return component_group |
3735 | + |
3736 | + def getAllRemoteComponentGroups(self): |
3737 | + """See `IBugTracker`.""" |
3738 | + component_groups = [] |
3739 | + |
3740 | + component_groups = Store.of(self).find( |
3741 | + BugTrackerComponentGroup, |
3742 | + BugTrackerComponentGroup.bug_tracker == self.id) |
3743 | + component_groups = component_groups.order_by( |
3744 | + BugTrackerComponentGroup.name) |
3745 | + return component_groups |
3746 | + |
3747 | + def getRemoteComponentGroup(self, component_group_name): |
3748 | + """See `IBugTracker`.""" |
3749 | + component_group = None |
3750 | + store = IStore(BugTrackerComponentGroup) |
3751 | + component_group = store.find( |
3752 | + BugTrackerComponentGroup, |
3753 | + name = component_group_name).one() |
3754 | + return component_group |
3755 | + |
3756 | |
3757 | class BugTrackerSet: |
3758 | """Implements IBugTrackerSet for a container or set of BugTrackers, |
3759 | @@ -627,9 +670,11 @@ |
3760 | |
3761 | def getMostActiveBugTrackers(self, limit=None): |
3762 | """See `IBugTrackerSet`.""" |
3763 | - store = IStore(self.table) |
3764 | - result = store.find(self.table, self.table.id == BugWatch.bugtrackerID) |
3765 | - result = result.group_by(self.table) |
3766 | + store = IStore(BugTracker) |
3767 | + result = store.find( |
3768 | + BugTracker, |
3769 | + BugTracker.id == BugWatch.bugtrackerID) |
3770 | + result = result.group_by(BugTracker) |
3771 | result = result.order_by(Desc(Count(BugWatch))) |
3772 | if limit is not None: |
3773 | return result[:limit] |
3774 | @@ -671,3 +716,91 @@ |
3775 | def queryByBugTracker(self, bugtracker): |
3776 | """See IBugTrackerSet.""" |
3777 | return self.table.selectBy(bugtracker=bugtracker.id) |
3778 | + |
3779 | + |
3780 | +class BugTrackerComponent(Storm): |
3781 | + """The software component in the remote bug tracker. |
3782 | + |
3783 | + Most bug trackers organize bug reports by the software 'component' |
3784 | + they affect. This class provides a mapping of this upstream component |
3785 | + to the corresponding source package in the distro. |
3786 | + """ |
3787 | + implements(IBugTrackerComponent) |
3788 | + __storm_table__ = 'BugTrackerComponent' |
3789 | + |
3790 | + id = Int(primary=True) |
3791 | + name = Unicode(allow_none=False) |
3792 | + |
3793 | + component_group_id = Int('component_group') |
3794 | + component_group = Reference( |
3795 | + component_group_id, |
3796 | + 'BugTrackerComponentGroup.id') |
3797 | + |
3798 | + is_visible = Bool(allow_none=False) |
3799 | + is_custom = Bool(allow_none=False) |
3800 | + |
3801 | + distro_source_package_id = Int('distro_source_package') |
3802 | + distro_source_package = Reference( |
3803 | + distro_source_package_id, |
3804 | + 'DistributionSourcePackageInDatabase.id') |
3805 | + |
3806 | + |
3807 | +class BugTrackerComponentGroup(Storm): |
3808 | + """A collection of components in a remote bug tracker. |
3809 | + |
3810 | + Some bug trackers organize sets of components into higher level groups, |
3811 | + such as Bugzilla's 'product'. |
3812 | + """ |
3813 | + implements(IBugTrackerComponentGroup) |
3814 | + __storm_table__ = 'BugTrackerComponentGroup' |
3815 | + |
3816 | + id = Int(primary=True) |
3817 | + name = Unicode(allow_none=False) |
3818 | + bug_tracker_id = Int('bug_tracker') |
3819 | + bug_tracker = Reference(bug_tracker_id, 'BugTracker.id') |
3820 | + components = ReferenceSet( |
3821 | + id, |
3822 | + BugTrackerComponent.component_group_id, |
3823 | + order_by=BugTrackerComponent.name) |
3824 | + |
3825 | + def addComponent(self, component_name): |
3826 | + """Adds a component that is synced from a remote bug tracker""" |
3827 | + |
3828 | + component = BugTrackerComponent() |
3829 | + component.name = component_name |
3830 | + component.component_group = self |
3831 | + |
3832 | + store = IStore(BugTrackerComponent) |
3833 | + store.add(component) |
3834 | + store.flush() |
3835 | + |
3836 | + return component |
3837 | + |
3838 | + def getComponent(self, component_name): |
3839 | + """Retrieves a component by the given name. |
3840 | + |
3841 | + None is returned if there is no component by that name in the |
3842 | + group. |
3843 | + """ |
3844 | + |
3845 | + if component_name is None: |
3846 | + return None |
3847 | + else: |
3848 | + return Store.of(self).find( |
3849 | + BugTrackerComponent, |
3850 | + (BugTrackerComponent.name == component_name)).one() |
3851 | + |
3852 | + def addCustomComponent(self, component_name): |
3853 | + """Adds a component locally that isn't synced from a remote tracker |
3854 | + """ |
3855 | + |
3856 | + component = BugTrackerComponent() |
3857 | + component.name = component_name |
3858 | + component.component_group = self |
3859 | + component.is_custom = True |
3860 | + |
3861 | + store = IStore(BugTrackerComponent) |
3862 | + store.add(component) |
3863 | + store.flush() |
3864 | + |
3865 | + return component |
3866 | |
3867 | === added directory 'lib/lp/bugs/model/tests' |
3868 | === added file 'lib/lp/bugs/model/tests/__init__.py' |
3869 | === added file 'lib/lp/bugs/model/tests/test_bugsubscriptionfilter.py' |
3870 | --- lib/lp/bugs/model/tests/test_bugsubscriptionfilter.py 1970-01-01 00:00:00 +0000 |
3871 | +++ lib/lp/bugs/model/tests/test_bugsubscriptionfilter.py 2010-10-04 22:08:24 +0000 |
3872 | @@ -0,0 +1,66 @@ |
3873 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
3874 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
3875 | + |
3876 | +"""Tests for the bugsubscription module.""" |
3877 | + |
3878 | +__metaclass__ = type |
3879 | + |
3880 | +from canonical.launchpad.interfaces.lpstorm import IStore |
3881 | +from canonical.testing import DatabaseFunctionalLayer |
3882 | +from lp.bugs.model.bugsubscriptionfilter import BugSubscriptionFilter |
3883 | +from lp.testing import ( |
3884 | + login_person, |
3885 | + TestCaseWithFactory, |
3886 | + ) |
3887 | + |
3888 | + |
3889 | +class TestBugSubscriptionFilter(TestCaseWithFactory): |
3890 | + |
3891 | + layer = DatabaseFunctionalLayer |
3892 | + |
3893 | + def setUp(self): |
3894 | + super(TestBugSubscriptionFilter, self).setUp() |
3895 | + self.target = self.factory.makeProduct() |
3896 | + self.subscriber = self.target.owner |
3897 | + login_person(self.subscriber) |
3898 | + self.subscription = self.target.addBugSubscription( |
3899 | + self.subscriber, self.subscriber) |
3900 | + |
3901 | + def test_basics(self): |
3902 | + """Test the basic operation of `BugSubscriptionFilter` objects.""" |
3903 | + # Create. |
3904 | + bug_subscription_filter = BugSubscriptionFilter() |
3905 | + bug_subscription_filter.structural_subscription = self.subscription |
3906 | + bug_subscription_filter.find_all_tags = True |
3907 | + bug_subscription_filter.include_any_tags = True |
3908 | + bug_subscription_filter.exclude_any_tags = True |
3909 | + bug_subscription_filter.other_parameters = u"foo" |
3910 | + bug_subscription_filter.description = u"bar" |
3911 | + # Flush and reload. |
3912 | + IStore(bug_subscription_filter).flush() |
3913 | + IStore(bug_subscription_filter).reload(bug_subscription_filter) |
3914 | + # Check. |
3915 | + self.assertIsNot(None, bug_subscription_filter.id) |
3916 | + self.assertEqual( |
3917 | + self.subscription.id, |
3918 | + bug_subscription_filter.structural_subscription_id) |
3919 | + self.assertEqual( |
3920 | + self.subscription, |
3921 | + bug_subscription_filter.structural_subscription) |
3922 | + self.assertIs(True, bug_subscription_filter.find_all_tags) |
3923 | + self.assertIs(True, bug_subscription_filter.include_any_tags) |
3924 | + self.assertIs(True, bug_subscription_filter.exclude_any_tags) |
3925 | + self.assertEqual(u"foo", bug_subscription_filter.other_parameters) |
3926 | + self.assertEqual(u"bar", bug_subscription_filter.description) |
3927 | + |
3928 | + def test_defaults(self): |
3929 | + """Test the default values of `BugSubscriptionFilter` objects.""" |
3930 | + # Create. |
3931 | + bug_subscription_filter = BugSubscriptionFilter() |
3932 | + bug_subscription_filter.structural_subscription = self.subscription |
3933 | + # Check. |
3934 | + self.assertIs(False, bug_subscription_filter.find_all_tags) |
3935 | + self.assertIs(False, bug_subscription_filter.include_any_tags) |
3936 | + self.assertIs(False, bug_subscription_filter.exclude_any_tags) |
3937 | + self.assertIs(None, bug_subscription_filter.other_parameters) |
3938 | + self.assertIs(None, bug_subscription_filter.description) |
3939 | |
3940 | === added file 'lib/lp/bugs/model/tests/test_bugsubscriptionfilterimportance.py' |
3941 | --- lib/lp/bugs/model/tests/test_bugsubscriptionfilterimportance.py 1970-01-01 00:00:00 +0000 |
3942 | +++ lib/lp/bugs/model/tests/test_bugsubscriptionfilterimportance.py 2010-10-04 22:08:24 +0000 |
3943 | @@ -0,0 +1,54 @@ |
3944 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
3945 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
3946 | + |
3947 | +"""Tests for the bugsubscription module.""" |
3948 | + |
3949 | +__metaclass__ = type |
3950 | + |
3951 | +from canonical.launchpad.interfaces.lpstorm import IStore |
3952 | +from canonical.testing import DatabaseFunctionalLayer |
3953 | +from lp.bugs.interfaces.bugtask import BugTaskImportance |
3954 | +from lp.bugs.model.bugsubscriptionfilter import BugSubscriptionFilter |
3955 | +from lp.bugs.model.bugsubscriptionfilterimportance import ( |
3956 | + BugSubscriptionFilterImportance, |
3957 | + ) |
3958 | +from lp.testing import ( |
3959 | + login_person, |
3960 | + TestCaseWithFactory, |
3961 | + ) |
3962 | + |
3963 | + |
3964 | +class TestBugSubscriptionFilterImportance(TestCaseWithFactory): |
3965 | + |
3966 | + layer = DatabaseFunctionalLayer |
3967 | + |
3968 | + def setUp(self): |
3969 | + super(TestBugSubscriptionFilterImportance, self).setUp() |
3970 | + self.target = self.factory.makeProduct() |
3971 | + self.subscriber = self.target.owner |
3972 | + login_person(self.subscriber) |
3973 | + self.subscription = self.target.addBugSubscription( |
3974 | + self.subscriber, self.subscriber) |
3975 | + self.subscription_filter = BugSubscriptionFilter() |
3976 | + self.subscription_filter.structural_subscription = self.subscription |
3977 | + |
3978 | + def test_basics(self): |
3979 | + """Test the basics of `BugSubscriptionFilterImportance` objects.""" |
3980 | + # Create. |
3981 | + bug_sub_filter_importance = BugSubscriptionFilterImportance() |
3982 | + bug_sub_filter_importance.filter = self.subscription_filter |
3983 | + bug_sub_filter_importance.importance = BugTaskImportance.HIGH |
3984 | + # Flush and reload. |
3985 | + IStore(bug_sub_filter_importance).flush() |
3986 | + IStore(bug_sub_filter_importance).reload(bug_sub_filter_importance) |
3987 | + # Check. |
3988 | + self.assertIsNot(None, bug_sub_filter_importance.id) |
3989 | + self.assertEqual( |
3990 | + self.subscription_filter.id, |
3991 | + bug_sub_filter_importance.filter_id) |
3992 | + self.assertEqual( |
3993 | + self.subscription_filter, |
3994 | + bug_sub_filter_importance.filter) |
3995 | + self.assertEqual( |
3996 | + BugTaskImportance.HIGH, |
3997 | + bug_sub_filter_importance.importance) |
3998 | |
3999 | === added file 'lib/lp/bugs/model/tests/test_bugsubscriptionfilterstatus.py' |
4000 | --- lib/lp/bugs/model/tests/test_bugsubscriptionfilterstatus.py 1970-01-01 00:00:00 +0000 |
4001 | +++ lib/lp/bugs/model/tests/test_bugsubscriptionfilterstatus.py 2010-10-04 22:08:24 +0000 |
4002 | @@ -0,0 +1,52 @@ |
4003 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
4004 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
4005 | + |
4006 | +"""Tests for the bugsubscription module.""" |
4007 | + |
4008 | +__metaclass__ = type |
4009 | + |
4010 | +from canonical.launchpad.interfaces.lpstorm import IStore |
4011 | +from canonical.testing import DatabaseFunctionalLayer |
4012 | +from lp.bugs.interfaces.bugtask import BugTaskStatus |
4013 | +from lp.bugs.model.bugsubscriptionfilter import BugSubscriptionFilter |
4014 | +from lp.bugs.model.bugsubscriptionfilterstatus import ( |
4015 | + BugSubscriptionFilterStatus, |
4016 | + ) |
4017 | +from lp.testing import ( |
4018 | + login_person, |
4019 | + TestCaseWithFactory, |
4020 | + ) |
4021 | + |
4022 | + |
4023 | +class TestBugSubscriptionFilterStatus(TestCaseWithFactory): |
4024 | + |
4025 | + layer = DatabaseFunctionalLayer |
4026 | + |
4027 | + def setUp(self): |
4028 | + super(TestBugSubscriptionFilterStatus, self).setUp() |
4029 | + self.target = self.factory.makeProduct() |
4030 | + self.subscriber = self.target.owner |
4031 | + login_person(self.subscriber) |
4032 | + self.subscription = self.target.addBugSubscription( |
4033 | + self.subscriber, self.subscriber) |
4034 | + self.subscription_filter = BugSubscriptionFilter() |
4035 | + self.subscription_filter.structural_subscription = self.subscription |
4036 | + |
4037 | + def test_basics(self): |
4038 | + """Test the basics of `BugSubscriptionFilterStatus` objects.""" |
4039 | + # Create. |
4040 | + bug_sub_filter_status = BugSubscriptionFilterStatus() |
4041 | + bug_sub_filter_status.filter = self.subscription_filter |
4042 | + bug_sub_filter_status.status = BugTaskStatus.NEW |
4043 | + # Flush and reload. |
4044 | + IStore(bug_sub_filter_status).flush() |
4045 | + IStore(bug_sub_filter_status).reload(bug_sub_filter_status) |
4046 | + # Check. |
4047 | + self.assertIsNot(None, bug_sub_filter_status.id) |
4048 | + self.assertEqual( |
4049 | + self.subscription_filter.id, |
4050 | + bug_sub_filter_status.filter_id) |
4051 | + self.assertEqual( |
4052 | + self.subscription_filter, |
4053 | + bug_sub_filter_status.filter) |
4054 | + self.assertEqual(BugTaskStatus.NEW, bug_sub_filter_status.status) |
4055 | |
4056 | === added file 'lib/lp/bugs/model/tests/test_bugsubscriptionfiltertag.py' |
4057 | --- lib/lp/bugs/model/tests/test_bugsubscriptionfiltertag.py 1970-01-01 00:00:00 +0000 |
4058 | +++ lib/lp/bugs/model/tests/test_bugsubscriptionfiltertag.py 2010-10-04 22:08:24 +0000 |
4059 | @@ -0,0 +1,51 @@ |
4060 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
4061 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
4062 | + |
4063 | +"""Tests for the bugsubscription module.""" |
4064 | + |
4065 | +__metaclass__ = type |
4066 | + |
4067 | +from canonical.launchpad.interfaces.lpstorm import IStore |
4068 | +from canonical.testing import DatabaseFunctionalLayer |
4069 | +from lp.bugs.model.bugsubscriptionfilter import BugSubscriptionFilter |
4070 | +from lp.bugs.model.bugsubscriptionfiltertag import BugSubscriptionFilterTag |
4071 | +from lp.testing import ( |
4072 | + login_person, |
4073 | + TestCaseWithFactory, |
4074 | + ) |
4075 | + |
4076 | + |
4077 | +class TestBugSubscriptionFilterTag(TestCaseWithFactory): |
4078 | + |
4079 | + layer = DatabaseFunctionalLayer |
4080 | + |
4081 | + def setUp(self): |
4082 | + super(TestBugSubscriptionFilterTag, self).setUp() |
4083 | + self.target = self.factory.makeProduct() |
4084 | + self.subscriber = self.target.owner |
4085 | + login_person(self.subscriber) |
4086 | + self.subscription = self.target.addBugSubscription( |
4087 | + self.subscriber, self.subscriber) |
4088 | + self.subscription_filter = BugSubscriptionFilter() |
4089 | + self.subscription_filter.structural_subscription = self.subscription |
4090 | + |
4091 | + def test_basics(self): |
4092 | + """Test the basics of `BugSubscriptionFilterTag` objects.""" |
4093 | + # Create. |
4094 | + bug_sub_filter_tag = BugSubscriptionFilterTag() |
4095 | + bug_sub_filter_tag.filter = self.subscription_filter |
4096 | + bug_sub_filter_tag.include = True |
4097 | + bug_sub_filter_tag.tag = u"foo" |
4098 | + # Flush and reload. |
4099 | + IStore(bug_sub_filter_tag).flush() |
4100 | + IStore(bug_sub_filter_tag).reload(bug_sub_filter_tag) |
4101 | + # Check. |
4102 | + self.assertIsNot(None, bug_sub_filter_tag.id) |
4103 | + self.assertEqual( |
4104 | + self.subscription_filter.id, |
4105 | + bug_sub_filter_tag.filter_id) |
4106 | + self.assertEqual( |
4107 | + self.subscription_filter, |
4108 | + bug_sub_filter_tag.filter) |
4109 | + self.assertIs(True, bug_sub_filter_tag.include) |
4110 | + self.assertEqual(u"foo", bug_sub_filter_tag.tag) |
4111 | |
4112 | === modified file 'lib/lp/bugs/tests/has-bug-supervisor.txt' |
4113 | --- lib/lp/bugs/tests/has-bug-supervisor.txt 2009-08-25 11:21:05 +0000 |
4114 | +++ lib/lp/bugs/tests/has-bug-supervisor.txt 2010-10-04 22:08:24 +0000 |
4115 | @@ -5,7 +5,7 @@ |
4116 | structural subscription targets. When the bug supervisor for such an object |
4117 | is set, a new bug subscription is created as well. |
4118 | |
4119 | - >>> target.bug_subscriptions |
4120 | + >>> list(target.bug_subscriptions) |
4121 | [] |
4122 | |
4123 | >>> print target.bug_supervisor |
4124 | |
4125 | === added file 'lib/lp/bugs/tests/test_bugtracker_components.py' |
4126 | --- lib/lp/bugs/tests/test_bugtracker_components.py 1970-01-01 00:00:00 +0000 |
4127 | +++ lib/lp/bugs/tests/test_bugtracker_components.py 2010-10-04 22:08:24 +0000 |
4128 | @@ -0,0 +1,176 @@ |
4129 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
4130 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
4131 | + |
4132 | +"""Test for components and component groups (products) in bug trackers.""" |
4133 | + |
4134 | +__metaclass__ = type |
4135 | + |
4136 | +__all__ = [] |
4137 | + |
4138 | +import unittest |
4139 | + |
4140 | +from canonical.launchpad.ftests import login_person |
4141 | +from canonical.testing import DatabaseFunctionalLayer |
4142 | +from lp.testing import TestCaseWithFactory |
4143 | + |
4144 | +class TestBugTrackerComponent(TestCaseWithFactory): |
4145 | + |
4146 | + layer = DatabaseFunctionalLayer |
4147 | + |
4148 | + def setUp(self): |
4149 | + super(TestBugTrackerComponent, self).setUp() |
4150 | + |
4151 | + regular_user = self.factory.makePerson() |
4152 | + login_person(regular_user) |
4153 | + |
4154 | + self.bug_tracker = self.factory.makeBugTracker() |
4155 | + |
4156 | + self.comp_group = self.factory.makeBugTrackerComponentGroup( |
4157 | + u'alpha', |
4158 | + self.bug_tracker) |
4159 | + |
4160 | + def test_component_creation(self): |
4161 | + """Verify a component can be created""" |
4162 | + component = self.factory.makeBugTrackerComponent( |
4163 | + u'example', self.comp_group) |
4164 | + self.assertTrue(component is not None) |
4165 | + self.assertEqual(component.name, u'example') |
4166 | + |
4167 | + def test_set_visibility(self): |
4168 | + """Users can delete components |
4169 | + |
4170 | + In case invalid components get imported from a remote bug |
4171 | + tracker, users can hide them so they don't show up in the UI. |
4172 | + We do this rather than delete them outright so that they won't |
4173 | + show up again when we re-sync from the remote bug tracker. |
4174 | + """ |
4175 | + component = self.factory.makeBugTrackerComponent( |
4176 | + u'example', self.comp_group) |
4177 | + self.assertEqual(component.is_visible, True) |
4178 | + |
4179 | + component.is_visible = False |
4180 | + self.assertEqual(component.is_visible, False) |
4181 | + |
4182 | + component.is_visible = True |
4183 | + self.assertEqual(component.is_visible, True) |
4184 | + |
4185 | + def test_custom_component(self): |
4186 | + """Users can also add components |
4187 | + |
4188 | + For whatever reason, it may be that we can't import a component |
4189 | + from the remote bug tracker. This gives users a way to correct |
4190 | + the omissions.""" |
4191 | + custom_component = self.factory.makeBugTrackerComponent( |
4192 | + u'example', self.comp_group, custom=True) |
4193 | + self.assertTrue(custom_component != None) |
4194 | + self.assertEqual(custom_component.is_custom, True) |
4195 | + |
4196 | + def test_multiple_component_creation(self): |
4197 | + """Verify several components can be created at once""" |
4198 | + comp_a = self.factory.makeBugTrackerComponent( |
4199 | + u'example-a', self.comp_group) |
4200 | + comp_b = self.factory.makeBugTrackerComponent( |
4201 | + u'example-b', self.comp_group) |
4202 | + comp_c = self.factory.makeBugTrackerComponent( |
4203 | + u'example-c', self.comp_group, True) |
4204 | + |
4205 | + self.assertTrue(comp_a is not None) |
4206 | + self.assertTrue(comp_b is not None) |
4207 | + self.assertTrue(comp_c is not None) |
4208 | + |
4209 | + |
4210 | +class TestBugTrackerWithComponents(TestCaseWithFactory): |
4211 | + |
4212 | + layer = DatabaseFunctionalLayer |
4213 | + |
4214 | + def setUp(self): |
4215 | + super(TestBugTrackerWithComponents, self).setUp() |
4216 | + |
4217 | + regular_user = self.factory.makePerson() |
4218 | + login_person(regular_user) |
4219 | + |
4220 | + self.bug_tracker = self.factory.makeBugTracker() |
4221 | + |
4222 | + def test_empty_bugtracker(self): |
4223 | + """Trivial case of bugtracker with no products or components""" |
4224 | + self.assertTrue(self.bug_tracker is not None) |
4225 | + |
4226 | + # Empty bugtrackers shouldn't return component groups |
4227 | + comp_group = self.bug_tracker.getRemoteComponentGroup(u'non-existant') |
4228 | + self.assertEqual(comp_group, None) |
4229 | + |
4230 | + # Verify it contains no component groups |
4231 | + comp_groups = self.bug_tracker.getAllRemoteComponentGroups() |
4232 | + self.assertEqual(len(list(comp_groups)), 0) |
4233 | + |
4234 | + def test_single_product_bugtracker(self): |
4235 | + """Bug tracker with a single (default) product and several components |
4236 | + """ |
4237 | + # Add a component group and fill it with some components |
4238 | + default_comp_group = self.bug_tracker.addRemoteComponentGroup( |
4239 | + u'alpha') |
4240 | + default_comp_group.addComponent(u'example-a') |
4241 | + default_comp_group.addComponent(u'example-b') |
4242 | + default_comp_group.addComponent(u'example-c') |
4243 | + |
4244 | + # Verify that retrieving an invalid component group returns nothing |
4245 | + comp_group = self.bug_tracker.getRemoteComponentGroup(u'non-existant') |
4246 | + self.assertEqual(comp_group, None) |
4247 | + |
4248 | + # Now retrieve the component group we added |
4249 | + comp_group = self.bug_tracker.getRemoteComponentGroup(u'alpha') |
4250 | + self.assertEqual(comp_group, default_comp_group) |
4251 | + self.assertEqual(comp_group.name, u'alpha') |
4252 | + |
4253 | + # Verify there is only the one component group in the tracker |
4254 | + comp_groups = self.bug_tracker.getAllRemoteComponentGroups() |
4255 | + self.assertEqual(len(list(comp_groups)), 1) |
4256 | + |
4257 | + def test_multiple_product_bugtracker(self): |
4258 | + """Bug tracker with multiple products and components""" |
4259 | + # Create several component groups with varying numbers of components |
4260 | + comp_group_i = self.bug_tracker.addRemoteComponentGroup(u'alpha') |
4261 | + |
4262 | + comp_group_ii = self.bug_tracker.addRemoteComponentGroup(u'beta') |
4263 | + comp_group_ii.addComponent(u'example-beta-1') |
4264 | + |
4265 | + comp_group_iii = self.bug_tracker.addRemoteComponentGroup(u'gamma') |
4266 | + comp_group_iii.addComponent(u'example-gamma-1') |
4267 | + comp_group_iii.addComponent(u'example-gamma-2') |
4268 | + comp_group_iii.addComponent(u'example-gamma-3') |
4269 | + |
4270 | + # Retrieving a non-existant component group returns nothing |
4271 | + comp_group = self.bug_tracker.getRemoteComponentGroup(u'non-existant') |
4272 | + self.assertEqual(comp_group, None) |
4273 | + |
4274 | + # Now retrieve one of the real component groups |
4275 | + comp_group = self.bug_tracker.getRemoteComponentGroup(u'beta') |
4276 | + self.assertEqual(comp_group, comp_group_ii) |
4277 | + |
4278 | + # Check the correct number of component groups are in the bug tracker |
4279 | + comp_groups = self.bug_tracker.getAllRemoteComponentGroups() |
4280 | + self.assertEqual(len(list(comp_groups)), 3) |
4281 | + |
4282 | + def test_get_components_for_component_group(self): |
4283 | + """Retrieve a set of components from a given product""" |
4284 | + # Create a component group with some components |
4285 | + default_comp_group = self.bug_tracker.addRemoteComponentGroup( |
4286 | + u'alpha') |
4287 | + default_comp_group.addComponent(u'example-a') |
4288 | + default_comp_group.addComponent(u'example-b') |
4289 | + default_comp_group.addComponent(u'example-c') |
4290 | + |
4291 | + # Verify group has the correct number of components |
4292 | + comp_group = self.bug_tracker.getRemoteComponentGroup(u'alpha') |
4293 | + self.assertEqual(len(list(comp_group.components)), 3) |
4294 | + |
4295 | + # Check one of the components, that it is what we expect |
4296 | + comp = comp_group.getComponent(u'example-b') |
4297 | + self.assertEqual(comp.name, u'example-b') |
4298 | + |
4299 | + |
4300 | +def test_suite(): |
4301 | + suite = unittest.TestSuite() |
4302 | + suite.addTest(unittest.TestLoader().loadTestsFromName(__name__)) |
4303 | + |
4304 | + return suite |
4305 | |
4306 | === modified file 'lib/lp/buildmaster/interfaces/buildfarmjob.py' |
4307 | --- lib/lp/buildmaster/interfaces/buildfarmjob.py 2010-09-16 12:27:46 +0000 |
4308 | +++ lib/lp/buildmaster/interfaces/buildfarmjob.py 2010-10-04 22:08:24 +0000 |
4309 | @@ -1,4 +1,4 @@ |
4310 | -# Copyright 2009 Canonical Ltd. This software is licensed under the |
4311 | +# Copyright 2009-2010 Canonical Ltd. This software is licensed under the |
4312 | # GNU Affero General Public License version 3 (see the file LICENSE). |
4313 | |
4314 | # pylint: disable-msg=E0211,E0213 |
4315 | @@ -256,6 +256,15 @@ |
4316 | |
4317 | was_built = Attribute("Whether or not modified by the builddfarm.") |
4318 | |
4319 | + # This doesn't belong here. It really belongs in IPackageBuild, but |
4320 | + # the TAL assumes it can read this directly. |
4321 | + dependencies = exported( |
4322 | + TextLine( |
4323 | + title=_('Dependencies'), required=False, |
4324 | + description=_( |
4325 | + 'Debian-like dependency line that must be satisfied before ' |
4326 | + 'attempting to build this request.'))) |
4327 | + |
4328 | |
4329 | class ISpecificBuildFarmJob(IBuildFarmJob): |
4330 | """A marker interface with which to define adapters for IBuildFarmJob. |
4331 | |
4332 | === modified file 'lib/lp/buildmaster/interfaces/packagebuild.py' |
4333 | --- lib/lp/buildmaster/interfaces/packagebuild.py 2010-09-10 12:29:36 +0000 |
4334 | +++ lib/lp/buildmaster/interfaces/packagebuild.py 2010-10-04 22:08:24 +0000 |
4335 | @@ -61,12 +61,6 @@ |
4336 | description=_("A URL for failed upload logs." |
4337 | "Will be None if there was no failure."))) |
4338 | |
4339 | - dependencies = exported( |
4340 | - TextLine( |
4341 | - title=_('Dependencies'), required=False, |
4342 | - description=_('Debian-like dependency line that must be satisfied' |
4343 | - ' before attempting to build this request.'))) |
4344 | - |
4345 | build_farm_job = Reference( |
4346 | title=_('Build farm job'), schema=IBuildFarmJob, required=True, |
4347 | readonly=True, description=_('The base build farm job.')) |
4348 | |
4349 | === modified file 'lib/lp/buildmaster/model/buildfarmjob.py' |
4350 | --- lib/lp/buildmaster/model/buildfarmjob.py 2010-09-16 12:27:46 +0000 |
4351 | +++ lib/lp/buildmaster/model/buildfarmjob.py 2010-10-04 22:08:24 +0000 |
4352 | @@ -237,6 +237,8 @@ |
4353 | |
4354 | failure_count = Int(name='failure_count', allow_none=False) |
4355 | |
4356 | + dependencies = None |
4357 | + |
4358 | def __init__(self, job_type, status=BuildStatus.NEEDSBUILD, |
4359 | processor=None, virtualized=None, date_created=None): |
4360 | super(BuildFarmJob, self).__init__() |
4361 | @@ -273,7 +275,7 @@ |
4362 | return self.date_finished - self.date_started |
4363 | |
4364 | def makeJob(self): |
4365 | - """See `IBuildFarmJob`.""" |
4366 | + """See `IBuildFarmJobOld`.""" |
4367 | raise NotImplementedError |
4368 | |
4369 | def jobStarted(self): |
4370 | @@ -420,7 +422,8 @@ |
4371 | # specific private builds to which they have access. |
4372 | origin.extend(left_join_archive) |
4373 | origin.append(LeftJoin( |
4374 | - TeamParticipation, TeamParticipation.teamID == Archive.ownerID)) |
4375 | + TeamParticipation, |
4376 | + TeamParticipation.teamID == Archive.ownerID)) |
4377 | extra_clauses.append( |
4378 | Or(Coalesce(Archive.private, False) == False, |
4379 | TeamParticipation.person == user)) |
4380 | |
4381 | === modified file 'lib/lp/code/browser/branch.py' |
4382 | --- lib/lp/code/browser/branch.py 2010-09-22 18:54:36 +0000 |
4383 | +++ lib/lp/code/browser/branch.py 2010-10-04 22:08:24 +0000 |
4384 | @@ -105,6 +105,7 @@ |
4385 | from canonical.widgets.branch import TargetBranchWidget |
4386 | from canonical.widgets.itemswidgets import LaunchpadRadioWidgetWithDescription |
4387 | from canonical.widgets.lazrjs import vocabulary_to_choice_edit_items |
4388 | +from lp.app.errors import NotFoundError |
4389 | from lp.blueprints.interfaces.specificationbranch import ISpecificationBranch |
4390 | from lp.bugs.interfaces.bug import IBugSet |
4391 | from lp.bugs.interfaces.bugbranch import IBugBranch |
4392 | @@ -146,6 +147,9 @@ |
4393 | from lp.registry.interfaces.productseries import IProductSeries |
4394 | from lp.registry.vocabularies import UserTeamsParticipationPlusSelfVocabulary |
4395 | from lp.services.propertycache import cachedproperty |
4396 | +from lp.translations.interfaces.translationtemplatesbuild import ( |
4397 | + ITranslationTemplatesBuildSource, |
4398 | + ) |
4399 | |
4400 | |
4401 | def quote(text): |
4402 | @@ -238,6 +242,16 @@ |
4403 | """Traverses to the `ICodeImport` for the branch.""" |
4404 | return self.context.code_import |
4405 | |
4406 | + @stepthrough("+translation-templates-build") |
4407 | + def traverse_translation_templates_build(self, id_string): |
4408 | + """Traverses to a `TranslationTemplatesBuild`.""" |
4409 | + try: |
4410 | + buildfarmjob_id = int(id_string) |
4411 | + except ValueError: |
4412 | + raise NotFoundError(id_string) |
4413 | + source = getUtility(ITranslationTemplatesBuildSource) |
4414 | + return source.getByBuildFarmJob(buildfarmjob_id) |
4415 | + |
4416 | |
4417 | class BranchEditMenu(NavigationMenu): |
4418 | """Edit menu for IBranch.""" |
4419 | |
4420 | === modified file 'lib/lp/code/browser/branchmergeproposal.py' |
4421 | --- lib/lp/code/browser/branchmergeproposal.py 2010-09-27 20:47:58 +0000 |
4422 | +++ lib/lp/code/browser/branchmergeproposal.py 2010-10-04 22:08:24 +0000 |
4423 | @@ -547,7 +547,7 @@ |
4424 | return diff_text.count('\n') >= config.diff.max_format_lines |
4425 | |
4426 | |
4427 | -class ICodeReviewNewRevisions(Interface): |
4428 | +class ICodeReviewNewRevisions(IComment): |
4429 | """Marker interface used to register views for CodeReviewNewRevisions.""" |
4430 | |
4431 | |
4432 | @@ -557,7 +557,7 @@ |
4433 | Each object instance represents a number of revisions scanned at a |
4434 | particular time. |
4435 | """ |
4436 | - implements(IComment, ICodeReviewNewRevisions) |
4437 | + implements(ICodeReviewNewRevisions) |
4438 | |
4439 | def __init__(self, revisions, date, branch): |
4440 | self.revisions = revisions |
4441 | @@ -567,6 +567,13 @@ |
4442 | # The date attribute is used to sort the comments in the conversation. |
4443 | self.date = date |
4444 | |
4445 | + # Other standard IComment attributes are not used. |
4446 | + self.extra_css_class = None |
4447 | + self.comment_author = None |
4448 | + self.body_text = None |
4449 | + self.comment_date = None |
4450 | + self.display_attachments = False |
4451 | + |
4452 | |
4453 | class CodeReviewNewRevisionsView(LaunchpadView): |
4454 | """The view for rendering the new revisions.""" |
4455 | |
4456 | === modified file 'lib/lp/code/browser/codereviewcomment.py' |
4457 | --- lib/lp/code/browser/codereviewcomment.py 2010-10-01 14:14:04 +0000 |
4458 | +++ lib/lp/code/browser/codereviewcomment.py 2010-10-04 22:08:24 +0000 |
4459 | @@ -43,6 +43,10 @@ |
4460 | from lp.services.propertycache import cachedproperty |
4461 | |
4462 | |
4463 | +class ICodeReviewDisplayComment(IComment, ICodeReviewComment): |
4464 | + """Marker interface for displaying code review comments.""" |
4465 | + |
4466 | + |
4467 | class CodeReviewDisplayComment: |
4468 | """A code review comment or activity or both. |
4469 | |
4470 | @@ -51,7 +55,7 @@ |
4471 | only code in the model itself. |
4472 | """ |
4473 | |
4474 | - implements(IComment) |
4475 | + implements(ICodeReviewDisplayComment) |
4476 | |
4477 | delegates(ICodeReviewComment, 'comment') |
4478 | |
4479 | @@ -70,6 +74,40 @@ |
4480 | else: |
4481 | return '' |
4482 | |
4483 | + @cachedproperty |
4484 | + def comment_author(self): |
4485 | + """The author of the comment.""" |
4486 | + return self.comment.message.owner |
4487 | + |
4488 | + @cachedproperty |
4489 | + def has_body(self): |
4490 | + """Is there body text?""" |
4491 | + return bool(self.body_text) |
4492 | + |
4493 | + @cachedproperty |
4494 | + def body_text(self): |
4495 | + """Get the body text for the message.""" |
4496 | + return self.comment.message_body |
4497 | + |
4498 | + @cachedproperty |
4499 | + def comment_date(self): |
4500 | + """The date of the comment.""" |
4501 | + return self.comment.message.datecreated |
4502 | + |
4503 | + @cachedproperty |
4504 | + def all_attachments(self): |
4505 | + return self.comment.getAttachments() |
4506 | + |
4507 | + @cachedproperty |
4508 | + def display_attachments(self): |
4509 | + # Attachments to show. |
4510 | + return [DiffAttachment(alias) for alias in self.all_attachments[0]] |
4511 | + |
4512 | + @cachedproperty |
4513 | + def other_attachments(self): |
4514 | + # Attachments to not show. |
4515 | + return self.all_attachments[1] |
4516 | + |
4517 | |
4518 | class CodeReviewCommentPrimaryContext: |
4519 | """The primary context is the comment is that of the source branch.""" |
4520 | @@ -132,45 +170,11 @@ |
4521 | """The decorated code review comment.""" |
4522 | return CodeReviewDisplayComment(self.context) |
4523 | |
4524 | - @cachedproperty |
4525 | - def comment_author(self): |
4526 | - """The author of the comment.""" |
4527 | - return self.context.message.owner |
4528 | - |
4529 | - @cachedproperty |
4530 | - def has_body(self): |
4531 | - """Is there body text?""" |
4532 | - return bool(self.body_text) |
4533 | - |
4534 | - @cachedproperty |
4535 | - def body_text(self): |
4536 | - """Get the body text for the message.""" |
4537 | - return self.context.message_body |
4538 | - |
4539 | - @cachedproperty |
4540 | - def comment_date(self): |
4541 | - """The date of the comment.""" |
4542 | - return self.context.message.datecreated |
4543 | - |
4544 | # Should the comment be shown in full? |
4545 | full_comment = True |
4546 | # Show comment expanders? |
4547 | show_expanders = False |
4548 | |
4549 | - @cachedproperty |
4550 | - def all_attachments(self): |
4551 | - return self.context.getAttachments() |
4552 | - |
4553 | - @cachedproperty |
4554 | - def display_attachments(self): |
4555 | - # Attachments to show. |
4556 | - return [DiffAttachment(alias) for alias in self.all_attachments[0]] |
4557 | - |
4558 | - @cachedproperty |
4559 | - def other_attachments(self): |
4560 | - # Attachments to not show. |
4561 | - return self.all_attachments[1] |
4562 | - |
4563 | |
4564 | class CodeReviewCommentSummary(CodeReviewCommentView): |
4565 | """Summary view of a CodeReviewComment""" |
4566 | |
4567 | === modified file 'lib/lp/code/browser/configure.zcml' |
4568 | --- lib/lp/code/browser/configure.zcml 2010-09-30 22:26:08 +0000 |
4569 | +++ lib/lp/code/browser/configure.zcml 2010-10-04 22:08:24 +0000 |
4570 | @@ -691,6 +691,16 @@ |
4571 | name="+index" |
4572 | template="../templates/codereviewcomment-index.pt"/> |
4573 | <browser:page |
4574 | + name="+fragment" |
4575 | + template="../templates/codereviewcomment-fragment.pt"/> |
4576 | + </browser:pages> |
4577 | + <browser:pages |
4578 | + facet="branches" |
4579 | + for="lp.code.browser.codereviewcomment.ICodeReviewDisplayComment" |
4580 | + layer="lp.code.publisher.CodeLayer" |
4581 | + class="lp.code.browser.codereviewcomment.CodeReviewCommentView" |
4582 | + permission="zope.Public"> |
4583 | + <browser:page |
4584 | name="+comment-header" |
4585 | template="../templates/codereviewcomment-header.pt"/> |
4586 | <browser:page |
4587 | @@ -699,9 +709,6 @@ |
4588 | <browser:page |
4589 | name="+comment-footer" |
4590 | template="../templates/codereviewcomment-footer.pt"/> |
4591 | - <browser:page |
4592 | - name="+fragment" |
4593 | - template="../templates/codereviewcomment-fragment.pt"/> |
4594 | </browser:pages> |
4595 | <browser:pages |
4596 | facet="branches" |
4597 | |
4598 | === modified file 'lib/lp/code/browser/tests/test_branchmergeproposal.py' |
4599 | --- lib/lp/code/browser/tests/test_branchmergeproposal.py 2010-09-15 20:41:46 +0000 |
4600 | +++ lib/lp/code/browser/tests/test_branchmergeproposal.py 2010-10-04 22:08:24 +0000 |
4601 | @@ -23,6 +23,7 @@ |
4602 | from canonical.launchpad.database.message import MessageSet |
4603 | from canonical.launchpad.webapp.interfaces import IPrimaryContext |
4604 | from canonical.launchpad.webapp.servers import LaunchpadTestRequest |
4605 | +from canonical.launchpad.webapp.testing import verifyObject |
4606 | from canonical.testing import ( |
4607 | DatabaseFunctionalLayer, |
4608 | LaunchpadFunctionalLayer, |
4609 | @@ -35,8 +36,10 @@ |
4610 | BranchMergeProposalMergedView, |
4611 | BranchMergeProposalVoteView, |
4612 | DecoratedCodeReviewVoteReference, |
4613 | + ICodeReviewNewRevisions, |
4614 | latest_proposals_for_each_branch, |
4615 | ) |
4616 | +from lp.code.browser.codereviewcomment import CodeReviewDisplayComment |
4617 | from lp.code.enums import ( |
4618 | BranchMergeProposalStatus, |
4619 | CodeReviewVote, |
4620 | @@ -45,6 +48,7 @@ |
4621 | PreviewDiff, |
4622 | StaticDiff, |
4623 | ) |
4624 | +from lp.code.tests.helpers import add_revision_to_branch |
4625 | from lp.testing import ( |
4626 | login_person, |
4627 | TestCaseWithFactory, |
4628 | @@ -575,6 +579,20 @@ |
4629 | view = create_initialized_view(self.bmp, '+index') |
4630 | self.assertEqual([], view.linked_bugs) |
4631 | |
4632 | + def test_CodeReviewNewRevisions_implements_ICodeReviewNewRevisions(self): |
4633 | + # The browser helper class implements its interface. |
4634 | + review_date = datetime(2009, 9, 10, tzinfo=pytz.UTC) |
4635 | + revision_date = review_date + timedelta(days=1) |
4636 | + bmp = self.factory.makeBranchMergeProposal( |
4637 | + date_created=review_date) |
4638 | + revision = add_revision_to_branch( |
4639 | + self.factory, bmp.source_branch, revision_date) |
4640 | + |
4641 | + view = create_initialized_view(bmp, '+index') |
4642 | + new_revisions = view.conversation.comments[0] |
4643 | + |
4644 | + self.assertTrue(verifyObject(ICodeReviewNewRevisions, new_revisions)) |
4645 | + |
4646 | def test_include_superseded_comments(self): |
4647 | for x, time in zip(range(3), time_counter()): |
4648 | if x != 0: |
4649 | @@ -707,7 +725,8 @@ |
4650 | body='testing', |
4651 | attachments=[('test.diff', 'text/plain', attachment_body)]) |
4652 | message = MessageSet().fromEmail(msg.as_string()) |
4653 | - return bmp.createCommentFromMessage(message, None, None, msg) |
4654 | + return CodeReviewDisplayComment( |
4655 | + bmp.createCommentFromMessage(message, None, None, msg)) |
4656 | |
4657 | def test_nonascii_in_attachment_renders(self): |
4658 | # The view should render without errors. |
4659 | @@ -723,7 +742,7 @@ |
4660 | # Need to commit in order to read the diff out of the librarian. |
4661 | transaction.commit() |
4662 | view = create_initialized_view(comment, '+comment-body') |
4663 | - [diff_attachment] = view.display_attachments |
4664 | + [diff_attachment] = view.comment.display_attachments |
4665 | self.assertEqual(u'\u2615', diff_attachment.diff_text) |
4666 | |
4667 | |
4668 | |
4669 | === modified file 'lib/lp/code/browser/tests/test_codereviewcomment.py' |
4670 | --- lib/lp/code/browser/tests/test_codereviewcomment.py 2010-08-20 20:31:18 +0000 |
4671 | +++ lib/lp/code/browser/tests/test_codereviewcomment.py 2010-10-04 22:08:24 +0000 |
4672 | @@ -3,35 +3,52 @@ |
4673 | |
4674 | """Unit tests for CodeReviewComments.""" |
4675 | |
4676 | +from __future__ import with_statement |
4677 | + |
4678 | __metaclass__ = type |
4679 | |
4680 | import unittest |
4681 | |
4682 | from canonical.launchpad.webapp.interfaces import IPrimaryContext |
4683 | +from canonical.launchpad.webapp.testing import verifyObject |
4684 | from canonical.testing import DatabaseFunctionalLayer |
4685 | +from lp.code.browser.codereviewcomment import ( |
4686 | + CodeReviewDisplayComment, |
4687 | + ICodeReviewDisplayComment, |
4688 | + ) |
4689 | from lp.testing import ( |
4690 | - login_person, |
4691 | + person_logged_in, |
4692 | TestCaseWithFactory, |
4693 | ) |
4694 | |
4695 | |
4696 | -class TestCodeReviewCommentPrimaryContext(TestCaseWithFactory): |
4697 | - # Tests the adaptation of a code review comment into a primary context. |
4698 | +class TestCodeReviewComments(TestCaseWithFactory): |
4699 | |
4700 | layer = DatabaseFunctionalLayer |
4701 | |
4702 | def testPrimaryContext(self): |
4703 | + # Tests the adaptation of a code review comment into a primary |
4704 | + # context. |
4705 | # We need a person to make a comment. |
4706 | - commenter = self.factory.makePerson() |
4707 | - login_person(commenter) |
4708 | - # The primary context of a code review comment is the same as the |
4709 | - # primary context for the branch merge proposal that the comment is |
4710 | - # for. |
4711 | - comment = self.factory.makeCodeReviewComment() |
4712 | + with person_logged_in(self.factory.makePerson()): |
4713 | + # The primary context of a code review comment is the same |
4714 | + # as the primary context for the branch merge proposal that |
4715 | + # the comment is for. |
4716 | + comment = self.factory.makeCodeReviewComment() |
4717 | + |
4718 | self.assertEqual( |
4719 | IPrimaryContext(comment).context, |
4720 | IPrimaryContext(comment.branch_merge_proposal).context) |
4721 | |
4722 | + def test_display_comment_provides_icodereviewdisplaycomment(self): |
4723 | + # The CodeReviewDisplayComment class provides IComment. |
4724 | + with person_logged_in(self.factory.makePerson()): |
4725 | + comment = self.factory.makeCodeReviewComment() |
4726 | + |
4727 | + display_comment = CodeReviewDisplayComment(comment) |
4728 | + |
4729 | + verifyObject(ICodeReviewDisplayComment, display_comment) |
4730 | + |
4731 | |
4732 | def test_suite(): |
4733 | return unittest.TestLoader().loadTestsFromName(__name__) |
4734 | |
4735 | === modified file 'lib/lp/code/doc/branch.txt' |
4736 | --- lib/lp/code/doc/branch.txt 2010-10-01 14:14:04 +0000 |
4737 | +++ lib/lp/code/doc/branch.txt 2010-10-04 22:08:24 +0000 |
4738 | @@ -405,6 +405,7 @@ |
4739 | sourcepackagerecipedata.base_branch |
4740 | sourcepackagerecipedatainstruction.branch |
4741 | specificationbranch.branch |
4742 | + translationtemplatesbuild.branch |
4743 | |
4744 | (Unfortunately, references can form a cycle-- note that |
4745 | codereviewcomments |
4746 | |
4747 | === modified file 'lib/lp/code/interfaces/branchrevision.py' |
4748 | --- lib/lp/code/interfaces/branchrevision.py 2010-09-09 01:04:26 +0000 |
4749 | +++ lib/lp/code/interfaces/branchrevision.py 2010-10-04 22:08:24 +0000 |
4750 | @@ -26,8 +26,6 @@ |
4751 | ancestry of a branch. History revisions have an integer sequence, merged |
4752 | revisions have sequence set to None. |
4753 | """ |
4754 | - id = Int(title=_('The database revision ID')) |
4755 | - |
4756 | sequence = Int( |
4757 | title=_("Revision number"), required=True, |
4758 | description=_("The index of the revision within the branch's history." |
4759 | |
4760 | === modified file 'lib/lp/code/model/branch.py' |
4761 | --- lib/lp/code/model/branch.py 2010-09-21 02:46:02 +0000 |
4762 | +++ lib/lp/code/model/branch.py 2010-10-04 22:08:24 +0000 |
4763 | @@ -919,7 +919,7 @@ |
4764 | def getScannerData(self): |
4765 | """See `IBranch`.""" |
4766 | columns = ( |
4767 | - BranchRevision.id, BranchRevision.sequence, Revision.revision_id) |
4768 | + BranchRevision.sequence, Revision.revision_id) |
4769 | rows = Store.of(self).using(Revision, BranchRevision).find( |
4770 | columns, |
4771 | Revision.id == BranchRevision.revision_id, |
4772 | @@ -927,7 +927,7 @@ |
4773 | rows = rows.order_by(BranchRevision.sequence) |
4774 | ancestry = set() |
4775 | history = [] |
4776 | - for branch_revision_id, sequence, revision_id in rows: |
4777 | + for sequence, revision_id in rows: |
4778 | ancestry.add(revision_id) |
4779 | if sequence is not None: |
4780 | history.append(revision_id) |
4781 | @@ -1027,10 +1027,14 @@ |
4782 | """Delete jobs for this branch prior to deleting branch. |
4783 | |
4784 | This deletion includes `BranchJob`s associated with the branch, |
4785 | - as well as `BuildQueue` entries for `TranslationTemplateBuildJob`s. |
4786 | + as well as `BuildQueue` entries for `TranslationTemplateBuildJob`s |
4787 | + and `TranslationTemplateBuild`s. |
4788 | """ |
4789 | # Avoid circular imports. |
4790 | from lp.code.model.branchjob import BranchJob |
4791 | + from lp.translations.model.translationtemplatesbuild import ( |
4792 | + TranslationTemplatesBuild, |
4793 | + ) |
4794 | |
4795 | store = Store.of(self) |
4796 | affected_jobs = Select( |
4797 | @@ -1044,6 +1048,10 @@ |
4798 | # Delete Jobs. Their BranchJobs cascade along in the database. |
4799 | store.find(Job, Job.id.is_in(affected_jobs)).remove() |
4800 | |
4801 | + store.find( |
4802 | + TranslationTemplatesBuild, |
4803 | + TranslationTemplatesBuild.branch == self).remove() |
4804 | + |
4805 | def destroySelf(self, break_references=False): |
4806 | """See `IBranch`.""" |
4807 | from lp.code.interfaces.branchjob import IReclaimBranchSpaceJobSource |
4808 | |
4809 | === modified file 'lib/lp/code/model/branchmergeproposal.py' |
4810 | --- lib/lp/code/model/branchmergeproposal.py 2010-09-22 18:55:25 +0000 |
4811 | +++ lib/lp/code/model/branchmergeproposal.py 2010-10-04 22:08:24 +0000 |
4812 | @@ -633,7 +633,7 @@ |
4813 | SourceRevision, |
4814 | SourceRevision.branch_id == self.source_branch.id, |
4815 | SourceRevision.sequence != None, |
4816 | - TargetRevision.id == None) |
4817 | + TargetRevision.branch_id == None) |
4818 | return result.order_by(Desc(SourceRevision.sequence)).config(limit=10) |
4819 | |
4820 | def createComment(self, owner, subject, content=None, vote=None, |
4821 | |
4822 | === modified file 'lib/lp/code/model/branchrevision.py' |
4823 | --- lib/lp/code/model/branchrevision.py 2010-09-09 01:04:26 +0000 |
4824 | +++ lib/lp/code/model/branchrevision.py 2010-10-04 22:08:24 +0000 |
4825 | @@ -21,8 +21,7 @@ |
4826 | class BranchRevision(Storm): |
4827 | """See `IBranchRevision`.""" |
4828 | __storm_table__ = 'BranchRevision' |
4829 | - |
4830 | - id = Int(primary=True) |
4831 | + __storm_primary__ = "branch_id", "revision_id" |
4832 | |
4833 | implements(IBranchRevision) |
4834 | |
4835 | |
4836 | === modified file 'lib/lp/code/model/tests/test_branchjob.py' |
4837 | --- lib/lp/code/model/tests/test_branchjob.py 2010-08-20 20:31:18 +0000 |
4838 | +++ lib/lp/code/model/tests/test_branchjob.py 2010-10-04 22:08:24 +0000 |
4839 | @@ -518,9 +518,7 @@ |
4840 | except bzr_errors.NoSuchRevision: |
4841 | revno = None |
4842 | if existing is not None: |
4843 | - branchrevision = IMasterStore(branch).find( |
4844 | - BranchRevision, BranchRevision.id == existing.id) |
4845 | - branchrevision.remove() |
4846 | + branch.removeBranchRevisions([existing.revision.revision_id]) |
4847 | branch.createBranchRevision(revno, revision) |
4848 | |
4849 | def create3CommitsBranch(self): |
4850 | |
4851 | === modified file 'lib/lp/code/templates/codereviewcomment-body.pt' |
4852 | --- lib/lp/code/templates/codereviewcomment-body.pt 2010-04-16 04:20:43 +0000 |
4853 | +++ lib/lp/code/templates/codereviewcomment-body.pt 2010-10-04 22:08:24 +0000 |
4854 | @@ -3,9 +3,9 @@ |
4855 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
4856 | omit-tag=""> |
4857 | |
4858 | - <tal:message replace="structure view/body_text/fmt:obfuscate-email/fmt:nice_pre" /> |
4859 | + <tal:message replace="structure view/comment/body_text/fmt:obfuscate-email/fmt:nice_pre" /> |
4860 | |
4861 | - <tal:good-attachments repeat="attachment view/display_attachments"> |
4862 | + <tal:good-attachments repeat="attachment view/comment/display_attachments"> |
4863 | <div class="boardComment attachment"> |
4864 | <div class="boardCommentDetails filename"><a tal:content="attachment/filename" tal:attributes="href attachment/getURL"/></div> |
4865 | <div class="boardCommentBody attachmentBody" tal:content="structure attachment/diff_text/fmt:diff"/> |
4866 | |
4867 | === modified file 'lib/lp/code/templates/codereviewcomment-header.pt' |
4868 | --- lib/lp/code/templates/codereviewcomment-header.pt 2010-02-18 16:40:09 +0000 |
4869 | +++ lib/lp/code/templates/codereviewcomment-header.pt 2010-10-04 22:08:24 +0000 |
4870 | @@ -3,9 +3,9 @@ |
4871 | xmlns:metal="http://xml.zope.org/namespaces/metal" |
4872 | omit-tag=""> |
4873 | |
4874 | - <tal:author replace="structure view/comment_author/fmt:link:mainsite"/> |
4875 | - <tal:has-body condition="view/has_body">wrote</tal:has-body> |
4876 | - <tal:date replace="view/comment_date/fmt:displaydate" /> |
4877 | + <tal:author replace="structure context/comment_author/fmt:link:mainsite"/> |
4878 | + <tal:has-body condition="context/has_body">wrote</tal:has-body> |
4879 | + <tal:date replace="context/comment_date/fmt:displaydate" /> |
4880 | <span tal:condition="context/from_superseded" class="sprite warning-icon" |
4881 | style="float: right">Posted in <a |
4882 | tal:attributes="href context/branch_merge_proposal/fmt:url">a |
4883 | |
4884 | === modified file 'lib/lp/codehosting/sshserver/session.py' |
4885 | --- lib/lp/codehosting/sshserver/session.py 2010-08-20 20:31:18 +0000 |
4886 | +++ lib/lp/codehosting/sshserver/session.py 2010-10-04 22:08:24 +0000 |
4887 | @@ -9,9 +9,20 @@ |
4888 | ] |
4889 | |
4890 | import os |
4891 | +import signal |
4892 | +import socket |
4893 | import urlparse |
4894 | |
4895 | -from twisted.internet.process import ProcessExitedAlready |
4896 | +from zope.event import notify |
4897 | +from zope.interface import implements |
4898 | + |
4899 | +from twisted.internet import ( |
4900 | + error, |
4901 | + fdesc, |
4902 | + interfaces, |
4903 | + main, |
4904 | + process, |
4905 | + ) |
4906 | from twisted.python import log |
4907 | from zope.event import notify |
4908 | |
4909 | @@ -35,6 +46,229 @@ |
4910 | """Raised when a session is asked to execute a forbidden command.""" |
4911 | |
4912 | |
4913 | +class _WaitForExit(process.ProcessReader): |
4914 | + """Wait on a socket for the exit status.""" |
4915 | + |
4916 | + def __init__(self, reactor, proc, sock): |
4917 | + super(_WaitForExit, self).__init__(reactor, proc, 'exit', |
4918 | + sock.fileno()) |
4919 | + self._sock = sock |
4920 | + self.connected = 1 |
4921 | + |
4922 | + def close(self): |
4923 | + self._sock.close() |
4924 | + |
4925 | + def dataReceived(self, data): |
4926 | + # TODO: how do we handle getting only *some* of the content?, Maybe we |
4927 | + # need to read more bytes first... |
4928 | + |
4929 | + # This is the only thing we do differently from the standard |
4930 | + # ProcessReader. When we get data on this socket, we need to treat it |
4931 | + # as a return code, or a failure. |
4932 | + if not data.startswith('exited'): |
4933 | + # Bad data, we want to signal that we are closing the connection |
4934 | + # TODO: How? |
4935 | + # self.proc.? |
4936 | + self.close() |
4937 | + # I don't know what to put here if we get bogus data, but I *do* |
4938 | + # want to say that the process is now considered dead to me |
4939 | + log.err('Got invalid exit information: %r' % (data,)) |
4940 | + exit_status = (255 << 8) |
4941 | + else: |
4942 | + exit_status = int(data.split('\n')[1]) |
4943 | + self.proc.processEnded(exit_status) |
4944 | + |
4945 | + |
4946 | +class ForkedProcessTransport(process.BaseProcess): |
4947 | + """Wrap the forked process in a ProcessTransport so we can talk to it. |
4948 | + |
4949 | + Note that instantiating the class creates the fork and sets it up in the |
4950 | + reactor. |
4951 | + """ |
4952 | + |
4953 | + implements(interfaces.IProcessTransport) |
4954 | + |
4955 | + # Design decisions |
4956 | + # [Decision #a] |
4957 | + # Inherit from process.BaseProcess |
4958 | + # This seems slightly risky, as process.BaseProcess is actually |
4959 | + # imported from twisted.internet._baseprocess.BaseProcess. The |
4960 | + # real-world Process then actually inherits from process._BaseProcess |
4961 | + # I've also had to copy a fair amount from the actual Process |
4962 | + # command. |
4963 | + # One option would be to inherit from process.Process, and just |
4964 | + # override stuff like __init__ and reapProcess which I don't want to |
4965 | + # do in the same way. (Is it ok not to call your Base classes |
4966 | + # __init__ if you don't want to do that exact work?) |
4967 | + |
4968 | + def __init__(self, reactor, executable, args, environment, proto): |
4969 | + process.BaseProcess.__init__(self, proto) |
4970 | + # Map from standard file descriptor to the associated pipe |
4971 | + self.pipes = {} |
4972 | + pid, path, sock = self._spawn(executable, args, environment) |
4973 | + self._fifo_path = path |
4974 | + self.pid = pid |
4975 | + self.process_sock = sock |
4976 | + self._fifo_path = path |
4977 | + self._connectSpawnToReactor(reactor) |
4978 | + if self.proto is not None: |
4979 | + self.proto.makeConnection(self) |
4980 | + |
4981 | + def _sendMessageToService(self, message): |
4982 | + """Send a message to the Forking service and get the response""" |
4983 | + path = config.codehosting.forking_daemon_socket |
4984 | + client_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
4985 | + log.msg('Connecting to Forking Service @ socket: %s for %r' |
4986 | + % (path, message)) |
4987 | + try: |
4988 | + client_sock.connect(path) |
4989 | + client_sock.sendall(message) |
4990 | + # We define the requests to be no bigger than 1kB. (For now) |
4991 | + response = client_sock.recv(1024) |
4992 | + except socket.error, e: |
4993 | + # TODO: What exceptions should be raised? |
4994 | + # Raising the raw exception seems to kill the twisted reactor |
4995 | + # Note that if the connection is refused, we *could* just |
4996 | + # fall back on a regular 'spawnProcess' call. |
4997 | + log.err('Connection failed: %s' % (e,)) |
4998 | + raise |
4999 | + if response.startswith("FAILURE"): |
5000 | + raise RuntimeError('Failed to send message: %r' % (response,)) |
small update, I removed the "connect_ to_lpservice. py" script. It was old prototyping code, which isn't relevant anymore.