=== modified file 'c2dconfigutils/cu2dTrigger.py'
--- c2dconfigutils/cu2dTrigger.py	2013-05-13 18:19:16 +0000
+++ c2dconfigutils/cu2dTrigger.py	2013-10-08 21:15:00 +0000
@@ -59,21 +59,25 @@
                             'Useful when using -c or -l ' +
                             '(default: {}).'.format(
                                 self.DEFAULT_STACKS_CFG_PATH))
-        parser.add_argument('-c', '--trigger-ci',
-                            default=None,
-                            help='trigger ci job on the defined target branch')
-        parser.add_argument('-l', '--trigger-autolanding',
-                            default=None,
-                            help='Trigger autolanding on the defined' +
-                            ' target branch')
+        parser.add_argument('-b', '--branch',
+                            default=None,
+                            help='target source branch to search')
+        parser.add_argument('-c', '--trigger-ci', action='store_true',
+                            default=False,
+                            help='trigger ci jobs')
+        parser.add_argument('-l', '--trigger-autolanding', action='store_true',
+                            default=False,
+                            help='Trigger autolanding jobs')
         parser.add_argument('stackcfg', nargs='?',
                             help='Path to a configuration file for the stack',
                             default=None)
         args = parser.parse_args()
 
-        if not args.stackcfg and \
-                not args.trigger_ci and not args.trigger_autolanding:
-            parser.error('One of -c, -l or stackcfg must be defined')
+        if not args.stackcfg and not args.branch:
+            parser.error('Either -b/--branch or stackcfg must be defined')
+        if not args.trigger_ci and not args.trigger_autolanding:
+            parser.error('Must specify -c/--trigger-ci or '
+                         '-l/--trigger-autolanding or both')
         return args
 
     def generate_trigger(self, project_name, project_config, job_type):
@@ -98,7 +102,7 @@
                 'branch': branch,
                 'options': options}
 
-    def process_stack(self, stack):
+    def process_stack(self, stack, trigger_types):
         """ Generate a list of job triggers from the projects within a stack
 
         :param stack: dictionary with configuration of the stack
@@ -113,7 +117,7 @@
                 project_config = copy.deepcopy(stack['ci_default'])
                 dict_union(project_config, stack[section_name][project_name])
 
-                for job_type in ['ci', 'autolanding']:
+                for job_type in trigger_types:
                     if project_config.get(job_type + '_template', None):
                         trigger_list.append(self.generate_trigger(
                             project_name, project_config, job_type))
@@ -150,7 +154,8 @@
         else:
             return result
 
-    def trigger_stack(self, default_config, stackcfg, plugin_path):
+    def trigger_stack(self, default_config, stackcfg, plugin_path,
+                      trigger_types):
         lock_name = self._get_lock_name(stackcfg)
         stackcfg = load_stack_cfg(stackcfg, default_config)
         if not stackcfg:
@@ -158,7 +163,7 @@
             return 1
         trigger_list = []
         if stackcfg['projects']:
-            trigger_list = self.process_stack(stackcfg)
+            trigger_list = self.process_stack(stackcfg, trigger_types)
 
         for trigger in trigger_list:
             self.trigger_job(plugin_path, trigger, lock_name)
@@ -192,10 +197,12 @@
         return None
 
     def trigger_project(self, plugin_path, default_config, trigger_branch,
-                        stackcfg_dir, trigger_type):
+                        stackcfg_dir, trigger_types):
 
-        trigger = self.get_trigger_for_target(default_config, trigger_branch,
-                                              stackcfg_dir, trigger_type)
+        for job_type in trigger_types:
+            trigger = self.get_trigger_for_target(default_config,
+                                                  trigger_branch,
+                                                  stackcfg_dir, job_type)
         if not trigger:
             return 1
         self.trigger_job(plugin_path, trigger, lock_name='target-branch')
@@ -207,16 +214,19 @@
 
         set_logging(args.debug)
         default_config = load_default_cfg(default_config_path)
+        trigger_types = []
+        if args.trigger_autolanding:
+            trigger_types.append('autolanding')
+        if args.trigger_ci:
+            trigger_types.append('ci')
         if args.stackcfg:
             return self.trigger_stack(default_config,
                                       args.stackcfg,
-                                      args.plugin_path)
-        if args.trigger_autolanding:
-            trigger_type = 'autolanding'
-            trigger_branch = args.trigger_autolanding
-        else:
-            trigger_type = 'ci'
-            trigger_branch = args.trigger_ci
-        return self.trigger_project(args.plugin_path, default_config,
-                                    trigger_branch, args.stackcfg_dir,
-                                    trigger_type)
+                                      args.plugin_path,
+                                      trigger_types)
+        if args.branch and args.stackcfg_dir:
+            return self.trigger_project(args.plugin_path, default_config,
+                                        args.branch, args.stackcfg_dir,
+                                        trigger_types)
+        logging.error('Invalid arguments')
+        return -1

=== modified file 'tests/test_cu2dTrigger.py'
--- tests/test_cu2dTrigger.py	2013-05-15 16:41:46 +0000
+++ tests/test_cu2dTrigger.py	2013-10-08 21:15:00 +0000
@@ -107,9 +107,10 @@
 
     def setUp(self):
         self.jt = JobTrigger()
+        self.trigger_types = ['ci', 'autolanding']
 
     def test_process_stack(self):
-        ret = self.jt.process_stack(self.stack)
+        ret = self.jt.process_stack(self.stack, self.trigger_types)
         self.assertEqual(self.expected_result, ret)
 
 
@@ -189,6 +190,7 @@
         self.plugin_path = '/tmp'
         self.stack_cfg = {'projects': {'foo': {},
                                        'bar': {}}}
+        self.trigger_types = ['ci', 'autolanding']
         self.jt = JobTrigger()
         self.jt.process_stack = MagicMock(return_value=['trigger'])
         self.jt.trigger_job = MagicMock()
@@ -198,9 +200,10 @@
         """Verifiy jobs are triggered for a valid stack"""
         load_stack_cfg.return_value = self.stack_cfg
         ret = self.jt.trigger_stack(self.default_config, self.stack_cfg_name,
-                                    self.plugin_path)
+                                    self.plugin_path, self.trigger_types)
         load_stack_cfg.assert_called_with('stacks/head/foobar.cfg', {})
-        self.jt.process_stack.assert_called_with(self.stack_cfg)
+        self.jt.process_stack.assert_called_with(self.stack_cfg,
+                                                 self.trigger_types)
         self.jt.trigger_job.assert_called_with(self.plugin_path, 'trigger',
                                                'head-foobar.cfg')
         self.assertEqual(ret, 0)
@@ -210,7 +213,7 @@
         """Verify no jobs are triggered when stack file fails to load"""
         load_stack_cfg.return_value = False
         ret = self.jt.trigger_stack(self.default_config, self.stack_cfg_name,
-                                    self.plugin_path)
+                                    self.plugin_path, self.trigger_types)
         load_stack_cfg.assert_called_with('stacks/head/foobar.cfg', {})
         self.assertFalse(self.jt.process_stack.called)
         self.assertFalse(self.jt.trigger_job.called)
@@ -221,7 +224,7 @@
         """Verify no jobs are triggered when no project section"""
         load_stack_cfg.return_value = {}
         ret = self.jt.trigger_stack(self.default_config, self.stack_cfg_name,
-                                    self.plugin_path)
+                                    self.plugin_path, self.trigger_types)
         load_stack_cfg.assert_called_with('stacks/head/foobar.cfg', {})
         self.assertFalse(self.jt.process_stack.called)
         self.assertFalse(self.jt.trigger_job.called)
@@ -234,7 +237,7 @@
                                        'to_transition': {'foo': {},
                                                          'bar': {}}}
         ret = self.jt.trigger_stack(self.default_config, self.stack_cfg_name,
-                                    self.plugin_path)
+                                    self.plugin_path, self.trigger_types)
         load_stack_cfg.assert_called_with('stacks/head/foobar.cfg', {})
         self.assertFalse(self.jt.process_stack.called)
         self.assertFalse(self.jt.trigger_job.called)
@@ -246,9 +249,10 @@
         load_stack_cfg.return_value = self.stack_cfg
         self.jt.process_stack = MagicMock(return_value=[])
         ret = self.jt.trigger_stack(self.default_config, self.stack_cfg_name,
-                                    self.plugin_path)
+                                    self.plugin_path, self.trigger_types)
         load_stack_cfg.assert_called_with('stacks/head/foobar.cfg', {})
-        self.jt.process_stack.assert_called_with(self.stack_cfg)
+        self.jt.process_stack.assert_called_with(self.stack_cfg,
+                                                 self.trigger_types)
         self.assertFalse(self.jt.trigger_job.called)
         self.assertEqual(ret, 0)
 
@@ -256,15 +260,18 @@
 class TestTriggerBranch(TestWithScenarios, TestCase):
     scenarios = [
         ('ci',
-         {'trigger_type': 'ci',
+         {'trigger_type': ['ci'],
+          'job_type': 'ci',
           'fasttrack': True,
           'options': ['--trigger-ci']}),
         ('autolanding-fasttrack',
-         {'trigger_type': 'autolanding',
+         {'trigger_type': ['autolanding'],
+          'job_type': 'autolanding',
           'fasttrack': True,
           'options': ['--autoland', '--fasttrack']}),
         ('autolanding-nofasttrack',
-         {'trigger_type': 'autolanding',
+         {'trigger_type': ['autolanding'],
+          'job_type': 'autolanding',
           'fasttrack': False,
           'options': ['--autoland']}),
     ]
@@ -284,7 +291,7 @@
                                  self.trigger_type)
         jt.get_trigger_for_target.assert_called_once_with(
             self.default_config, self.target_branch,
-            self.stackcfg_dir, self.trigger_type)
+            self.stackcfg_dir, self.job_type)
         jt.trigger_job.assert_called_once_with(self.plugin_path, trigger,
                                                lock_name='target-branch')
         self.assertEqual(ret, 0)
@@ -322,9 +329,9 @@
         trigger = jt.get_trigger_for_target(self.default_config,
                                             self.target_branch,
                                             self.stackcfg_dir,
-                                            self.trigger_type)
+                                            self.job_type)
         expected_trigger = {
-            'name': 'branch-{}'.format(self.trigger_type),
+            'name': 'branch-{}'.format(self.job_type),
             'branch': self.target_branch,
             'options': self.options
         }
@@ -367,12 +374,38 @@
 
     @patch('c2dconfigutils.cu2dTrigger.load_default_cfg')
     def test_stackcfg_defined(self, load_default_cfg):
+        sys_argv = ['./command', '--trigger-ci', '../stacks/head/stack.cfg']
+        with patch('sys.argv', sys_argv):
+            jt = JobTrigger()
+            jt.trigger_stack = MagicMock()
+            jt('')
+            jt.trigger_stack.assert_called_once()
+
+    @patch('c2dconfigutils.cu2dTrigger.load_default_cfg')
+    def test_trigger_ci_and_autolanding_stack(self, load_default_cfg):
+        load_default_cfg.return_value = {}
+        sys_argv = ['./command', '--trigger-ci', '--trigger-autolanding',
+                    '../stacks/head/stack.cfg']
+        with patch('sys.argv', sys_argv):
+            jt = JobTrigger()
+            jt.trigger_stack = MagicMock()
+            jt('')
+            jt.trigger_stack.assert_called_once_with(
+                {}, '../stacks/head/stack.cfg',
+                JobTrigger.DEFAULT_PLUGIN_PATH,
+                ['autolanding', 'ci'])
+
+    @patch('c2dconfigutils.cu2dTrigger.load_default_cfg')
+    def test_missing_type(self, load_default_cfg):
         sys_argv = ['./command', '../stacks/head/stack.cfg']
         with patch('sys.argv', sys_argv):
             jt = JobTrigger()
             jt.trigger_stack = MagicMock()
-            jt('')
-            jt.trigger_stack.assert_called_once()
+            try:
+                jt('')
+            except SystemExit:
+                exception = True
+            self.assertTrue(exception)
 
     @patch('c2dconfigutils.cu2dTrigger.load_default_cfg')
     def test_trigger_autolanding(self, load_default_cfg):
@@ -381,13 +414,13 @@
         plugin_path = '/plugin/path'
         cfg_dir = '../stacks'
         sys_argv = ['./command', '--trigger-autolanding',
-                    branch, '-p', plugin_path, '-D', cfg_dir]
+                    '--branch', branch, '-p', plugin_path, '-D', cfg_dir]
         with patch('sys.argv', sys_argv):
             jt = JobTrigger()
             jt.trigger_project = MagicMock()
             jt('')
             jt.trigger_project.assert_called_once_with(plugin_path, {}, branch,
-                                                       cfg_dir, 'autolanding')
+                                                       cfg_dir, ['autolanding'])
 
     @patch('c2dconfigutils.cu2dTrigger.load_default_cfg')
     def test_trigger_ci(self, load_default_cfg):
@@ -396,10 +429,43 @@
         plugin_path = '/plugin/path'
         cfg_dir = '../stacks'
         sys_argv = ['./command', '--trigger-ci',
-                    branch, '-p', plugin_path, '-D', cfg_dir]
-        with patch('sys.argv', sys_argv):
-            jt = JobTrigger()
-            jt.trigger_project = MagicMock()
-            jt('')
-            jt.trigger_project.assert_called_once_with(plugin_path, {}, branch,
-                                                       cfg_dir, 'ci')
+                    '--branch', branch, '-p', plugin_path, '-D', cfg_dir]
+        with patch('sys.argv', sys_argv):
+            jt = JobTrigger()
+            jt.trigger_project = MagicMock()
+            jt('')
+            jt.trigger_project.assert_called_once_with(plugin_path, {}, branch,
+                                                       cfg_dir, ['ci'])
+
+    @patch('c2dconfigutils.cu2dTrigger.load_default_cfg')
+    def test_trigger_ci_and_autolanding_branch(self, load_default_cfg):
+        load_default_cfg.return_value = {}
+        branch = 'lp:branch'
+        plugin_path = '/plugin/path'
+        cfg_dir = '../stacks'
+        sys_argv = ['./command', '--trigger-ci', '--trigger-autolanding',
+                    '--branch', branch, '-p', plugin_path, '-D', cfg_dir]
+        with patch('sys.argv', sys_argv):
+            jt = JobTrigger()
+            jt.trigger_project = MagicMock()
+            jt('')
+            jt.trigger_project.assert_called_once_with(plugin_path, {}, branch,
+                                                       cfg_dir,
+                                                       ['autolanding', 'ci'])
+
+    @patch('c2dconfigutils.cu2dTrigger.load_default_cfg')
+    def test_trigger_ci_missing_branch(self, load_default_cfg):
+        load_default_cfg.return_value = {}
+        branch = 'lp:branch'
+        plugin_path = '/plugin/path'
+        cfg_dir = '../stacks'
+        sys_argv = ['./command', '--trigger-ci',
+                    '-p', plugin_path, '-D', cfg_dir]
+        with patch('sys.argv', sys_argv):
+            jt = JobTrigger()
+            jt.trigger_project = MagicMock()
+            try:
+                jt('')
+            except SystemExit:
+                exception = True
+            self.assertTrue(exception)

