Use $HOME/.config/depot_tools on linux for .cfg files
Or $XDG_CONFIG_HOME/.config/depot_tools if set
A followup CL can add support for win/macos.
Bug: b/345092320
Change-Id: I877baa4d7fd912b42cfcd88ad0aa347b700a89f2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/5604606
Commit-Queue: Richard Wang <richardwa@google.com>
Reviewed-by: Takuto Ikuta <tikuta@chromium.org>
Reviewed-by: Josip Sokcevic <sokcevic@chromium.org>
diff --git a/.gitignore b/.gitignore
index 22b610a..e2e03d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,7 +84,7 @@
*~
*.swp
-# Ignore the monitoring config. It is unique for each user.
+# Ignore win/mac monitoring config. It is unique for each depot_tools checkout.
/metrics.cfg
# Ignore the ninjalog upload config.
diff --git a/metrics.py b/metrics.py
index 627db84..0f0083d 100644
--- a/metrics.py
+++ b/metrics.py
@@ -17,9 +17,10 @@
import gclient_utils
import metrics_utils
import subprocess2
+import utils
DEPOT_TOOLS = os.path.dirname(os.path.abspath(__file__))
-CONFIG_FILE = os.path.join(DEPOT_TOOLS, 'metrics.cfg')
+CONFIG_FILE = utils.depot_tools_config_path('metrics.cfg')
UPLOAD_SCRIPT = os.path.join(DEPOT_TOOLS, 'upload_metrics.py')
DEFAULT_COUNTDOWN = 10
diff --git a/ninjalog_uploader_wrapper.py b/ninjalog_uploader_wrapper.py
index f17a053..563144e 100755
--- a/ninjalog_uploader_wrapper.py
+++ b/ninjalog_uploader_wrapper.py
@@ -11,10 +11,11 @@
import ninjalog_uploader
import subprocess2
+import utils
THIS_DIR = os.path.dirname(__file__)
UPLOADER = os.path.join(THIS_DIR, "ninjalog_uploader.py")
-CONFIG = os.path.join(THIS_DIR, "ninjalog.cfg")
+CONFIG = utils.depot_tools_config_path("ninjalog.cfg")
VERSION = 3
diff --git a/reclient_metrics.py b/reclient_metrics.py
index 934c45e..6d3771f 100755
--- a/reclient_metrics.py
+++ b/reclient_metrics.py
@@ -10,8 +10,10 @@
import subprocess
import sys
+import utils
+
THIS_DIR = os.path.dirname(__file__)
-CONFIG = os.path.join(THIS_DIR, 'reclient_metrics.cfg')
+CONFIG = utils.depot_tools_config_path('reclient_metrics.cfg')
VERSION = 1
diff --git a/tests/metrics_test.py b/tests/metrics_test.py
index 9e02628..c011ebc 100644
--- a/tests/metrics_test.py
+++ b/tests/metrics_test.py
@@ -14,6 +14,7 @@
import metrics
import metrics_utils
+import utils
# TODO: Should fix these warnings.
# pylint: disable=line-too-long
@@ -30,7 +31,7 @@
class MetricsCollectorTest(unittest.TestCase):
def setUp(self):
- self.config_file = os.path.join(ROOT_DIR, 'metrics.cfg')
+ self.config_file = utils.depot_tools_config_path('metrics.cfg')
self.collector = metrics.MetricsCollector()
# Keep track of the URL requests, file reads/writes and subprocess
diff --git a/tests/utils_test.py b/tests/utils_test.py
index 15cd3fe..5d0ca81 100755
--- a/tests/utils_test.py
+++ b/tests/utils_test.py
@@ -5,7 +5,9 @@
import logging
import os
+import shutil
import sys
+import tempfile
import unittest
from unittest import mock
@@ -41,6 +43,77 @@
self.assertEqual(version, 'unknown')
+class ConfigDirTest(unittest.TestCase):
+
+ @mock.patch('sys.platform', 'win')
+ def testWin(self):
+ self.assertEqual(DEPOT_TOOLS_ROOT, utils.depot_tools_config_dir())
+
+ @mock.patch('sys.platform', 'darwin')
+ def testMac(self):
+ self.assertEqual(DEPOT_TOOLS_ROOT, utils.depot_tools_config_dir())
+
+ @mock.patch('sys.platform', 'foo')
+ def testOther(self):
+ self.assertEqual(DEPOT_TOOLS_ROOT, utils.depot_tools_config_dir())
+
+ @mock.patch('sys.platform', 'linux')
+ @mock.patch.dict('os.environ', {})
+ def testLinuxDefault(self):
+ self.assertEqual(
+ os.path.join(os.path.expanduser('~/.config'), 'depot_tools'),
+ utils.depot_tools_config_dir())
+
+ @mock.patch('sys.platform', 'linux')
+ @mock.patch.dict('os.environ', {'XDG_CONFIG_HOME': '/my/home'})
+ def testLinuxCustom(self):
+ self.assertEqual(os.path.join('/my/home', 'depot_tools'),
+ utils.depot_tools_config_dir())
+
+
+class ConfigPathTest(unittest.TestCase):
+
+ def setUp(self):
+ self.temp_dir = tempfile.mkdtemp(prefix='utils_test')
+ self.config_dir = os.path.join(self.temp_dir, 'test_files')
+
+ self.isfile = mock.Mock()
+ self.move = mock.Mock()
+
+ mock.patch('os.path.isfile', self.isfile).start()
+ mock.patch('shutil.move', self.move).start()
+ mock.patch('utils.depot_tools_config_dir',
+ lambda: self.config_dir).start()
+
+ self.addCleanup(mock.patch.stopall)
+ self.addCleanup(shutil.rmtree, self.temp_dir)
+
+ def testCreatesConfigDir(self):
+ # Ensure "legacy path" doesn't exist so that nothing gets moved.
+ def EnsureLegacyPathNotExists(path):
+ return path != os.path.join(DEPOT_TOOLS_ROOT, 'metrics.cfg')
+
+ self.isfile.side_effect = EnsureLegacyPathNotExists
+
+ self.assertEqual(os.path.join(self.config_dir, 'metrics.cfg'),
+ utils.depot_tools_config_path('metrics.cfg'))
+ self.assertTrue(os.path.exists(self.config_dir))
+ self.move.assert_not_called()
+
+ def testMovesLegacy(self):
+ # Ensure "legacy path" exists so that it gets moved.
+ def EnsureLegacyPathExists(path):
+ return path == os.path.join(DEPOT_TOOLS_ROOT, 'metrics.cfg')
+
+ self.isfile.side_effect = EnsureLegacyPathExists
+
+ self.assertEqual(os.path.join(self.config_dir, 'metrics.cfg'),
+ utils.depot_tools_config_path('metrics.cfg'))
+ self.move.assert_called_once_with(
+ os.path.join(DEPOT_TOOLS_ROOT, 'metrics.cfg'),
+ os.path.join(self.config_dir, 'metrics.cfg'))
+
+
if __name__ == '__main__':
logging.basicConfig(
level=logging.DEBUG if '-v' in sys.argv else logging.ERROR)
diff --git a/utils.py b/utils.py
index a85d2f7..5500dbf 100644
--- a/utils.py
+++ b/utils.py
@@ -3,7 +3,12 @@
# found in the LICENSE file.
import os
+import pathlib
+import shutil
import subprocess
+import sys
+
+DEPOT_TOOLS_ROOT = os.path.dirname(os.path.abspath(__file__))
def depot_tools_version():
@@ -23,3 +28,29 @@
return 'recipes.cfg-%d' % (mtime)
except Exception:
return 'unknown'
+
+
+def depot_tools_config_dir():
+ # Use depot tools path for mac, windows.
+ if not sys.platform.startswith('linux'):
+ return DEPOT_TOOLS_ROOT
+
+ # Use $XDG_CONFIG_HOME/depot_tools or $HOME/.config/depot_tools on linux.
+ config_root = os.getenv('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))
+ return os.path.join(config_root, 'depot_tools')
+
+
+def depot_tools_config_path(file):
+ config_dir = depot_tools_config_dir()
+ expected_path = os.path.join(config_dir, file)
+
+ # Silently create config dir if necessary.
+ pathlib.Path(config_dir).mkdir(parents=True, exist_ok=True)
+
+ # Silently migrate cfg from legacy path if it exists.
+ if not os.path.isfile(expected_path):
+ legacy_path = os.path.join(DEPOT_TOOLS_ROOT, file)
+ if os.path.isfile(legacy_path):
+ shutil.move(legacy_path, expected_path)
+
+ return expected_path