# vim:ts=4:sw=4:et:
# Copyright 2015-present Facebook, Inc.
# Licensed under the Apache License, Version 2.0

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# no unicode literals
import os
import pywatchman

import WatchmanInstance
import WatchmanTestCase


@WatchmanTestCase.expand_matrix
class TestWatchProject(WatchmanTestCase.WatchmanTestCase):
    def runProjectTests(self, config, expect, touch_watchmanconfig=False):
        inst = WatchmanInstance.Instance(config=config)
        try:
            inst.start()
            client = self.getClient(inst)

            for touch, expect_watch, expect_rel, expect_pass in expect:
                # encode the test criteria in the dirname so that we can
                # figure out which test scenario failed more easily

                suffix = '-%s-%s-%s-%s' % (
                    touch, expect_watch, expect_rel, expect_pass
                )
                suffix = suffix.replace('/', 'Z')
                d = self.mkdtemp(suffix=suffix)

                dir_to_watch = os.path.join(d, 'a', 'b', 'c')
                os.makedirs(dir_to_watch, 0o777)
                self.touchRelative(d, touch)
                if touch_watchmanconfig:
                    self.touchRelative(d, '.watchmanconfig')

                if expect_watch:
                    expect_watch = os.path.join(d, expect_watch)
                else:
                    expect_watch = d

                if expect_pass:
                    res = client.query('watch-project', dir_to_watch)

                    self.assertEqual(
                        self.normAbsolutePath(os.path.join(d, expect_watch)),
                        self.normAbsolutePath(res['watch'])
                    )
                    if not expect_rel:
                        self.assertEqual(None, res.get('relative_path'))
                    else:
                        self.assertEqual(self.normRelativePath(expect_rel),
                                         self.normRelativePath(res.get('relative_path')))
                else:
                    with self.assertRaises(pywatchman.WatchmanError) as ctx:
                        client.query('watch-project', dir_to_watch)
                    self.assertIn(
                        (
                            'none of the files listed in global config ' +
                            'root_files are present in path `' + os.path.join(
                                d, 'a', 'b', 'c'
                            ) + ' or any of its parent directories'
                        ), str(ctx.exception)
                    )
        finally:
            inst.stop()

    def test_watchProject(self):
        expect = [
            ('a/b/c/.git', 'a/b/c', None, True),
            ("a/b/.hg", "a/b", "c", True),
            ("a/.foo", "a", "b/c", True),
            (".bar", None, "a/b/c", True),
            ("a/.bar", "a", "b/c", True),
            (".svn", "a/b/c", None, True),
            ("a/baz", "a/b/c", None, True),
        ]
        self.runProjectTests(
            {'root_files': ['.git', '.hg', '.foo', '.bar']}, expect
        )

    def test_watchProjectWatchmanConfig(self):
        expect = [
            ('a/b/c/.git', None, 'a/b/c', True),
            ("a/b/.hg", None, "a/b/c", True),
            ("a/.foo", None, "a/b/c", True),
            (".bar", None, "a/b/c", True),
            ("a/.bar", None, "a/b/c", True),
            (".svn", None, "a/b/c", True),
            ("a/baz", None, "a/b/c", True),
        ]
        self.runProjectTests(
            {'root_files': ['.git', '.hg', '.foo', '.bar']},
            expect,
            touch_watchmanconfig=True
        )

        def test_watchProjectEnforcing(self):
            config = {
                'root_files': ['.git', '.hg', '.foo', '.bar'],
                'enforce_root_files': True,
            }
            expect = [
                ("a/b/c/.git", "a/b/c", None, True),
                ("a/b/.hg", "a/b", "c", True),
                ("a/.foo", "a", "b/c", True),
                (".bar", None, "a/b/c", True),
                ("a/.bar", "a", "b/c", True),
                (".svn", None, None, False),
                ("a/baz", None, None, False),
            ]
            self.runProjectTests(config=config, expect=expect)

    def test_reUseNestedWatch(self):
        d = self.mkdtemp()
        abc = os.path.join(d, 'a', 'b', 'c')
        os.makedirs(abc, 0o777)
        self.touchRelative(abc, '.watchmanconfig')

        res = self.watchmanCommand('watch-project', d)
        self.assertEqual(d, self.normAbsolutePath(res['watch']))

        res = self.watchmanCommand('watch-project', abc)
        self.assertEqual(d, self.normAbsolutePath(res['watch']))
        self.assertEqual('a/b/c',
                         self.normRelativePath(res['relative_path']))

@@ -2542,16 +2542,17 @@
    ) + '
+%60
  or any 
@@ -2576,16 +2576,79 @@
 ectories
+. ' +%0A                            'root_files is defined by the
 '%0A      
@@ -3779,20 +3779,16 @@
      )%0A%0A
-    
     def 
@@ -3817,28 +3817,24 @@
 cing(self):%0A
-    
         conf
@@ -3844,36 +3844,32 @@
 = %7B%0A            
-    
 'root_files': %5B'
@@ -3911,20 +3911,16 @@
         
-   
- 
 'enforce
@@ -3951,25 +3951,18 @@
     
-    %7D%0A   
+%7D%0A
         
  exp
@@ -3953,25 +3953,24 @@
   %7D%0A        
- 
 expect = %5B%0A 
@@ -3960,36 +3960,32 @@
      expect = %5B%0A
-    
             (%22a/
@@ -4021,36 +4021,32 @@
 e),%0A            
-  
-  
 (%22a/b/.hg%22, %22a/b
@@ -4064,36 +4064,32 @@
 e),%0A            
-    
 (%22a/.foo%22, %22a%22, 
@@ -4106,36 +4106,32 @@
 e),%0A            
-  
-  
 (%22.bar%22, None, %22
@@ -4149,36 +4149,32 @@
 e),%0A            
-    
 (%22a/.bar%22, %22a%22, 
@@ -4191,36 +4191,32 @@
 e),%0A            
- 
-   
 (%22.svn%22, None, N
@@ -4220,36 +4220,32 @@
 , None, False),%0A
-    
             (%22a/
@@ -4274,34 +4274,26 @@
 e),%0A        
-    %5D%0A    
+%5D%0A
         self

Fix and re-enable a test that was disabled.