├── watchman ├── java │ ├── .nobuckcheck │ ├── sandcastle.ini │ ├── .gitignore │ ├── third-party │ │ ├── junit │ │ │ ├── README │ │ │ └── BUCK │ │ ├── mockito │ │ │ ├── README │ │ │ └── BUCK │ │ ├── objenesis │ │ │ ├── README │ │ │ └── BUCK │ │ ├── guava │ │ │ ├── README │ │ │ └── BUCK │ │ ├── jsr-305 │ │ │ ├── README │ │ │ └── BUCK │ │ ├── jna │ │ │ ├── README │ │ │ └── BUCK │ │ ├── nuprocess │ │ │ ├── README │ │ │ └── BUCK │ │ ├── hamcrest │ │ │ ├── README │ │ │ └── BUCK │ │ └── immutables │ │ │ ├── README │ │ │ └── BUCK │ ├── src │ │ └── com │ │ │ └── facebook │ │ │ └── watchman │ │ │ ├── Callback.java │ │ │ ├── WatchmanTransport.java │ │ │ ├── WatchmanTransportUnavailableException.java │ │ │ ├── Deserializer.java │ │ │ ├── WatchmanException.java │ │ │ └── bser │ │ │ └── BserConstants.java │ ├── README.md │ ├── .buckconfig │ └── BUCK ├── node │ ├── .flowconfig │ ├── bser │ │ ├── yarn.lock │ │ ├── CMakeLists.txt │ │ └── package.json │ ├── yarn.lock │ ├── package.json │ └── README.md ├── .projectid ├── integration │ ├── __init__.py │ ├── trig-cwd.py │ ├── site_spawn_fail.py │ ├── site_spawn.py │ ├── cat.py │ ├── trig.py │ ├── lib │ │ ├── __init__.py │ │ ├── Interrupt.py │ │ └── node.py │ ├── trigjson.py │ ├── touch.py │ ├── node_basic.js │ ├── test_invalid_watchmanconfig.py │ ├── eden │ │ ├── test_eden_takeover.py │ │ ├── test_eden_shutdown.py │ │ ├── test_eden_watch_root.py │ │ └── test_eden_unmount.py │ ├── test_command.py │ ├── test_watch_del_all.py │ ├── test_force_recrawl.py │ ├── test_clock.py │ ├── test_two_deep.py │ ├── test_info.py │ ├── test_big_file.py │ ├── test_remove_then_add.py │ ├── test_fork.py │ ├── test_auth.py │ ├── test_case_sensitive.py │ ├── test_kqueue_and_fsevents_recrawl.py │ ├── test_remove.py │ ├── test_perms.py │ ├── test_absroot.py │ ├── CMakeLists.txt │ ├── test_bulkstat.py │ └── test_log.py ├── python │ ├── tests │ │ └── __init__.py │ ├── .gitignore │ ├── MANIFEST.in │ ├── README.md │ ├── pywatchman │ │ ├── CMakeLists.txt │ │ ├── encoding.py │ │ └── capabilities.py │ ├── setup.py │ ├── publish-pypi.sh │ ├── CMakeLists.txt │ └── pyproject.toml ├── build │ ├── vagrant │ │ ├── .gitignore │ │ └── README.md │ └── package │ │ ├── watchman-deb │ │ ├── DEBIAN │ │ │ ├── control │ │ │ └── postinst │ │ └── Dockerfile │ │ ├── watchman-build │ │ └── Dockerfile │ │ ├── fedora-env │ │ └── Dockerfile │ │ ├── watchman.spec │ │ ├── ubuntu-env │ │ └── Dockerfile │ │ ├── make-packages.sh │ │ └── substcontrol.py ├── thirdparty │ ├── deelevate_binding │ │ ├── src │ │ │ └── lib.rs │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── CMakeLists.txt │ │ └── include │ │ │ └── deelevate.h │ ├── wildmatch │ │ ├── .dir-locals.el │ │ └── wildmatch.h │ ├── getopt │ │ └── GetOpt.h │ ├── libart │ │ ├── tests │ │ │ └── runner.c │ │ ├── README.md │ │ └── LICENSE │ └── jansson │ │ └── utf.h ├── rust │ ├── .gitignore │ ├── serde_bser │ │ ├── README.md │ │ ├── src │ │ │ ├── lib.rs │ │ │ ├── ser │ │ │ │ └── count_write.rs │ │ │ └── de │ │ │ │ ├── seq.rs │ │ │ │ └── reentrant.rs │ │ ├── Cargo.toml │ │ └── LICENSE │ └── watchman_client │ │ ├── Cargo.toml │ │ ├── LICENSE │ │ └── examples │ │ ├── subscribe.rs │ │ └── state.rs ├── ruby │ └── ruby-watchman │ │ ├── .rspec │ │ ├── Gemfile │ │ ├── .gitignore │ │ ├── ext │ │ └── ruby-watchman │ │ │ ├── depend │ │ │ ├── extconf.rb │ │ │ └── watchman.h │ │ ├── lib │ │ ├── ruby-watchman.rb │ │ └── ruby-watchman │ │ │ └── version.rb │ │ ├── spec │ │ └── spec_helper.rb │ │ ├── ruby-watchman.gemspec │ │ ├── LICENSE.txt │ │ └── Rakefile ├── test │ ├── run.sh │ ├── MercurialTest.cpp │ ├── LogTest.cpp │ ├── lib │ │ ├── FakeWatcher.h │ │ └── FakeWatcher.cpp │ └── RingBufferTest.cpp ├── cppclient │ ├── watchmanclient.pc.in │ └── WatchmanResponseError.cpp ├── SanityCheck.h ├── SignalHandler.h ├── listener.h ├── cli │ ├── CMakeLists.txt │ ├── src │ │ └── main.rs │ └── Cargo.toml ├── portability │ ├── GetOpt.h │ ├── WinError.h │ └── Backtrace.h ├── LogConfig.h ├── LogConfig.cpp ├── state.h ├── Shutdown.h ├── fuzz │ ├── BserDecode.cpp │ ├── JsonDecode.cpp │ └── PyBserDecode.cpp ├── .clang-tidy ├── ProcessUtil.h ├── fs │ ├── WindowsTime.h │ ├── Pipe.h │ ├── FSDetect.h │ ├── DirHandle.h │ └── WindowsTime.cpp ├── Constants.h ├── query │ ├── FileResult.cpp │ ├── Query.cpp │ ├── intcompare.h │ ├── QueryResult.cpp │ ├── GlobEscaping.h │ ├── QueryResult.h │ ├── GlobEscaping.cpp │ ├── GlobTree.h │ └── parse.h ├── GroupLookup.h ├── Connect.h ├── watcher │ └── Watcher.cpp ├── ClientContext.h ├── root │ ├── resolve.h │ ├── warnerr.h │ ├── test │ │ └── RootTest.cpp │ ├── watchlist.h │ └── reap.cpp ├── ProcessUtil.cpp ├── UserDir.h ├── FlagMap.h ├── sockname.cpp ├── Shutdown.cpp ├── FlagMap.cpp ├── Poison.h ├── watchman_preprocessor.h ├── Cookie.h ├── sockname.h ├── telemetry │ ├── LogEvent.cpp │ ├── WatchmanStats.cpp │ └── WatchmanStructuredLogger.h ├── GroupLookup.cpp ├── cmds │ └── heapprof.cpp ├── saved_state │ ├── SavedStateFactory.h │ └── SavedStateFactory.cpp ├── Hash.h ├── Connect.cpp ├── Poison.cpp ├── benchmarks │ └── string.cpp └── RingBuffer.h ├── website ├── static │ ├── .nojekyll │ └── img │ │ ├── logo.png │ │ ├── favicon.png │ │ └── watchman-social-card.png ├── .prettierignore ├── docs │ ├── cmd │ │ ├── _category_.json │ │ ├── log.md │ │ ├── shutdown-server.md │ │ ├── find.md │ │ ├── trigger-del.md │ │ ├── unsubscribe.md │ │ ├── trigger-list.md │ │ ├── watch-list.md │ │ ├── watch-del-all.md │ │ ├── get-sockname.md │ │ ├── list-capabilities.md │ │ ├── watch-del.md │ │ ├── log-level.md │ │ ├── clock.md │ │ └── get-config.md │ └── expr │ │ ├── _category_.json │ │ ├── exists.md │ │ ├── true.md │ │ ├── not.md │ │ ├── false.md │ │ ├── empty.md │ │ ├── type.md │ │ ├── anyof.md │ │ ├── allof.md │ │ ├── suffix.md │ │ ├── pcre.md │ │ ├── name.md │ │ └── size.md ├── .npmrc ├── .gitignore ├── babel.config.js ├── .stylelintrc.js ├── .prettierrc ├── README.md ├── src │ └── pages │ │ ├── styles.module.css │ │ ├── support.md │ │ └── index.module.css ├── sidebars.js └── package.json ├── .gitattributes ├── rustfmt.toml ├── autogen.cmd ├── install-system-packages.sh ├── run-tests.sh ├── clippy.toml ├── autogen.sh ├── LICENSE ├── README.markdown └── .gitignore /watchman/java/.nobuckcheck: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /watchman/node/.flowconfig: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/static/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /watchman/.projectid: -------------------------------------------------------------------------------- 1 | watchman 2 | -------------------------------------------------------------------------------- /watchman/integration/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /watchman/python/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /watchman/python/.gitignore: -------------------------------------------------------------------------------- 1 | instroot 2 | -------------------------------------------------------------------------------- /watchman/build/vagrant/.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant/ 2 | -------------------------------------------------------------------------------- /watchman/thirdparty/deelevate_binding/src/lib.rs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.png binary 3 | -------------------------------------------------------------------------------- /watchman/java/sandcastle.ini: -------------------------------------------------------------------------------- 1 | oncall = tmp_t21891137 2 | -------------------------------------------------------------------------------- /watchman/python/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include pywatchman/bser.h 2 | -------------------------------------------------------------------------------- /watchman/rust/.gitignore: -------------------------------------------------------------------------------- 1 | */Cargo.lock 2 | */target/ 3 | -------------------------------------------------------------------------------- /website/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .docusaurus 4 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --color 3 | -------------------------------------------------------------------------------- /website/docs/cmd/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Commands" 3 | } 4 | -------------------------------------------------------------------------------- /watchman/thirdparty/deelevate_binding/.gitignore: -------------------------------------------------------------------------------- 1 | .*.sw* 2 | /target 3 | Cargo.lock -------------------------------------------------------------------------------- /website/docs/expr/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Expression Terms" 3 | } 4 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /website/.npmrc: -------------------------------------------------------------------------------- 1 | # Stop people use npm instead of yarn by accident 2 | engine-strict = true 3 | -------------------------------------------------------------------------------- /website/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azanaia/watchman/HEAD/website/static/img/logo.png -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/.gitignore: -------------------------------------------------------------------------------- 1 | *.bundle 2 | *.gem 3 | *.so 4 | Gemfile.lock 5 | mkmf.log 6 | vendor 7 | -------------------------------------------------------------------------------- /website/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azanaia/watchman/HEAD/website/static/img/favicon.png -------------------------------------------------------------------------------- /watchman/java/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore files used by the Buck build system 2 | /.buckd/ 3 | /buck-cache/ 4 | /buck-out/ 5 | -------------------------------------------------------------------------------- /website/static/img/watchman-social-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azanaia/watchman/HEAD/website/static/img/watchman-social-card.png -------------------------------------------------------------------------------- /watchman/thirdparty/wildmatch/.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((c-mode . ((c-basic-offset . 8) 2 | (indent-tabs-mode . t) 3 | (tab-width . 8) 4 | (fill-column . 80)))) 5 | -------------------------------------------------------------------------------- /website/docs/expr/exists.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: exists 3 | category: Expression Terms 4 | --- 5 | 6 | Evaluates as true if the file exists 7 | 8 | "exists" 9 | ["exists"] 10 | -------------------------------------------------------------------------------- /website/docs/expr/true.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "true" 3 | section: Expression Terms 4 | --- 5 | 6 | The `true` expression always evaluates as true. 7 | 8 | "true" 9 | ["true"] 10 | -------------------------------------------------------------------------------- /watchman/python/README.md: -------------------------------------------------------------------------------- 1 | # Watchman client for Python 2 | 3 | This directory contains the Watchman client for Python. 4 | 5 | ## Build 6 | 7 | ```sh 8 | python -m build 9 | ``` 10 | -------------------------------------------------------------------------------- /website/docs/expr/not.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: not 3 | category: Expression Terms 4 | --- 5 | 6 | The `not` expression inverts the result of the subexpression argument: 7 | 8 | ["not", "empty"] 9 | -------------------------------------------------------------------------------- /website/docs/expr/false.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "false" 3 | section: Expression Terms 4 | --- 5 | 6 | The `false` expression always evaluates as false. 7 | 8 | "false" 9 | ["false"] 10 | -------------------------------------------------------------------------------- /website/docs/cmd/log.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: log 3 | category: Commands 4 | --- 5 | 6 | Generates a log line in the watchman log. 7 | 8 | ```bash 9 | $ watchman log debug "log this please" 10 | ``` 11 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/ext/ruby-watchman/depend: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. All Rights Reserved. 2 | 3 | CFLAGS += -Wall -Wextra -Wno-unused-parameter 4 | 5 | watchman.o: watchman.c watchman.h 6 | -------------------------------------------------------------------------------- /watchman/java/third-party/junit/README: -------------------------------------------------------------------------------- 1 | README for Junit 2 | 3 | URL: https://github.com/junit-team/junit4 4 | Downloaded From: http://central.maven.org/maven2/junit/junit/4.12/junit-4.12.jar 5 | License: Apache 2.0 6 | -------------------------------------------------------------------------------- /watchman/java/third-party/mockito/README: -------------------------------------------------------------------------------- 1 | README for Mockito 2 | 3 | URL: http://mockito.org/ 4 | Downloaded From: http://central.maven.org/maven2/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5.jar 5 | License: MIT 6 | -------------------------------------------------------------------------------- /watchman/java/third-party/objenesis/README: -------------------------------------------------------------------------------- 1 | README for Objenesis 2 | 3 | URL: http://objenesis.org/ 4 | Downloaded From: http://central.maven.org/maven2/org/objenesis/objenesis/1.3/objenesis-1.3.jar 5 | License: MIT 6 | -------------------------------------------------------------------------------- /watchman/java/third-party/guava/README: -------------------------------------------------------------------------------- 1 | README for Guava 2 | 3 | URL: https://github.com/google/guava 4 | Downloaded From: http://central.maven.org/maven2/com/google/guava/guava/19.0/guava-19.0.jar 5 | License: Apache 2.0 6 | -------------------------------------------------------------------------------- /website/docs/expr/empty.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: empty 3 | category: Expression Terms 4 | --- 5 | 6 | Evaluates as true if the file exists, has size 0 and is a regular file or 7 | directory. 8 | 9 | "empty" 10 | ["empty"] 11 | -------------------------------------------------------------------------------- /watchman/java/third-party/jsr-305/README: -------------------------------------------------------------------------------- 1 | README for JSR-305 2 | 3 | URL: http://findbugs.sourceforge.net/ 4 | Downloaded From: http://central.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.1/jsr305-3.0.1.jar 5 | License: Apache 2.0 6 | -------------------------------------------------------------------------------- /watchman/thirdparty/deelevate_binding/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "deelevate_binding" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["staticlib", "lib"] 8 | 9 | [dependencies] 10 | deelevate = "0.1" 11 | -------------------------------------------------------------------------------- /watchman/build/package/watchman-deb/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: watchman 2 | Version: %VERSION% 3 | Architecture: amd64 4 | Maintainer: Meta Platforms, Inc. 5 | Standards-Version: 4.6.1.1 6 | Description: A file watching service 7 | Depends: %DEPENDS% 8 | -------------------------------------------------------------------------------- /watchman/java/third-party/jna/README: -------------------------------------------------------------------------------- 1 | README for JNA 2 | 3 | URL: https://github.com/java-native-access/jna 4 | Downloaded From: http://central.maven.org/maven2/net/java/dev/jna/jna/4.2.0/jna-4.2.0.jar 5 | License: Apache 2.0 and LPGL 2.1 dual license 6 | -------------------------------------------------------------------------------- /watchman/java/third-party/nuprocess/README: -------------------------------------------------------------------------------- 1 | README for NuProcess 2 | 3 | URL: https://github.com/brettwooldridge/NuProcess 4 | Downloaded from: http://central.maven.org/maven2/com/zaxxer/nuprocess/1.1.0/nuprocess-1.1.0.jar 5 | License: Apache 2.0 license 6 | -------------------------------------------------------------------------------- /website/docs/cmd/shutdown-server.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: shutdown-server 3 | category: Commands 4 | --- 5 | 6 | This command causes your watchman service to exit with a normal status code. 7 | 8 | ```bash 9 | $ watchman shutdown-server 10 | ``` 11 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/lib/ruby-watchman.rb: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | require 'ruby-watchman/ext' 7 | -------------------------------------------------------------------------------- /watchman/build/package/watchman-build/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BASE_IMAGE 2 | FROM $BASE_IMAGE 3 | 4 | WORKDIR /watchman 5 | RUN ./install-system-packages.sh 6 | 7 | # Clean up the temporary build artifacts so the image is smaller. 8 | RUN ./autogen.sh && rm -rf /tmp/fbcode_builder_getdeps* 9 | -------------------------------------------------------------------------------- /watchman/rust/serde_bser/README.md: -------------------------------------------------------------------------------- 1 | # Work in Progress! 2 | 3 | This is work in progress on a BSER implementation that is compatible 4 | with serde. It is not complete! If you're reading this and want 5 | to help move it closer to completion, please don't be afraid to 6 | work up a pull request! 7 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/lib/ruby-watchman/version.rb: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | module RubyWatchman 7 | VERSION = '0.0.2' 8 | end 9 | -------------------------------------------------------------------------------- /watchman/test/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # This is a dumb wrapper to satisfy the buck_sh_test rule 8 | exec "$@" 9 | -------------------------------------------------------------------------------- /website/docs/cmd/find.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: find 3 | category: Commands 4 | --- 5 | 6 | Finds all files that match the optional list of patterns under the specified 7 | dir. If no patterns were specified, all files are returned. 8 | 9 | ```bash 10 | $ watchman find /path/to/dir [patterns] 11 | ``` 12 | -------------------------------------------------------------------------------- /watchman/cppclient/watchmanclient.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: watchmanclient 7 | Description: Watchman C++ client library 8 | Requires: libfolly 9 | Version: 0 10 | Libs: -L${libdir} -lwatchmanclient 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Get help on options with `rustfmt --help=config` 2 | # Please keep these in alphabetical order. 3 | edition = "2021" 4 | format_code_in_doc_comments = true 5 | group_imports = "StdExternalCrate" 6 | imports_granularity = "Item" 7 | merge_derives = false 8 | use_field_init_shorthand = true 9 | version = "Two" 10 | -------------------------------------------------------------------------------- /watchman/SanityCheck.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | namespace watchman { 11 | void startSanityCheckThread(); 12 | } 13 | -------------------------------------------------------------------------------- /watchman/java/third-party/hamcrest/README: -------------------------------------------------------------------------------- 1 | README for Hamcrest-2 2 | 3 | URL: http://hamcrest.org/ 4 | Downloaded From: 5 | * http://central.maven.org/maven2/org/hamcrest/hamcrest-junit/2.0.0.0/hamcrest-junit-2.0.0.0.jar 6 | * http://central.maven.org/maven2/org/hamcrest/java-hamcrest/2.0.0.0/java-hamcrest-2.0.0.0.jar 7 | License: BSD 8 | -------------------------------------------------------------------------------- /website/docs/cmd/trigger-del.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: trigger-del 3 | category: Commands 4 | --- 5 | 6 | Deletes a named trigger from the list of registered triggers. This disables and 7 | removes the trigger from both the in-memory and the saved state lists. 8 | 9 | ```bash 10 | $ watchman trigger-del /root triggername 11 | ``` 12 | -------------------------------------------------------------------------------- /watchman/node/bser/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | node-int64@^0.4.0: 6 | version "0.4.0" 7 | resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" 8 | integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= 9 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /watchman/SignalHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | namespace watchman { 11 | 12 | void setup_signal_handlers(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | module.exports = { 9 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 10 | }; 11 | -------------------------------------------------------------------------------- /watchman/build/package/watchman-deb/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BASE_IMAGE 2 | FROM $BASE_IMAGE 3 | 4 | WORKDIR /watchman 5 | 6 | ENV BUILT="/watchman/built" 7 | 8 | ADD make-deb.sh /watchman/build/make-deb.sh 9 | ADD DEBIAN /watchman/watchman/build/package/DEBIAN 10 | 11 | # TODO: make a debugsymbols package 12 | RUN strip built/bin/* 13 | 14 | RUN /watchman/build/make-deb.sh 15 | -------------------------------------------------------------------------------- /watchman/listener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "watchman/fs/FileDescriptor.h" 11 | 12 | void w_listener_prep_inetd(); 13 | bool w_start_listener(); 14 | -------------------------------------------------------------------------------- /autogen.cmd: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | python3 build/fbcode_builder/getdeps.py build --src-dir=. watchman "--project-install-prefix=watchman:%userprofile%" --scratch-path "C:\open\scratch" 4 | 5 | python3 build/fbcode_builder/getdeps.py fixup-dyn-deps --src-dir=. watchman built "--project-install-prefix=watchman:%userprofile%" --final-install-prefix "%userprofile%" --scratch-path "C:\open\scratch" -------------------------------------------------------------------------------- /install-system-packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # vim:ts=2:sw=2:et: 3 | # Copyright (c) Meta Platforms, Inc. and affiliates. 4 | # 5 | # This source code is licensed under the MIT license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | set -x 9 | python3 "$(dirname "$0")/build/fbcode_builder/getdeps.py" install-system-deps --recursive watchman 10 | -------------------------------------------------------------------------------- /run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # vim:ts=2:sw=2:et: 3 | # Copyright (c) Meta Platforms, Inc. and affiliates. 4 | # 5 | # This source code is licensed under the MIT license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | set -x 9 | python3 "$(dirname "$0")/build/fbcode_builder/getdeps.py" test --allow-system-packages --no-testpilot watchman 10 | -------------------------------------------------------------------------------- /website/.stylelintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | module.exports = { 9 | plugins: ['stylelint-copyright'], 10 | rules: { 11 | 'docusaurus/copyright-header': true, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /website/docs/cmd/unsubscribe.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: unsubscribe 3 | category: Commands 4 | --- 5 | 6 | Available starting in version 1.6 7 | 8 | Cancels a named subscription against the specified root. The server side will no 9 | longer generate subscription packets for the specified subscription. 10 | 11 | ```json 12 | ["unsubscribe", "/path/to/root", "mysubscriptionname"] 13 | ``` 14 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) 7 | $LOAD_PATH.unshift File.expand_path('../../ext', __FILE__) 8 | require 'ruby-watchman' 9 | -------------------------------------------------------------------------------- /watchman/java/third-party/guava/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "guava-jar", 3 | out = "guava-19.0.jar", 4 | sha1 = "6ce200f6b23222af3d8abb6b6459e6c44f4bb0e9", 5 | url = "http://central.maven.org/maven2/com/google/guava/guava/19.0/guava-19.0.jar", 6 | ) 7 | 8 | prebuilt_jar( 9 | name = "guava", 10 | binary_jar = ":guava-jar", 11 | visibility = ["PUBLIC"], 12 | ) 13 | -------------------------------------------------------------------------------- /watchman/integration/trig-cwd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | 8 | import os 9 | 10 | 11 | os.environ["PWD"] = os.getcwd() 12 | 13 | for k, v in os.environ.items(): 14 | print("%s=%s" % (k, v)) 15 | -------------------------------------------------------------------------------- /watchman/cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | if (IS_FB_BUILD) 7 | rust_executable(watchmanctl FEATURES fb) 8 | else() 9 | rust_executable(watchmanctl) 10 | endif() 11 | 12 | install_rust_executable(watchmanctl) 13 | -------------------------------------------------------------------------------- /watchman/java/third-party/objenesis/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "objenesis-jar", 3 | out = "objenesis-1.3.jar", 4 | sha1 = "dc13ae4faca6df981fc7aeb5a522d9db446d5d50", 5 | url = "http://central.maven.org/maven2/org/objenesis/objenesis/1.3/objenesis-1.3.jar", 6 | ) 7 | 8 | prebuilt_jar( 9 | name = "objenesis", 10 | binary_jar = ":objenesis-jar", 11 | visibility = ["PUBLIC"], 12 | ) 13 | -------------------------------------------------------------------------------- /watchman/build/package/fedora-env/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG FEDORA_VERSION 2 | FROM fedora:$FEDORA_VERSION 3 | 4 | RUN dnf install -y gcc g++ git openssl-devel rpmdevtools 5 | 6 | RUN curl https://sh.rustup.rs -sSf | sh -s -- -y 7 | ENV PATH="/root/.cargo/bin:${PATH}" 8 | 9 | # Avoid build output from Watchman's build getting buffered in large 10 | # chunks, which makes debugging progress tough. 11 | ENV PYTHONUNBUFFERED=1 12 | -------------------------------------------------------------------------------- /watchman/portability/GetOpt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #ifdef _WIN32 11 | 12 | #include "watchman/thirdparty/getopt/GetOpt.h" // @manual 13 | 14 | #else 15 | 16 | #include 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /website/docs/cmd/trigger-list.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: trigger-list 3 | category: Commands 4 | --- 5 | 6 | Returns the set of registered triggers associated with a root directory. 7 | 8 | ```bash 9 | $ watchman trigger-list /root 10 | ``` 11 | 12 | Note that the format of the output from `trigger-list` changed in Watchman 13 | version 2.9.7. It will now output a list of trigger objects as defined by the 14 | `trigger` command. 15 | -------------------------------------------------------------------------------- /watchman/LogConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace watchman::logging { 13 | 14 | extern int log_level; 15 | extern std::string log_name; 16 | 17 | } // namespace watchman::logging 18 | -------------------------------------------------------------------------------- /watchman/java/third-party/jsr-305/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "jsr-305-jar", 3 | out = "jsr305.jar", 4 | sha1 = "f7be08ec23c21485b9b5a1cf1654c2ec8c58168d", 5 | url = "http://central.maven.org/maven2/com/google/code/findbugs/jsr305/3.0.1/jsr305-3.0.1.jar", 6 | ) 7 | 8 | prebuilt_jar( 9 | name = "jsr-305", 10 | binary_jar = ":jsr-305-jar", 11 | visibility = [ 12 | "PUBLIC", 13 | ], 14 | ) 15 | -------------------------------------------------------------------------------- /website/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSameLine": true, 4 | "bracketSpacing": false, 5 | "printWidth": 80, 6 | "proseWrap": "never", 7 | "singleQuote": true, 8 | "trailingComma": "all", 9 | "overrides": [ 10 | { 11 | "files": "*.md", 12 | "options": { 13 | "proseWrap": "always", 14 | "embeddedLanguageFormatting": "off" 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /website/docs/cmd/watch-list.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: watch-list 3 | category: Commands 4 | --- 5 | 6 | Returns a list of watched dirs. 7 | 8 | From the command line: 9 | 10 | ```bash 11 | $ watchman watch-list 12 | ``` 13 | 14 | JSON: 15 | 16 | ```json 17 | ["watch-list"] 18 | ``` 19 | 20 | Result: 21 | 22 | ```json 23 | { 24 | "version": "1.9", 25 | "roots": [ 26 | "/home/wez/watchman" 27 | ] 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /watchman/integration/site_spawn_fail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # This is a simple script that fails to spawn a process in the background 8 | 9 | import sys 10 | 11 | 12 | print("failed to start") 13 | sys.stdout.flush() 14 | sys.exit(1) 15 | -------------------------------------------------------------------------------- /watchman/java/third-party/immutables/README: -------------------------------------------------------------------------------- 1 | README for Immutables 2 | 3 | URL: https://github.com/immutables/immutables 4 | Downloaded From: 5 | * http://central.maven.org/maven2/org/immutables/generator/2.1.5/generator-2.1.5.jar 6 | * http://central.maven.org/maven2/org/immutables/value-processor/2.1.5/value-processor-2.1.5.jar 7 | * http://central.maven.org/maven2/org/immutables/value/2.1.5/value-2.1.5.jar 8 | 9 | License: Apache 2.0 10 | -------------------------------------------------------------------------------- /watchman/python/pywatchman/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | add_fb_python_library(pywatchman 7 | SOURCES 8 | __init__.py 9 | capabilities.py 10 | encoding.py 11 | load.py 12 | pybser.py 13 | windows.py 14 | NAMESPACE pywatchman 15 | ) 16 | -------------------------------------------------------------------------------- /watchman/java/src/com/facebook/watchman/Callback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.facebook.watchman; 9 | 10 | import java.util.Map; 11 | 12 | public interface Callback { 13 | void call(Map message) throws Exception; 14 | } 15 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | too-many-lines-threshold = 200 2 | await-holding-invalid-types = [ 3 | { path = "tracing::span::Entered", reason = "`Entered` is not aware when a function is suspended: https://docs.rs/tracing/latest/tracing/struct.Span.html#in-asynchronous-code" }, 4 | { path = "tracing::span::EnteredSpan", reason = "`EnteredSpan` is not aware when a function is suspended: https://docs.rs/tracing/latest/tracing/struct.Span.html#in-asynchronous-code" }, 5 | ] 6 | -------------------------------------------------------------------------------- /watchman/portability/WinError.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #ifdef _WIN32 13 | 14 | // DWORD = uint32_t 15 | 16 | const char* win32_strerror(uint32_t err); 17 | int map_win32_err(uint32_t err); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /watchman/LogConfig.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/LogConfig.h" 9 | #include "watchman/Logging.h" 10 | 11 | namespace watchman::logging { 12 | 13 | int log_level = LogLevel::ERR; 14 | std::string log_name; 15 | 16 | } // namespace watchman::logging 17 | -------------------------------------------------------------------------------- /watchman/java/third-party/nuprocess/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "nuprocess-jar", 3 | out = "nuprocess-1.1.0.jar", 4 | sha1 = "9479382344b61b36dd3ca1ec1b10aaa91295d632", 5 | url = "http://central.maven.org/maven2/com/zaxxer/nuprocess/1.1.0/nuprocess-1.1.0.jar", 6 | ) 7 | 8 | prebuilt_jar( 9 | name = "nuprocess", 10 | binary_jar = ":nuprocess-jar", 11 | visibility = ["PUBLIC"], 12 | deps = [ 13 | "//third-party/jna:jna", 14 | ], 15 | ) 16 | -------------------------------------------------------------------------------- /watchman/state.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "watchman/thirdparty/jansson/jansson.h" 11 | 12 | void w_state_shutdown(); 13 | void w_state_save(); 14 | bool w_state_load(); 15 | 16 | bool w_root_save_state(json_ref& state); 17 | bool w_root_load_state(const json_ref& state); 18 | -------------------------------------------------------------------------------- /watchman/rust/serde_bser/src/lib.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #![cfg_attr(fbcode_build, deny(warnings, rust_2018_idioms))] 9 | 10 | pub mod bytestring; 11 | pub mod de; 12 | mod errors; 13 | mod header; 14 | pub mod ser; 15 | pub mod value; 16 | 17 | pub use crate::de::from_reader; 18 | pub use crate::de::from_slice; 19 | -------------------------------------------------------------------------------- /watchman/java/README.md: -------------------------------------------------------------------------------- 1 | Watchman Java Library 2 | ==== 3 | 4 | This provides Java bindings to the Watchman service. 5 | 6 | Building 7 | === 8 | 9 | Make sure that you have [buck](https://buckbuild.com/) installed. In this 10 | folder, run: 11 | 12 | ``` 13 | buck fetch :watchman 14 | buck build :watchman 15 | ``` 16 | 17 | The resulting JAR file is found in: 18 | `buck-out/gen/watchman.jar' 19 | 20 | To run the tests: 21 | 22 | ``` 23 | buck fetch :watchman-tests 24 | buck test :watchman-lib 25 | ``` 26 | 27 | -------------------------------------------------------------------------------- /watchman/Shutdown.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace watchman { 13 | class Event; 14 | } 15 | 16 | using watchman_event = watchman::Event; 17 | 18 | bool w_is_stopping(); 19 | void w_request_shutdown(); 20 | void w_push_listener_thread_event(std::shared_ptr event); 21 | -------------------------------------------------------------------------------- /watchman/node/bser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | add_fb_python_unittest(bser_js 7 | SOURCES 8 | test_bser.py 9 | 10 | DEPENDS 11 | integration_lib 12 | 13 | WORKING_DIRECTORY 14 | ${CMAKE_BINARY_DIR} 15 | 16 | ENV 17 | "YARN_PATH=${YARN}" 18 | "NODE_BIN=${NODE}" 19 | "WATCHMAN_SRC_DIR=${CMAKE_SOURCE_DIR}/watchman" 20 | ) 21 | -------------------------------------------------------------------------------- /website/docs/expr/type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: type 3 | category: Expression Terms 4 | --- 5 | 6 | Evaluates as true if the type of the file matches that specified by the second 7 | argument; this matches regular files: 8 | 9 | ["type", "f"] 10 | 11 | Possible types are: 12 | 13 | - **b**: block special file 14 | - **c**: character special file 15 | - **d**: directory 16 | - **f**: regular file 17 | - **p**: named pipe (fifo) 18 | - **l**: symbolic link 19 | - **s**: socket 20 | - **D**: Solaris Door 21 | - **?**: An unknown file type 22 | -------------------------------------------------------------------------------- /watchman/java/third-party/mockito/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "mockito-jar", 3 | out = "mockito-core-1.9.5.jar", 4 | sha1 = "c3264abeea62c4d2f367e21484fbb40c7e256393", 5 | url = "http://central.maven.org/maven2/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5.jar", 6 | ) 7 | 8 | prebuilt_jar( 9 | name = "mockito", 10 | binary_jar = ":mockito-jar", 11 | visibility = ["PUBLIC"], 12 | deps = [ 13 | "//third-party/hamcrest:hamcrest-2", 14 | "//third-party/objenesis:objenesis", 15 | ], 16 | ) 17 | -------------------------------------------------------------------------------- /watchman/integration/site_spawn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # This is a simple script that spawns a watchman process in the background 8 | 9 | import os 10 | import subprocess 11 | import sys 12 | 13 | 14 | args = sys.argv[1:] 15 | args.insert(0, os.environ.get("WATCHMAN_BINARY", "watchman")) 16 | args.insert(1, "--foreground") 17 | subprocess.Popen(args) 18 | -------------------------------------------------------------------------------- /watchman/java/src/com/facebook/watchman/WatchmanTransport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.facebook.watchman; 9 | 10 | import java.io.Closeable; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | 14 | public interface WatchmanTransport extends Closeable { 15 | InputStream getInputStream(); 16 | OutputStream getOutputStream(); 17 | } 18 | -------------------------------------------------------------------------------- /watchman/fuzz/BserDecode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/bser.h" 9 | 10 | extern "C" int LLVMFuzzerTestOneInput(void const* data, size_t size) { 11 | auto* d = reinterpret_cast(data); 12 | try { 13 | bunser(d, d + size); 14 | } catch (const BserParseError&) { 15 | // Caught parse errors are okay. 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /watchman/integration/cat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | 8 | import sys 9 | 10 | 11 | args = sys.argv[1:] 12 | 13 | if not args: 14 | args = ["-"] 15 | 16 | for file_name in args: 17 | if file_name == "-": 18 | sys.stdout.write(sys.stdin.read()) 19 | else: 20 | with open(file_name, "rb") as f: 21 | sys.stdout.write(f.read()) 22 | -------------------------------------------------------------------------------- /watchman/integration/trig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | 8 | import sys 9 | import time 10 | 11 | 12 | log_file_name = sys.argv[1] 13 | 14 | args = sys.argv[2:] 15 | 16 | with open(log_file_name, "a") as f: 17 | for arg in args: 18 | f.write("%s " % time.time()) 19 | f.write(arg) 20 | f.write("\n") 21 | 22 | print("WOOT from trig.sh") 23 | -------------------------------------------------------------------------------- /watchman/java/third-party/junit/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "junit-download", 3 | out = "junit-4.12.jar", 4 | sha1 = "2973d150c0dc1fefe998f834810d68f278ea58ec", 5 | url = "http://central.maven.org/maven2/junit/junit/4.12/junit-4.12.jar", 6 | ) 7 | 8 | prebuilt_jar( 9 | name = "junit-jar", 10 | binary_jar = ":junit-download", 11 | ) 12 | 13 | java_library( 14 | name = "junit", 15 | visibility = ["PUBLIC"], 16 | exported_deps = [ 17 | ":junit-jar", 18 | "//third-party/hamcrest:hamcrest-2", 19 | ], 20 | ) 21 | -------------------------------------------------------------------------------- /watchman/integration/lib/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # pyre-unsafe 7 | 8 | import os.path 9 | 10 | if "WATCHMAN_INTEGRATION_HELPERS" in os.environ: 11 | HELPER_ROOT = os.path.join(os.environ["WATCHMAN_INTEGRATION_HELPERS"]) 12 | else: 13 | WATCHMAN_SRC_DIR: str = os.environ.get("WATCHMAN_SRC_DIR", os.getcwd()) 14 | HELPER_ROOT = os.path.join(WATCHMAN_SRC_DIR, "integration") 15 | -------------------------------------------------------------------------------- /watchman/.clang-tidy: -------------------------------------------------------------------------------- 1 | # NOTE there must be no spaces before the '-', so put the comma after. 2 | # When making changes, be sure to verify the output of the following command to ensure 3 | # the desired checks are enabled (run from the directory containing a .clang-tidy file): 4 | # `clang-tidy -- --dump-config` 5 | # NOTE: Please don't disable inheritance from the parent to make sure that common checks get propagated. 6 | --- 7 | InheritParentConfig: true 8 | Checks: ' 9 | facebook-hte-PortabilityInclude-gflags/gflags.h, 10 | -facebook-hte-RelativeInclude, 11 | ' 12 | ... 13 | -------------------------------------------------------------------------------- /watchman/ProcessUtil.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace facebook::eden { 13 | class ProcessInfoHandle; 14 | } 15 | 16 | namespace watchman { 17 | 18 | using ProcessInfoHandle = facebook::eden::ProcessInfoHandle; 19 | 20 | ProcessInfoHandle lookupProcessInfo(pid_t pid); 21 | 22 | } // namespace watchman 23 | -------------------------------------------------------------------------------- /watchman/build/package/watchman-deb/DEBIAN/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | case "$1" in 4 | configure) 5 | mkdir -p /usr/local/var/run/watchman 6 | chmod 2777 /usr/local/var/run/watchman 7 | ;; 8 | 9 | abort-upgrade|abort-remove|abort-deconfigure) 10 | ;; 11 | 12 | *) 13 | echo "postinst called with unknown argument \`$1'" >&2 14 | exit 1 15 | ;; 16 | esac 17 | 18 | # dh_installdeb will replace this with shell code automatically 19 | # generated by other debhelper scripts. 20 | 21 | #DEBHELPER# 22 | 23 | exit 0 24 | -------------------------------------------------------------------------------- /watchman/integration/trigjson.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | 8 | import sys 9 | 10 | 11 | log_file_name = sys.argv[1] 12 | 13 | # Copy json from stdin to the log file 14 | with open(log_file_name, "a") as f: 15 | print("trigjson.py: Copying STDIN to %s" % log_file_name) 16 | json_in = sys.stdin.read() 17 | print("stdin: %s" % json_in) 18 | f.write(json_in) 19 | -------------------------------------------------------------------------------- /website/docs/expr/anyof.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: anyof 3 | category: Expression Terms 4 | --- 5 | 6 | The `anyof` expression term evaluates as true if any of the grouped expressions 7 | also evaluated as true. The following expression matches files whose name ends 8 | with either `.txt` or `.md`: 9 | 10 | ["anyof", ["match", "*.txt"], ["match", "*.md"]] 11 | 12 | Each array element after the term name is evaluated as an expression of its own: 13 | 14 | ["anyof", expr1, expr2, ... exprN] 15 | 16 | Evaluation of the subexpressions stops at the first one that returns true. 17 | -------------------------------------------------------------------------------- /watchman/build/package/watchman.spec: -------------------------------------------------------------------------------- 1 | Name: watchman 2 | Version: %{version} 3 | Release: 1%{?dist} 4 | License: MIT 5 | Summary: A file watching service 6 | URL: https://facebook.github.io/watchman/ 7 | 8 | %description 9 | 10 | A file watching service. 11 | 12 | %build 13 | 14 | %install 15 | mkdir -p %{buildroot}%{prefix} 16 | cp -rvp %{image}/* %{buildroot}%{prefix} 17 | 18 | %files 19 | %defattr(-, root, root, -) 20 | %{prefix}bin/watchman 21 | %{prefix}bin/watchmanctl 22 | 23 | %post 24 | 25 | mkdir -p %{prefix}/var/run/watchman 26 | chmod 2777 %{prefix}/var/run/watchman 27 | -------------------------------------------------------------------------------- /watchman/fs/WindowsTime.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | namespace watchman { 14 | 15 | #ifdef _WIN32 16 | 17 | void FILETIME_to_timespec(const FILETIME* ft, timespec* ts); 18 | void FILETIME_LARGE_INTEGER_to_timespec(LARGE_INTEGER ft, timespec* ts); 19 | 20 | #endif 21 | 22 | } // namespace watchman 23 | -------------------------------------------------------------------------------- /watchman/integration/touch.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # Portable simple implementation of `touch` 7 | 8 | 9 | import errno 10 | import os 11 | import sys 12 | 13 | 14 | fname = sys.argv[1] 15 | 16 | try: 17 | os.utime(fname, None) 18 | except OSError as e: 19 | if e.errno == errno.ENOENT: 20 | with open(fname, "a"): 21 | os.utime(fname, None) 22 | else: 23 | raise 24 | -------------------------------------------------------------------------------- /watchman/Constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace watchman { 13 | 14 | inline constexpr uint32_t kIoBufSize = 1024 * 1024; 15 | inline constexpr uint32_t kBatchLimit = 16 * 1024; 16 | 17 | } // namespace watchman 18 | 19 | #define WATCHMAN_IO_BUF_SIZE (::watchman::kIoBufSize) 20 | #define WATCHMAN_BATCH_LIMIT (::watchman::kBatchLimit) 21 | -------------------------------------------------------------------------------- /watchman/query/FileResult.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/query/FileResult.h" 9 | 10 | namespace watchman { 11 | 12 | FileResult::~FileResult() {} 13 | 14 | std::optional FileResult::dtype() { 15 | auto statInfo = stat(); 16 | if (!statInfo.has_value()) { 17 | return std::nullopt; 18 | } 19 | return statInfo->dtype(); 20 | } 21 | 22 | } // namespace watchman 23 | -------------------------------------------------------------------------------- /website/docs/expr/allof.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: allof 3 | category: Expression Terms 4 | --- 5 | 6 | The `allof` expression term evaluates as true if all of the grouped expressions 7 | also evaluated as true. For example, this expression matches only files whose 8 | name ends with `.txt` and that are not empty files: 9 | 10 | ["allof", ["match", "*.txt"], ["not", "empty"]] 11 | 12 | Each array element after the term name is evaluated as an expression of its own: 13 | 14 | ["allof", expr1, expr2, ... exprN] 15 | 16 | Evaluation of the subexpressions stops at the first one that returns false. 17 | -------------------------------------------------------------------------------- /watchman/GroupLookup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #ifndef _WIN32 11 | 12 | #include 13 | /** 14 | * Gets the group struct for the given group name. The return value may point 15 | * to a static area so it should be used immediately and not passed to free(3). 16 | * 17 | * Returns null on failure. 18 | */ 19 | const struct group* w_get_group(const char* group_name); 20 | #endif // _WIN32 21 | -------------------------------------------------------------------------------- /website/docs/cmd/watch-del-all.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: watch-del-all 3 | category: Commands 4 | --- 5 | 6 | Available since version 3.1.1. 7 | 8 | Removes all watches and associated triggers. 9 | 10 | From the command line: 11 | 12 | ```bash 13 | $ watchman watch-del-all 14 | ``` 15 | 16 | JSON: 17 | 18 | ```json 19 | ["watch-del-all"] 20 | ``` 21 | 22 | Analogous to the `watch-del` this command will remove all watches and associated 23 | triggers from the running process, and the state file ( unless watchman service 24 | was started with 25 | [--no-save-state server option](cli-options.md#server-options)). 26 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | -------------------------------------------------------------------------------- /watchman/fuzz/JsonDecode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/thirdparty/jansson/jansson.h" 9 | 10 | extern "C" int LLVMFuzzerTestOneInput(void const* data, size_t size) { 11 | json_error_t err{}; 12 | auto* d = reinterpret_cast(data); 13 | try { 14 | json_loadb(d, size, JSON_DECODE_ANY, &err); 15 | } catch (std::exception&) { 16 | // Catchable exceptions are okay. 17 | } 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /watchman/Connect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include "watchman/Result.h" 12 | 13 | namespace watchman { 14 | class Stream; 15 | } 16 | 17 | /** 18 | * Connect to a running Watchman instance via unix socket or a named pipe. 19 | * 20 | * Returns a connected stream, or an errno upon error. 21 | */ 22 | watchman::ResultErrno> w_stm_connect( 23 | int timeoutms); 24 | -------------------------------------------------------------------------------- /watchman/test/MercurialTest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/scm/Mercurial.h" 9 | #include 10 | 11 | using namespace std::chrono; 12 | 13 | TEST(Mercurial, convertCommitDate) { 14 | auto date = watchman::Mercurial::convertCommitDate("1529420960.025200"); 15 | auto result = duration_cast(date.time_since_epoch()).count(); 16 | auto expected = 1529420960; 17 | EXPECT_EQ(result, expected); 18 | } 19 | -------------------------------------------------------------------------------- /watchman/watcher/Watcher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/watcher/Watcher.h" 9 | 10 | namespace watchman { 11 | 12 | Watcher::Watcher(const char* name, unsigned flags) : name(name), flags(flags) {} 13 | 14 | Watcher::~Watcher() {} 15 | 16 | bool Watcher::startWatchFile(watchman_file*) { 17 | return true; 18 | } 19 | 20 | bool Watcher::start(const std::shared_ptr&) { 21 | return true; 22 | } 23 | 24 | } // namespace watchman 25 | -------------------------------------------------------------------------------- /watchman/build/vagrant/README.md: -------------------------------------------------------------------------------- 1 | # Vagrant VMs for Validating Watchman Builds 2 | 3 | Watchman uses GitHub Actions for CI, but sometimes it's useful to have 4 | reproducible, bare environments representative of where people 5 | typically attempt to build Watchman. 6 | 7 | This Vagrantfile provides some provisioned VMs with the minimal set of 8 | dependencies required to build and run Watchman. 9 | 10 | None of the VMs will autostart, so they must be specified explicitly 11 | to `vagrant up`. When running `vagrant up` or `vagrant provision`, 12 | ensure the `WATCHMAN_SOURCE` environment variable contains a path to 13 | the Watchman source directory. 14 | -------------------------------------------------------------------------------- /watchman/node/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | bser@^2.1.0: 6 | version "2.1.1" 7 | resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" 8 | integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== 9 | dependencies: 10 | node-int64 "^0.4.0" 11 | 12 | node-int64@^0.4.0: 13 | version "0.4.0" 14 | resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" 15 | integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= 16 | -------------------------------------------------------------------------------- /watchman/ClientContext.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "eden/common/utils/ProcessInfoCache.h" 11 | 12 | namespace watchman { 13 | /** 14 | * A struct containing information about the client that is triggering some 15 | * action in watchman. Currently used for telemetry. 16 | */ 17 | struct ClientContext { 18 | pid_t clientPid; 19 | std::optional clientInfo; 20 | }; 21 | 22 | } // namespace watchman 23 | -------------------------------------------------------------------------------- /website/docs/cmd/get-sockname.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: get-sockname 3 | category: Commands 4 | --- 5 | 6 | If you're integrating against watchman using the unix socket and either the JSON 7 | or BSER protocol, you may need to discover the correct socket path. Rather than 8 | hard-coding the path or replicating the logic discussed in 9 | [Command Line](cli-options.md), you can simply execute the CLI to determine the 10 | path. This has the side effect of spawning the service for your user if it was 11 | not already running--bonus! 12 | 13 | ```bash 14 | $ watchman get-sockname 15 | { 16 | "version": "2.5", 17 | "sockname": "/tmp/.watchman.wez" 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /watchman/root/resolve.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace watchman { 13 | class Root; 14 | } 15 | 16 | std::shared_ptr w_root_resolve( 17 | const char* path, 18 | bool auto_watch); 19 | 20 | std::shared_ptr w_root_resolve_for_client_mode( 21 | const char* filename); 22 | 23 | std::shared_ptr 24 | root_resolve(const char* filename, bool auto_watch, bool* created); 25 | -------------------------------------------------------------------------------- /watchman/query/Query.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/query/Query.h" 9 | #include "watchman/query/GlobTree.h" 10 | #include "watchman/query/QueryExpr.h" 11 | 12 | namespace watchman { 13 | 14 | Query::~Query() = default; 15 | 16 | bool Query::isFieldRequested(w_string_piece name) const { 17 | for (auto& f : fieldList) { 18 | if (f->name.piece() == name) { 19 | return true; 20 | } 21 | } 22 | return false; 23 | } 24 | 25 | } // namespace watchman 26 | -------------------------------------------------------------------------------- /watchman/root/warnerr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include "watchman/watchman_string.h" 13 | 14 | struct watchman_dir; 15 | 16 | namespace watchman { 17 | 18 | class Root; 19 | 20 | void handle_open_errno( 21 | Root& root, 22 | w_string_piece dirName, 23 | std::chrono::system_clock::time_point now, 24 | const char* syscall, 25 | const std::error_code& err); 26 | 27 | } // namespace watchman 28 | -------------------------------------------------------------------------------- /watchman/cppclient/WatchmanResponseError.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "WatchmanConnection.h" 9 | 10 | namespace watchman { 11 | 12 | using namespace folly; 13 | 14 | static const dynamic kError("error"); 15 | 16 | WatchmanResponseError::WatchmanResponseError(const folly::dynamic& response) 17 | : WatchmanError(response[kError].c_str()), response_(response) {} 18 | 19 | const folly::dynamic& WatchmanResponseError::getResponse() const { 20 | return response_; 21 | } 22 | } // namespace watchman 23 | -------------------------------------------------------------------------------- /watchman/ProcessUtil.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/ProcessUtil.h" 9 | 10 | #include "eden/common/utils/ProcessInfoCache.h" 11 | 12 | namespace watchman { 13 | 14 | using namespace facebook::eden; 15 | 16 | namespace { 17 | ProcessInfoCache& getProcessInfoCache() { 18 | static auto* pic = new ProcessInfoCache; 19 | return *pic; 20 | } 21 | } // namespace 22 | 23 | ProcessInfoHandle lookupProcessInfo(pid_t pid) { 24 | return getProcessInfoCache().lookup(pid); 25 | } 26 | 27 | } // namespace watchman 28 | -------------------------------------------------------------------------------- /watchman/portability/Backtrace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #ifdef _WIN32 11 | 12 | #define HAVE_BACKTRACE 13 | #define HAVE_BACKTRACE_SYMBOLS 14 | 15 | extern "C" { 16 | 17 | typedef struct _EXCEPTION_POINTERS* LPEXCEPTION_POINTERS; 18 | 19 | size_t backtrace(void** frames, size_t n_frames); 20 | char** backtrace_symbols(void** array, size_t n_frames); 21 | size_t backtrace_from_exception( 22 | LPEXCEPTION_POINTERS exception, 23 | void** frames, 24 | size_t n_frames); 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /watchman/java/src/com/facebook/watchman/WatchmanTransportUnavailableException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.facebook.watchman; 9 | 10 | public class WatchmanTransportUnavailableException extends Exception { 11 | 12 | public WatchmanTransportUnavailableException() { 13 | super(); 14 | } 15 | 16 | public WatchmanTransportUnavailableException(String message) { 17 | super(message); 18 | } 19 | 20 | public WatchmanTransportUnavailableException(String message, Throwable cause) { 21 | super(message, cause); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /watchman/java/src/com/facebook/watchman/Deserializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.facebook.watchman; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.util.Map; 13 | 14 | public interface Deserializer { 15 | 16 | /** 17 | * Reads the next object from the InputSteram, blocking until it becomes available. 18 | * @param stream the stream to read from 19 | * @return a deserialized object, read from the stream 20 | */ 21 | Map deserialize(InputStream stream) throws IOException; 22 | } 23 | -------------------------------------------------------------------------------- /watchman/thirdparty/deelevate_binding/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT WIN32) 2 | message( FATAL_ERROR "deelevate cannot be used on platforms other than Windows" ) 3 | endif() 4 | 5 | find_package(Python COMPONENTS Interpreter) 6 | 7 | rust_executable(deelevate BINARY_NAME eledo-pty-bridge) 8 | 9 | rust_static_library(rust_deelevate CRATE deelevate) 10 | install_rust_static_library( 11 | rust_deelevate 12 | INSTALL_DIR thirdparty 13 | ) 14 | 15 | add_library(libdeelevate INTERFACE) 16 | target_include_directories(libdeelevate INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) 17 | target_link_libraries( 18 | libdeelevate 19 | INTERFACE 20 | rust_deelevate 21 | userenv.lib 22 | bcrypt.lib 23 | ntdll.lib 24 | ) 25 | 26 | install( 27 | TARGETS libdeelevate 28 | ) 29 | -------------------------------------------------------------------------------- /watchman/thirdparty/wildmatch/wildmatch.h: -------------------------------------------------------------------------------- 1 | /* Copyright 1986-present, Rich $alz, Wayne Davison, and Duy Nguyen. 2 | * Licensed under the Apache License, Version 2.0 */ 3 | 4 | #ifndef WILDMATCH_H 5 | #define WILDMATCH_H 6 | 7 | #define WM_CASEFOLD 1 8 | #define WM_PATHNAME 2 9 | #define WM_PERIOD 4 10 | #define WM_NOESCAPE 8 11 | 12 | #define WM_ABORT_MALFORMED 2 13 | #define WM_NOMATCH 1 14 | #define WM_MATCH 0 15 | #define WM_ABORT_ALL -1 16 | #define WM_ABORT_TO_STARSTAR -2 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | struct wildopts; 23 | 24 | int wildmatch(const char *pattern, const char *text, 25 | unsigned int flags, 26 | struct wildopts *wo); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /website/docs/cmd/list-capabilities.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: list-capabilities 3 | category: Commands 4 | --- 5 | 6 | _Since 3.8._ 7 | 8 | This command returns the full list of supported [capabilities](capabilities.md) 9 | offered by the watchman server. The intention is that client applications will 10 | use the [expanded version command](version.md) to check compatibility rather 11 | than interrogating the full list. 12 | 13 | Here's some example output. The actual capabilities list is in unspecified order 14 | and is much longer than is reproduced here: 15 | 16 | ```bash 17 | $ watchman list-capabilities 18 | { 19 | "version": "3.8.0", 20 | "capabilities": [ 21 | "field-mode", 22 | "term-allof", 23 | "cmd-trigger" 24 | ] 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /watchman/UserDir.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace watchman { 13 | 14 | /** 15 | * Returns the username of the current user. 16 | */ 17 | std::string computeUserName(); 18 | 19 | /** 20 | * Returns a cached reference to the current user's temporary directory. 21 | */ 22 | const std::string& getTemporaryDirectory(); 23 | 24 | /** 25 | * Computes the Watchman state directory corresponding to the given user name. 26 | */ 27 | std::string computeWatchmanStateDirectory(const std::string& user); 28 | 29 | } // namespace watchman 30 | -------------------------------------------------------------------------------- /watchman/integration/lib/Interrupt.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # pyre-unsafe 7 | 8 | 9 | interrupted = False 10 | 11 | 12 | def wasInterrupted() -> bool: 13 | global interrupted 14 | return interrupted 15 | 16 | 17 | def setInterrupted() -> None: 18 | global interrupted 19 | interrupted = True 20 | 21 | 22 | def checkInterrupt() -> None: 23 | """ 24 | If an interrupt was detected, raise it now. 25 | We use this to defer interrupt processing until we're 26 | in the right place to handle it. 27 | """ 28 | if wasInterrupted(): 29 | raise KeyboardInterrupt() 30 | -------------------------------------------------------------------------------- /watchman/java/third-party/jna/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "jna-jar", 3 | out = "jna-4.2.0.jar", 4 | sha1 = "812b976ed15bb1b0b3fc059fae927b0f76b39585", 5 | url = "http://central.maven.org/maven2/net/java/dev/jna/jna/4.2.0/jna-4.2.0.jar", 6 | ) 7 | 8 | remote_file( 9 | name = "jna-platform-jar", 10 | out = "jna-platform-4.2.0.jar", 11 | sha1 = "4a04d34615d534f273f7b8bd30d75304efe4ab04", 12 | url = "http://central.maven.org/maven2/net/java/dev/jna/jna-platform/4.2.0/jna-platform-4.2.0.jar", 13 | ) 14 | 15 | prebuilt_jar( 16 | name = "jna", 17 | binary_jar = ":jna-jar", 18 | visibility = ["PUBLIC"], 19 | ) 20 | 21 | prebuilt_jar( 22 | name = "jna-platform", 23 | binary_jar = ":jna-platform-jar", 24 | visibility = ["PUBLIC"], 25 | ) 26 | -------------------------------------------------------------------------------- /watchman/FlagMap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | struct flag_map { 14 | uint32_t value; 15 | const char* label; 16 | }; 17 | 18 | /** 19 | * Given a flag map in `fmap`, and a set of flags in `flags`, 20 | * expand the flag bits that are set in `flags` into the corresponding 21 | * labels in `fmap` and print the result into the caller provided 22 | * buffer `buf` of size `len` bytes. 23 | */ 24 | void w_expand_flags( 25 | const struct flag_map* fmap, 26 | uint32_t flags, 27 | char* buf, 28 | size_t len); 29 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/ext/ruby-watchman/extconf.rb: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | require 'mkmf' 7 | 8 | def header(item) 9 | unless find_header(item) 10 | puts "couldn't find #{item} (required)" 11 | exit 1 12 | end 13 | end 14 | 15 | # mandatory headers 16 | header('ruby.h') 17 | header('fcntl.h') 18 | header('sys/errno.h') 19 | header('sys/socket.h') 20 | 21 | # variable headers 22 | have_header('ruby/st.h') # >= 1.9; sets HAVE_RUBY_ST_H 23 | have_header('st.h') # 1.8; sets HAVE_ST_H 24 | 25 | RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC'] 26 | 27 | create_makefile('ruby-watchman/ext') 28 | -------------------------------------------------------------------------------- /watchman/java/.buckconfig: -------------------------------------------------------------------------------- 1 | [java] 2 | src_roots = java, test 3 | source_level = 6 4 | target_level = 6 5 | jar_spool_mode = direct_to_jar 6 | 7 | [project] 8 | ide = intellij 9 | allow_symlinks = forbid 10 | watchman_query_timeout_ms = 1000 11 | initial_targets = //watchman 12 | ignore = .git, .buckd, .idea, buck-out, buck-cache, \ 13 | **/.DS_Store, **/**.orig, \ 14 | *___jb_bak___*, \ 15 | *___jb_tmp___*, \ 16 | *___jb_old___*, \ 17 | **/*.swp, \ 18 | **/*~ 19 | parallel_parsing = true 20 | 21 | [build] 22 | thread_core_ratio = 0.75 23 | thread_core_ratio_min_threads = 1 24 | 25 | [cache] 26 | mode = dir 27 | dir = buck-cache 28 | dir_max_size = 100MB 29 | 30 | [test] 31 | timeout = 60000 32 | 33 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # vim:ts=2:sw=2:et: 3 | # Copyright (c) Meta Platforms, Inc. and affiliates. 4 | # 5 | # This source code is licensed under the MIT license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | cd "$(dirname "$0")" 9 | 10 | set -x 11 | PREFIX=${PREFIX:-/usr/local} 12 | python3 build/fbcode_builder/getdeps.py build \ 13 | --allow-system-packages \ 14 | --src-dir=. \ 15 | "--project-install-prefix=watchman:$PREFIX" \ 16 | watchman 17 | python3 build/fbcode_builder/getdeps.py fixup-dyn-deps \ 18 | --allow-system-packages \ 19 | --src-dir=. \ 20 | "--project-install-prefix=watchman:$PREFIX" \ 21 | --final-install-prefix "$PREFIX" \ 22 | watchman built 23 | 24 | find built -ls 25 | -------------------------------------------------------------------------------- /website/docs/cmd/watch-del.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: watch-del 3 | category: Commands 4 | --- 5 | 6 | Removes a watch and any associated triggers. 7 | 8 | From the command line: 9 | 10 | ```bash 11 | $ watchman watch-del /path/to/dir 12 | ``` 13 | 14 | JSON: 15 | 16 | ```json 17 | ["watch-del", "/path/to/dir"] 18 | ``` 19 | 20 | The removed watch and any associated triggers will be removed from the state 21 | file and will not be automatically watched if/when watchman is restarted. 22 | 23 | However, if `--no-save-state` was used to start the watchman service, the watch 24 | and triggers will be deleted from the running process but no changes will be 25 | made to the state file. If this same directory is listed in the state file, the 26 | watch will be re-established if/when the service is restarted. 27 | -------------------------------------------------------------------------------- /watchman/python/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # vim:ts=4:sw=4:et: 3 | # Copyright (c) Meta Platforms, Inc. and affiliates. 4 | # 5 | # This source code is licensed under the MIT license found in the 6 | # LICENSE file in the root directory of this source tree. 7 | 8 | 9 | from setuptools import Extension, setup 10 | 11 | setup( 12 | packages=["pywatchman"], 13 | ext_modules=[ 14 | Extension( 15 | "pywatchman.bser", 16 | sources=["pywatchman/bsermodule.c", "pywatchman/bser.c"], 17 | include_dirs=["./pywatchman"], 18 | ) 19 | ], 20 | zip_safe=True, 21 | scripts=[ 22 | "bin/watchman-make", 23 | "bin/watchman-wait", 24 | "bin/watchman-replicate-subscription", 25 | ], 26 | test_suite="tests", 27 | ) 28 | -------------------------------------------------------------------------------- /watchman/root/test/RootTest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/root/Root.h" 9 | #include 10 | #include 11 | 12 | namespace { 13 | 14 | using namespace watchman; 15 | 16 | TEST(RootTest, IgnoreSet_includes_ignore_vcs_if_no_ignore_dirs) { 17 | json_ref val = json_object({ 18 | {"ignore_vcs", json_array({w_string_to_json(".hg")})}, 19 | }); 20 | Configuration config(val); 21 | 22 | auto ignores = computeIgnoreSet(w_string{"root"}, config); 23 | EXPECT_TRUE(ignores.isIgnoreVCS(w_string{"root/.hg"})); 24 | } 25 | 26 | } // namespace 27 | -------------------------------------------------------------------------------- /watchman/integration/node_basic.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | var assert = require('assert'); 9 | var watchman = require('fb-watchman'); 10 | var client = new watchman.Client(); 11 | 12 | var t = setTimeout(function () { 13 | assert.fail('timeout', null, 'timed out running test'); 14 | }, 10000); 15 | 16 | client.on('error', function(error) { 17 | assert.fail(error, null, 'unexpected error'); 18 | }); 19 | 20 | client.command(['version'], function(error, resp) { 21 | assert.equal(error, null, 'no errors'); 22 | console.log('Talking to watchman version', resp.version); 23 | client.end(); 24 | clearTimeout(t); 25 | }); 26 | 27 | -------------------------------------------------------------------------------- /watchman/query/intcompare.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "watchman/thirdparty/jansson/jansson.h" 11 | 12 | namespace watchman { 13 | 14 | enum w_query_icmp_op { 15 | W_QUERY_ICMP_EQ, 16 | W_QUERY_ICMP_NE, 17 | W_QUERY_ICMP_GT, 18 | W_QUERY_ICMP_GE, 19 | W_QUERY_ICMP_LT, 20 | W_QUERY_ICMP_LE, 21 | }; 22 | struct w_query_int_compare { 23 | enum w_query_icmp_op op; 24 | json_int_t operand; 25 | }; 26 | void parse_int_compare(const json_ref& term, struct w_query_int_compare* comp); 27 | bool eval_int_compare(json_int_t ival, struct w_query_int_compare* comp); 28 | 29 | } // namespace watchman 30 | -------------------------------------------------------------------------------- /watchman/sockname.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/Options.h" 9 | 10 | using namespace watchman; 11 | 12 | namespace watchman { 13 | 14 | bool disable_unix_socket = false; 15 | bool disable_named_pipe = false; 16 | 17 | const char* get_sock_name_legacy() { 18 | #ifdef _WIN32 19 | return flags.named_pipe_path.c_str(); 20 | #else 21 | return flags.unix_sock_name.c_str(); 22 | #endif 23 | } 24 | 25 | const std::string& get_unix_sock_name() { 26 | return flags.unix_sock_name; 27 | } 28 | 29 | const std::string& get_named_pipe_sock_path() { 30 | return flags.named_pipe_path; 31 | } 32 | 33 | } // namespace watchman 34 | -------------------------------------------------------------------------------- /watchman/query/QueryResult.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/query/QueryResult.h" 9 | 10 | namespace watchman { 11 | 12 | json_ref RenderResult::toJson() && { 13 | auto arr = json_array(std::move(results)); 14 | if (templ) { 15 | json_array_set_template_new(arr, std::move(*templ)); 16 | } 17 | return arr; 18 | } 19 | 20 | json_ref QueryDebugInfo::render() const { 21 | std::vector arr; 22 | for (auto& fn : cookieFileNames) { 23 | arr.push_back(w_string_to_json(fn)); 24 | } 25 | return json_object({ 26 | {"cookie_files", json_array(std::move(arr))}, 27 | }); 28 | } 29 | 30 | } // namespace watchman 31 | -------------------------------------------------------------------------------- /watchman/rust/serde_bser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde_bser" 3 | version = "0.4.0" 4 | authors = ["Rain ", "Wez Furlong"] 5 | edition = "2021" 6 | description = "Implements the Watchman BSER encoding for serde. https://facebook.github.io/watchman/docs/bser.html" 7 | documentation = "https://docs.rs/serde_bser" 8 | repository = "https://github.com/facebook/watchman/" 9 | license = "MIT" 10 | 11 | [dependencies] 12 | anyhow = "1.0" 13 | byteorder = "1.3" 14 | bytes = { version = "1.0", features = ["serde"] } 15 | serde = { version = "1.0.126", features = ["derive", "rc"] } 16 | serde_bytes = "0.11" 17 | thiserror = "1.0" 18 | 19 | [dev-dependencies] 20 | maplit = "1.0" 21 | 22 | [features] 23 | debug_bytes = [] 24 | default = [] 25 | 26 | [lints.rust] 27 | unexpected_cfgs = { level = "warn", check-cfg = ["cfg(fbcode_build)"] } 28 | -------------------------------------------------------------------------------- /watchman/node/bser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bser", 3 | "version": "2.1.1", 4 | "description": "JavaScript implementation of the BSER Binary Serialization", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "node test/bser.js" 11 | }, 12 | "files": [ 13 | "index.js" 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/facebook/watchman" 18 | }, 19 | "keywords": [ 20 | "bser", 21 | "binary", 22 | "protocol" 23 | ], 24 | "author": "Wez Furlong (http://wezfurlong.org)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/facebook/watchman/issues" 28 | }, 29 | "homepage": "https://facebook.github.io/watchman/docs/bser.html", 30 | "dependencies": { 31 | "node-int64": "^0.4.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /watchman/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fb-watchman", 3 | "version": "2.0.2", 4 | "description": "Bindings for the Watchman file watching service", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git@github.com:facebook/watchman.git" 9 | }, 10 | "keywords": [ 11 | "facebook", 12 | "watchman", 13 | "file", 14 | "watch", 15 | "watcher", 16 | "watching", 17 | "fs.watch", 18 | "fswatcher", 19 | "fs", 20 | "glob", 21 | "utility" 22 | ], 23 | "author": "Wez Furlong (http://wezfurlong.org)", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/facebook/watchman/issues" 27 | }, 28 | "homepage": "https://facebook.github.io/watchman/", 29 | "files": [ 30 | "index.js" 31 | ], 32 | "dependencies": { 33 | "bser": "2.1.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /watchman/integration/test_invalid_watchmanconfig.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | 12 | from watchman.integration.lib import WatchmanTestCase 13 | 14 | 15 | @WatchmanTestCase.expand_matrix 16 | class TestWatchmanConfigValid(WatchmanTestCase.WatchmanTestCase): 17 | def test_trailing_comma(self) -> None: 18 | root = self.mkdtemp() 19 | with open(os.path.join(root, ".watchmanconfig"), "w") as f: 20 | f.write('{"ignore_dirs":["foo",],}') 21 | 22 | with self.assertRaises(Exception) as ctx: 23 | self.watchmanCommand("watch", root) 24 | self.assertIn("failed to parse json", str(ctx.exception)) 25 | -------------------------------------------------------------------------------- /watchman/fs/Pipe.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | #include "watchman/fs/FileDescriptor.h" 10 | 11 | namespace watchman { 12 | 13 | // Convenience for constructing a Pipe 14 | class Pipe { 15 | public: 16 | FileDescriptor read; 17 | FileDescriptor write; 18 | 19 | // Construct a pipe, setting the close-on-exec and 20 | // non-blocking bits. 21 | Pipe(); 22 | }; 23 | 24 | // Convenience for constructing a SocketPair 25 | class SocketPair { 26 | public: 27 | FileDescriptor read; 28 | FileDescriptor write; 29 | 30 | // Construct a socketpair, setting the close-on-exec and 31 | // non-blocking bits. 32 | SocketPair(); 33 | }; 34 | 35 | } // namespace watchman 36 | -------------------------------------------------------------------------------- /watchman/query/GlobEscaping.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "watchman/watchman_string.h" 11 | 12 | namespace watchman { 13 | /** 14 | * Convert a path to a glob pattern that matches that path literally. 15 | * NOTE: `/` is the only allowed separator. `\` is treated as a literal 16 | * character and NOT a separator, and is therefore escaped. 17 | */ 18 | w_string convertLiteralPathToGlob(w_string_piece literal); 19 | 20 | /** 21 | * Convert a glob pattern written for `noescape: true` to a glob pattern that 22 | * can be used without the `noescape` flag. 23 | */ 24 | w_string convertNoEscapeGlobToGlob(w_string_piece noescapePattern); 25 | } // namespace watchman 26 | -------------------------------------------------------------------------------- /watchman/fs/FSDetect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include "watchman/fs/FileDescriptor.h" 13 | #include "watchman/watchman_string.h" 14 | 15 | namespace watchman { 16 | 17 | /** Returns CaseSensitive or CaseInSensitive depending on the 18 | * case sensitivity of the input path. */ 19 | CaseSensitivity getCaseSensitivityForPath(const char* path); 20 | 21 | } // namespace watchman 22 | 23 | // Returns the name of the filesystem for the specified path 24 | w_string w_fstype(const char* path); 25 | std::optional find_fstype_in_linux_proc_mounts( 26 | std::string_view path, 27 | std::string_view procMountsData); 28 | -------------------------------------------------------------------------------- /watchman/java/src/com/facebook/watchman/WatchmanException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.facebook.watchman; 9 | 10 | import java.util.Map; 11 | 12 | public class WatchmanException extends Exception { 13 | 14 | private final Map response; 15 | 16 | public WatchmanException() { 17 | super(); 18 | response = null; 19 | } 20 | 21 | public WatchmanException(String reason) { 22 | super(reason); 23 | response = null; 24 | } 25 | 26 | public WatchmanException(String error, Map response) { 27 | super(error); 28 | this.response = response; 29 | } 30 | 31 | public Map getResponse() { 32 | return response; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /watchman/build/package/ubuntu-env/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG UBUNTU_VERSION 2 | FROM ubuntu:$UBUNTU_VERSION 3 | 4 | # https://serverfault.com/a/1016972 to ensure installing tzdata does 5 | # not result in a prompt that hangs forever. 6 | ENV DEBIAN_FRONTEND=noninteractive 7 | ENV TZ=Etc/UTC 8 | 9 | RUN apt-get -y update 10 | RUN apt-get -y install python3 gcc g++ libssl-dev curl sudo 11 | 12 | # Ubuntu 18.04 has an older version of Git, which causes actions/checkout@v3 13 | # to check out the repository with REST, breaking version number generation. 14 | RUN apt-get -y install software-properties-common 15 | RUN add-apt-repository -y ppa:git-core/ppa 16 | RUN apt-get -y install git 17 | 18 | RUN curl https://sh.rustup.rs -sSf | sh -s -- -y 19 | ENV PATH="/root/.cargo/bin:${PATH}" 20 | 21 | # Avoid build output from Watchman's build getting buffered in large 22 | # chunks, which makes debugging progress tough. 23 | ENV PYTHONUNBUFFERED=1 24 | -------------------------------------------------------------------------------- /watchman/rust/serde_bser/src/ser/count_write.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | use std::io; 9 | use std::io::Write; 10 | 11 | /// A writer that counts how many bytes were written. 12 | pub struct CountWrite { 13 | count: usize, 14 | } 15 | 16 | impl CountWrite { 17 | pub fn new() -> Self { 18 | CountWrite { count: 0 } 19 | } 20 | 21 | #[inline] 22 | pub fn count(&self) -> usize { 23 | self.count 24 | } 25 | } 26 | 27 | impl Write for CountWrite { 28 | #[inline] 29 | fn write(&mut self, buf: &[u8]) -> io::Result { 30 | self.count += buf.len(); 31 | Ok(buf.len()) 32 | } 33 | 34 | #[inline] 35 | fn flush(&mut self) -> io::Result<()> { 36 | Ok(()) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /website/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | * 7 | * @format 8 | */ 9 | 10 | /** 11 | * CSS files with the .module.css suffix will be treated as CSS modules 12 | * and scoped locally. 13 | */ 14 | 15 | .heroBanner { 16 | padding: 4rem 0; 17 | text-align: center; 18 | position: relative; 19 | overflow: hidden; 20 | } 21 | 22 | @media screen and (max-width: 996px) { 23 | .heroBanner { 24 | padding: 2rem; 25 | } 26 | } 27 | 28 | .buttons { 29 | display: flex; 30 | align-items: center; 31 | justify-content: center; 32 | } 33 | 34 | .features { 35 | display: flex; 36 | align-items: center; 37 | padding: 2rem 0; 38 | width: 100%; 39 | } 40 | 41 | .featureImage { 42 | height: 200px; 43 | width: 200px; 44 | } 45 | -------------------------------------------------------------------------------- /watchman/thirdparty/getopt/GetOpt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Portions Copyright (c) 1987, 1993, 1994 3 | * The Regents of the University of California. All rights reserved. 4 | * 5 | * Portions Copyright (c) 2003-2010, PostgreSQL Global Development Group 6 | */ 7 | 8 | #pragma once 9 | 10 | #ifdef _WIN32 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | extern int opterr; 17 | extern int optind; 18 | extern int optopt; 19 | extern char* optarg; 20 | 21 | struct option { 22 | const char* name; 23 | int has_arg; 24 | int* flag; 25 | int val; 26 | }; 27 | 28 | #define no_argument 0 29 | #define required_argument 1 30 | 31 | extern int getopt_long( 32 | int argc, 33 | char* const argv[], 34 | const char* optstring, 35 | const struct option* longopts, 36 | int* longindex); 37 | 38 | int getopt(int nargc, char* const nargv[], const char* ostr); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /watchman/fuzz/PyBserDecode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/python/pywatchman/bser.h" 9 | 10 | extern "C" int LLVMFuzzerTestOneInput(void const* data, size_t size) { 11 | // libfuzzer is not happy if Py_Initialize initializes signal handlers. 12 | Py_InitializeEx(0); 13 | 14 | auto* d = reinterpret_cast(data); 15 | unser_ctx_t ctx{}; 16 | ctx.is_mutable = false; 17 | ctx.value_encoding = nullptr; 18 | ctx.value_errors = nullptr; 19 | ctx.bser_version = 1; 20 | ctx.bser_capabilities = 0; 21 | 22 | PyObject* parsed = bser_loads_recursive(&d, d + size, &ctx); 23 | if (!parsed) { 24 | // Raised parse errors are okay. 25 | PyErr_Clear(); 26 | return 0; 27 | } 28 | Py_DECREF(parsed); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /watchman/integration/eden/test_eden_takeover.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | from watchman.integration.lib import WatchmanEdenTestCase 10 | 11 | 12 | def populate(repo): 13 | repo.write_file(".watchmanconfig", '{"ignore_dirs":[".buckd"]}') 14 | repo.write_file("hello", "hola\n") 15 | repo.commit("initial commit.") 16 | 17 | 18 | class TestEdenTakeover(WatchmanEdenTestCase.WatchmanEdenTestCase): 19 | def test_eden_takeover(self) -> None: 20 | root = self.makeEdenMount(populate) 21 | self.eden.graceful_restart() 22 | 23 | self.watchmanCommand("watch", root) 24 | watch_list = self.getWatchList() 25 | self.assertEqual(len(watch_list), 1) 26 | self.assertEqual(watch_list[0], root) 27 | -------------------------------------------------------------------------------- /watchman/integration/test_command.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # pyre-unsafe 7 | 8 | 9 | import json 10 | 11 | from watchman.integration.lib import WatchmanTestCase 12 | 13 | 14 | @WatchmanTestCase.expand_matrix 15 | class TestCommand(WatchmanTestCase.WatchmanTestCase): 16 | def test_unknown_commands_print_json_error(self) -> None: 17 | stdout, stderr = self.watchmanInstance().commandViaCLI( 18 | ["--pretty", "unknown-command"] 19 | ) 20 | self.assertEqual(b"", stderr) 21 | self.assertNotEqual(b"", stdout) 22 | error = json.loads(stdout) 23 | self.assertRegex( 24 | error["error"], 25 | ".*watchman::CommandValidationError: failed to validate command: unknown command unknown-command", 26 | ) 27 | -------------------------------------------------------------------------------- /website/src/pages/support.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Need help? 3 | --- 4 | 5 | # Need help? 6 | 7 | If you're having trouble or otherwise have questions about Watchman, and 8 | [the troubleshooting guide](./docs/troubleshooting) didn't resolve 9 | your issue, you can try reaching out to the maintainers in one of the following 10 | ways: 11 | 12 | ## Stack Overflow 13 | 14 | We'd like to encourage discussing and answering Watchman related questions on 15 | Stack Overflow. [Look at the recent Watchman questions on Stack Overflow]( 16 | http://stackoverflow.com/questions/tagged/watchman?sort=newest) and if you 17 | can't find what you're looking for, [ask your question on Stack Overflow]( 18 | http://stackoverflow.com/questions/ask?tags=watchman) 19 | 20 | ## Bugs? 21 | 22 | If you've found a bug, or haven't had any success in reaching out through the 23 | channels above, please [file an issue in our tracker]( 24 | https://github.com/facebook/watchman/issues/new) 25 | -------------------------------------------------------------------------------- /watchman/fs/DirHandle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include "watchman/fs/FileInformation.h" 12 | 13 | namespace watchman { 14 | 15 | struct DirEntry { 16 | bool has_stat; 17 | const char* d_name; 18 | FileInformation stat; 19 | }; 20 | 21 | class DirHandle { 22 | public: 23 | virtual ~DirHandle() = default; 24 | virtual const DirEntry* readDir() = 0; 25 | #ifndef _WIN32 26 | virtual int getFd() const = 0; 27 | #endif 28 | }; 29 | 30 | /** 31 | * Returns a dir handle to path. 32 | * Does not follow symlinks if strict == true. 33 | * Throws std::system_error if the dir could not be opened. 34 | */ 35 | std::unique_ptr openDir(const char* path, bool strict = true); 36 | 37 | } // namespace watchman 38 | -------------------------------------------------------------------------------- /watchman/python/publish-pypi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # 8 | # =============================== 9 | # pywatchman pypi publishing tool 10 | # =============================== 11 | # 12 | # this publishes the watchman python module to the pypi project 13 | # index located at https://pypi.python.org/pypi/pywatchman. the 14 | # metadata used for this process comes directly from setup.py. 15 | # 16 | # this requires write access to the pywatchman project on pypi 17 | # as well as a ~/.pypirc of the following form: 18 | # 19 | # [distutils] 20 | # index-servers = pypi 21 | # 22 | # [pypi] 23 | # repository: https://pypi.python.org/pypi 24 | # username: 25 | # password: 26 | # 27 | 28 | python setup.py sdist bdist_wheel upload -r pypi 29 | -------------------------------------------------------------------------------- /watchman/python/pywatchman/encoding.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | 7 | import sys 8 | 9 | 10 | """Module to deal with filename encoding on the local system, as returned by 11 | Watchman.""" 12 | 13 | 14 | default_local_errors = "surrogateescape" 15 | 16 | 17 | def get_local_encoding() -> str: 18 | if sys.platform == "win32": 19 | # Watchman always returns UTF-8 encoded strings on Windows. 20 | return "utf-8" 21 | # On the Python 3 versions we support, sys.getfilesystemencoding never 22 | # returns None. 23 | return sys.getfilesystemencoding() 24 | 25 | 26 | def encode_local(s): 27 | return s.encode(get_local_encoding(), default_local_errors) 28 | 29 | 30 | def decode_local(bs): 31 | return bs.decode(get_local_encoding(), default_local_errors) 32 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /** 9 | * Creating a sidebar enables you to: 10 | - create an ordered group of docs 11 | - render a sidebar for each doc of that group 12 | - provide next/previous navigation 13 | 14 | The sidebars can be generated from the filesystem, or explicitly defined here. 15 | 16 | Create as many sidebars as you want. 17 | */ 18 | 19 | module.exports = { 20 | // By default, Docusaurus generates a sidebar from the docs folder structure 21 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 22 | 23 | // But you can create a sidebar manually 24 | /* 25 | tutorialSidebar: [ 26 | { 27 | type: 'category', 28 | label: 'Tutorial', 29 | items: ['hello'], 30 | }, 31 | ], 32 | */ 33 | }; 34 | -------------------------------------------------------------------------------- /watchman/test/LogTest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | #include "watchman/Logging.h" 10 | 11 | using namespace watchman; 12 | 13 | void w_request_shutdown(void) {} 14 | 15 | TEST(Log, logging) { 16 | char huge[8192]; 17 | bool logged = false; 18 | 19 | auto sub = watchman::getLog().subscribe( 20 | watchman::DBG, [&logged]() { logged = true; }); 21 | 22 | memset(huge, 'X', sizeof(huge)); 23 | huge[sizeof(huge) - 1] = '\0'; 24 | 25 | logf(DBG, "test {}", huge); 26 | 27 | std::vector> pending; 28 | sub->getPending(pending); 29 | EXPECT_FALSE(pending.empty()) << "got an item from our subscription"; 30 | EXPECT_TRUE(logged); 31 | } 32 | 33 | /* vim:ts=2:sw=2:et: 34 | */ 35 | -------------------------------------------------------------------------------- /watchman/integration/test_watch_del_all.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | 12 | from watchman.integration.lib import WatchmanTestCase 13 | 14 | 15 | @WatchmanTestCase.expand_matrix 16 | class TestWatchDelAll(WatchmanTestCase.WatchmanTestCase): 17 | def test_watch_del_all(self) -> None: 18 | root = self.mkdtemp() 19 | 20 | dirs = [os.path.join(root, f) for f in ["a", "b", "c", "d"]] 21 | 22 | for d in dirs: 23 | os.mkdir(d) 24 | self.touchRelative(d, "foo") 25 | self.watchmanCommand("watch", d) 26 | self.assertFileList(d, files=["foo"]) 27 | 28 | self.watchmanCommand("watch-del-all") 29 | self.assertEqual(self.watchmanCommand("watch-list")["roots"], []) 30 | -------------------------------------------------------------------------------- /website/docs/expr/suffix.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: suffix 3 | category: Expression Terms 4 | --- 5 | 6 | The `suffix` expression evaluates true if the file suffix matches the second 7 | argument. This matches files name `foo.php` and `foo.PHP` but not `foophp`: 8 | 9 | ["suffix", "php"] 10 | 11 | Suffix expression matches are case insensitive. 12 | 13 | ## suffix-set 14 | 15 | _Since 5.0_ 16 | 17 | You may specify multiple suffixes to match against by setting the second 18 | argument to an array: 19 | 20 | ["suffix", ["php", "css", "html"]] 21 | 22 | This second form can be accelerated and is preferred over an `anyof` 23 | construction. In the following example the two terms are functionally equivalent 24 | but the set form has a more efficient and thus faster runtime: 25 | 26 | ["anyof", ["suffix", "php"], ["suffix", "html"]] 27 | 28 | ["suffix", ["php", "html"]] 29 | 30 | The [capability](capabilities.md) name associated with this enhanced 31 | functionality is `suffix-set`. 32 | -------------------------------------------------------------------------------- /watchman/Shutdown.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/Shutdown.h" 9 | #include 10 | #include 11 | #include "watchman/watchman_stream.h" 12 | 13 | namespace { 14 | 15 | static std::vector> listener_thread_events; 16 | static std::atomic stopping = false; 17 | 18 | } // namespace 19 | 20 | bool w_is_stopping() { 21 | return stopping.load(std::memory_order_relaxed); 22 | } 23 | 24 | void w_request_shutdown() { 25 | stopping.store(true, std::memory_order_relaxed); 26 | // Knock listener thread out of poll/accept 27 | for (auto& evt : listener_thread_events) { 28 | evt->notify(); 29 | } 30 | } 31 | 32 | void w_push_listener_thread_event(std::shared_ptr event) { 33 | listener_thread_events.push_back(std::move(event)); 34 | } 35 | -------------------------------------------------------------------------------- /watchman/test/lib/FakeWatcher.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "watchman/watcher/Watcher.h" 11 | 12 | namespace watchman { 13 | 14 | class FileSystem; 15 | 16 | class FakeWatcher : public Watcher { 17 | public: 18 | explicit FakeWatcher(FileSystem& fileSystem, bool failsToStart = false); 19 | 20 | bool start(const std::shared_ptr& root) override; 21 | 22 | std::unique_ptr startWatchDir( 23 | const std::shared_ptr& root, 24 | const char* path) override; 25 | 26 | bool waitNotify(int timeoutms) override; 27 | ConsumeNotifyRet consumeNotify( 28 | const std::shared_ptr& root, 29 | PendingChanges& coll) override; 30 | 31 | private: 32 | FileSystem& fileSystem_; 33 | bool failsToStart_; 34 | }; 35 | 36 | } // namespace watchman 37 | -------------------------------------------------------------------------------- /watchman/FlagMap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/FlagMap.h" 9 | #include 10 | #include 11 | 12 | void w_expand_flags( 13 | const struct flag_map* fmap, 14 | uint32_t flags, 15 | char* buf, 16 | size_t len) { 17 | bool first = true; 18 | *buf = '\0'; 19 | while (fmap->label && len) { 20 | if ((flags & fmap->value) == fmap->value) { 21 | size_t space; 22 | 23 | if (!first) { 24 | *buf = ' '; 25 | buf++; 26 | len--; 27 | } else { 28 | first = false; 29 | } 30 | 31 | space = std::min(len, strlen(fmap->label) + 1); 32 | memcpy(buf, fmap->label, space); 33 | 34 | len -= space - 1; 35 | buf += space - 1; 36 | } 37 | fmap++; 38 | } 39 | } 40 | 41 | /* vim:ts=2:sw=2:et: 42 | */ 43 | -------------------------------------------------------------------------------- /watchman/Poison.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include "watchman/watchman_string.h" 14 | 15 | namespace watchman { 16 | 17 | /** 18 | * Some error conditions will put us into a non-recoverable state where we 19 | * can't guarantee that we will be operating correctly. Rather than suffering 20 | * in silence and misleading our clients, we'll poison ourselves and advertise 21 | * that we have done so and provide some advice on how the user can cure us. 22 | */ 23 | extern folly::Synchronized poisoned_reason; 24 | 25 | void set_poison_state( 26 | w_string_piece dir, 27 | std::chrono::system_clock::time_point now, 28 | const char* syscall, 29 | const std::error_code& err); 30 | 31 | } // namespace watchman 32 | -------------------------------------------------------------------------------- /watchman/integration/test_force_recrawl.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # pyre-unsafe 7 | 8 | 9 | import os 10 | 11 | from watchman.integration.lib import WatchmanTestCase 12 | 13 | 14 | @WatchmanTestCase.expand_matrix 15 | class TestForceRecrawl(WatchmanTestCase.WatchmanTestCase): 16 | def test_force_recrawl(self) -> None: 17 | root = self.mkdtemp() 18 | self.watchmanCommand("watch", root) 19 | 20 | os.mkdir(os.path.join(root, "foo")) 21 | filelist = ["foo"] 22 | 23 | self.assertFileList(root, filelist) 24 | 25 | self.suspendWatchman() 26 | 27 | filelist = ["foo"] 28 | for i in range(20000): 29 | self.touchRelative(root, "foo", str(i)) 30 | filelist.append(f"foo/{i}") 31 | 32 | self.resumeWatchman() 33 | 34 | self.assertFileList(root, filelist) 35 | -------------------------------------------------------------------------------- /watchman/thirdparty/libart/tests/runner.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test_art.c" 5 | 6 | int main(void) 7 | { 8 | setlogmask(LOG_UPTO(LOG_DEBUG)); 9 | 10 | Suite *s1 = suite_create("art"); 11 | TCase *tc1 = tcase_create("art"); 12 | SRunner *sr = srunner_create(s1); 13 | int nf; 14 | 15 | // Add the art tests 16 | suite_add_tcase(s1, tc1); 17 | tcase_add_test(tc1, test_art_init_and_destroy); 18 | tcase_add_test(tc1, test_art_insert); 19 | tcase_add_test(tc1, test_art_insert_verylong); 20 | tcase_add_test(tc1, test_art_insert_search); 21 | tcase_add_test(tc1, test_art_insert_delete); 22 | tcase_add_test(tc1, test_art_insert_iter); 23 | tcase_add_test(tc1, test_art_iter_prefix); 24 | tcase_add_test(tc1, test_art_long_prefix); 25 | tcase_add_test(tc1, test_art_insert_search_uuid); 26 | 27 | srunner_run_all(sr, CK_ENV); 28 | nf = srunner_ntests_failed(sr); 29 | srunner_free(sr); 30 | return nf == 0 ? 0 : 1; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /watchman/watchman_preprocessor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | // Helpers for pasting __LINE__ for symbol generation 11 | #define w_paste2(pre, post) pre##post 12 | #define w_paste1(pre, post) w_paste2(pre, post) 13 | #define w_gen_symbol(pre) w_paste1(pre, __LINE__) 14 | 15 | #if _MSC_VER >= 1400 16 | #include // @manual 17 | #if _MSC_VER > 1400 18 | #define WATCHMAN_FMT_STRING(x) _Printf_format_string_ x 19 | #else 20 | #define WATCHMAN_FMT_STRING(x) __format_string x 21 | #endif 22 | #else 23 | #define WATCHMAN_FMT_STRING(x) x 24 | #endif 25 | 26 | #ifdef __GNUC__ 27 | #define WATCHMAN_FMT_ATTR(fmt_param_no, dots_param_no) \ 28 | __attribute__((__format__(__printf__, fmt_param_no, dots_param_no))) 29 | #endif 30 | 31 | #ifndef WATCHMAN_FMT_ATTR 32 | #define WATCHMAN_FMT_ATTR(fmt_param_no, dots_param_no) /* nothing */ 33 | #endif 34 | -------------------------------------------------------------------------------- /watchman/Cookie.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include "watchman/watchman_string.h" 12 | 13 | namespace watchman { 14 | 15 | inline constexpr std::string_view kCookiePrefix = ".watchman-cookie-"; 16 | 17 | /** 18 | * We need to guarantee that we never collapse a cookie notification 19 | * out of the pending list, because we absolutely must observe it coming 20 | * in via the kernel notification mechanism in order for synchronization 21 | * to be correct. 22 | * Since we don't have a Root available, we can't tell what the 23 | * precise cookie prefix is for the current pending list here, so 24 | * we do a substring match. Not the most elegant thing in the world. 25 | */ 26 | inline bool isPossiblyACookie(w_string_piece path) { 27 | return path.contains(kCookiePrefix); 28 | } 29 | 30 | } // namespace watchman 31 | -------------------------------------------------------------------------------- /watchman/sockname.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace watchman { 13 | 14 | /** Returns the legacy socket name. 15 | * It is legacy because its meaning is system dependent and 16 | * a little confusing, but needs to be retained for backwards 17 | * compatibility reasons as it is exported into the environment 18 | * in a number of scenarios. 19 | * You should prefer to use get_unix_sock_name() or 20 | * get_named_pipe_sock_path() instead 21 | */ 22 | const char* get_sock_name_legacy(); 23 | 24 | /** Returns the configured unix domain socket path. */ 25 | const std::string& get_unix_sock_name(); 26 | 27 | /** Returns the configured named pipe socket path */ 28 | const std::string& get_named_pipe_sock_path(); 29 | 30 | extern bool disable_unix_socket; 31 | extern bool disable_named_pipe; 32 | 33 | } // namespace watchman 34 | -------------------------------------------------------------------------------- /watchman/python/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | add_subdirectory(pywatchman) 7 | 8 | add_fb_python_executable(watchman-diag 9 | SOURCES 10 | bin/watchman-diag=__main__.py 11 | DEPENDS 12 | pywatchman 13 | ) 14 | install_fb_python_executable(watchman-diag) 15 | 16 | add_fb_python_executable(watchman-make 17 | SOURCES 18 | bin/watchman-make=__main__.py 19 | DEPENDS 20 | pywatchman 21 | ) 22 | install_fb_python_executable(watchman-make) 23 | 24 | add_fb_python_executable(watchman-replicate-subscription 25 | SOURCES 26 | bin/watchman-replicate-subscription=__main__.py 27 | DEPENDS 28 | pywatchman 29 | ) 30 | install_fb_python_executable(watchman-replicate-subscription) 31 | 32 | add_fb_python_executable(watchman-wait 33 | SOURCES 34 | bin/watchman-wait=__main__.py 35 | DEPENDS 36 | pywatchman 37 | ) 38 | install_fb_python_executable(watchman-wait) 39 | -------------------------------------------------------------------------------- /website/docs/cmd/log-level.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: log-level 3 | category: Commands 4 | --- 5 | 6 | Changes the log level of your connection to the watchman service. 7 | 8 | From the command line: 9 | 10 | ```bash 11 | $ watchman --server-encoding=json --persistent log-level debug 12 | ``` 13 | 14 | JSON: 15 | 16 | ```json 17 | ["log-level", "debug"] 18 | ``` 19 | 20 | This command changes the log level of your client session. Whenever watchman 21 | writes to its log, it walks the list of client sessions and also sends a log 22 | packet to any that have their log level set to match the current log event. 23 | 24 | Valid log levels are: 25 | 26 | - `debug` - receive all log events 27 | - `error` - receive only important log events 28 | - `off` - receive no log events 29 | 30 | Note that you cannot tap into the output of triggered processes using this 31 | mechanism. 32 | 33 | Log events are sent unilaterally by the server as they happen, and have the 34 | following structure: 35 | 36 | ```json 37 | { 38 | "version": "1.0", 39 | "log": "log this please" 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /watchman/integration/lib/node.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # pyre-unsafe 7 | 8 | import distutils.spawn 9 | import os 10 | import subprocess 11 | 12 | 13 | def _find_node(): 14 | return os.environ.get("NODE_BIN", distutils.spawn.find_executable("node")) 15 | 16 | 17 | def _find_yarn(): 18 | return os.environ.get("YARN_PATH", distutils.spawn.find_executable("yarn")) 19 | 20 | 21 | # To avoid CI environments that put broken yarn and node executables in PATH, 22 | # verify they at least run. 23 | def _ensure_can_run(binary_path) -> None: 24 | if binary_path is None: 25 | return None 26 | try: 27 | if 0 != subprocess.call([binary_path, "--version"], stdout=subprocess.DEVNULL): 28 | return None 29 | except OSError: 30 | return None 31 | return binary_path 32 | 33 | 34 | node_bin = _ensure_can_run(_find_node()) 35 | yarn_bin = _ensure_can_run(_find_yarn()) 36 | -------------------------------------------------------------------------------- /watchman/java/src/com/facebook/watchman/bser/BserConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | package com.facebook.watchman.bser; 9 | 10 | public class BserConstants { 11 | // Utility class, do not instantiate. 12 | private BserConstants() { } 13 | 14 | public static final byte BSER_ARRAY = 0x00; 15 | public static final byte BSER_OBJECT = 0x01; 16 | public static final byte BSER_STRING = 0x02; 17 | public static final byte BSER_INT8 = 0x03; 18 | public static final byte BSER_INT16 = 0x04; 19 | public static final byte BSER_INT32 = 0x05; 20 | public static final byte BSER_INT64 = 0x06; 21 | public static final byte BSER_REAL = 0x07; 22 | public static final byte BSER_TRUE = 0x08; 23 | public static final byte BSER_FALSE = 0x09; 24 | public static final byte BSER_NULL = 0x0a; 25 | public static final byte BSER_TEMPLATE = 0x0b; 26 | public static final byte BSER_SKIP = 0x0c; 27 | } 28 | -------------------------------------------------------------------------------- /watchman/integration/eden/test_eden_shutdown.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # pyre-strict 7 | 8 | from eden.integration.lib import hgrepo 9 | from watchman.integration.lib import WatchmanEdenTestCase, WatchmanInstance 10 | 11 | 12 | class TestEdenShutdown(WatchmanEdenTestCase.WatchmanEdenTestCase): 13 | def test_shutdown_and_restart(self) -> None: 14 | def populate(repo: hgrepo.HgRepository) -> None: 15 | repo.write_file("hello", "hola\n") 16 | repo.commit("initial commit.") 17 | 18 | root = self.makeEdenMount(populate) 19 | 20 | inst = WatchmanInstance.Instance() 21 | _, stderr = inst.commandViaCLI(["watch", root]) 22 | self.assertEqual(stderr, b"") 23 | _, stderr = inst.commandViaCLI(["shutdown-server"]) 24 | self.assertEqual(stderr, b"") 25 | _, stderr = inst.commandViaCLI(["get-sockname"]) 26 | self.assertEqual(stderr, b"") 27 | -------------------------------------------------------------------------------- /watchman/telemetry/LogEvent.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | 10 | #include "watchman/WatchmanConfig.h" 11 | #include "watchman/telemetry/LogEvent.h" 12 | 13 | namespace watchman { 14 | 15 | std::pair getLogEventCounters(const LogEventType& type) { 16 | static std::unordered_map eventCounters; 17 | static int64_t samplingRate = cfg_get_int("scribe-sampling-rate", 100); 18 | 19 | // Find event counter or add if missing - init to 0; 20 | auto it = eventCounters.find(type); 21 | if (it == eventCounters.end()) { 22 | it = eventCounters.emplace(type, 0).first; 23 | } 24 | 25 | // Return sampling rate and event count 26 | auto& eventCounter = it->second; 27 | auto eventCount = ++eventCounter % samplingRate; 28 | return std::make_pair(samplingRate, eventCount ? eventCount : samplingRate); 29 | } 30 | 31 | } // namespace watchman 32 | -------------------------------------------------------------------------------- /website/docs/cmd/clock.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: clock 3 | category: Commands 4 | --- 5 | 6 | Returns the current clock value for a watched root. 7 | 8 | _Since 3.9._ 9 | 10 | _The [capability](capabilities.md) name associated with this enhanced 11 | functionality is `clock-sync-timeout`._ 12 | 13 | `sync_timeout` specifies the number of milliseconds that you want to wait to 14 | observe a synchronization cookie. The synchronization cookie is created at the 15 | start of your clock call and, once the cookie is observed, means that the clock 16 | value returned by this command is at least as current as the time of your clock 17 | call. 18 | 19 | If no `sync_timeout` is specified, the returned clock value is the instantaneous 20 | value of the clock associated with the watched root, and may be almost 21 | immediately invalidated if there are any filesystem notifications that are yet 22 | to be processed. 23 | 24 | ```bash 25 | $ watchman clock /path/to/dir 26 | ``` 27 | 28 | JSON: 29 | 30 | Note the third options argument is optional. 31 | 32 | ```json 33 | ["clock", "/path/to/dir", {"sync_timeout": 100}] 34 | ``` 35 | -------------------------------------------------------------------------------- /watchman/integration/eden/test_eden_watch_root.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | 12 | import pywatchman 13 | from watchman.integration.lib import WatchmanEdenTestCase 14 | 15 | 16 | class TestEdenWatchRoot(WatchmanEdenTestCase.WatchmanEdenTestCase): 17 | def test_eden_watch_root(self) -> None: 18 | def populate(repo): 19 | repo.write_file("adir/file", "foo!\n") 20 | repo.commit("initial commit.") 21 | 22 | root = self.makeEdenMount(populate) 23 | 24 | with self.assertRaises(pywatchman.WatchmanError) as ctx: 25 | self.watchmanCommand("watch", os.path.join(root, "adir")) 26 | self.assertRegex( 27 | str(ctx.exception), 28 | ( 29 | "unable to resolve root .*: eden: you may only watch " 30 | + "from the root of an eden mount point." 31 | ), 32 | ) 33 | -------------------------------------------------------------------------------- /website/docs/cmd/get-config.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: get-config 3 | category: Commands 4 | --- 5 | 6 | The `get-config` command returns the `.watchmanconfig` for the root. If there is 7 | no `.watchmanconfig`, it returns an empty configuration field: 8 | 9 | ```bash 10 | $ watchman get-config . 11 | { 12 | "version": "2.9.9", 13 | "config": {} 14 | } 15 | ``` 16 | 17 | ```bash 18 | $ watchman get-config /path/to/root 19 | { 20 | "version": "2.9.9", 21 | "config": { 22 | "ignore_dirs": [ 23 | "buck-out" 24 | ] 25 | } 26 | } 27 | ``` 28 | 29 | Note that watchman only reads the `.watchmanconfig` file when the watch is 30 | established. If changes are made after that point, the `get-config` response 31 | will not reflect them. 32 | 33 | See [Configuration Options](../config.md#configuration-options) for details on 34 | valid contents of the `config` field. Note that the values returned by 35 | `get-config` are passed straight through from the `.watchmanconfig` file, and 36 | thus may contain fields that are not strictly legal. 37 | 38 | This command is available since watchman version 2.9.9. 39 | -------------------------------------------------------------------------------- /watchman/test/RingBufferTest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | 10 | #include "watchman/RingBuffer.h" 11 | 12 | using namespace watchman; 13 | 14 | TEST(RingBufferTest, writes_can_be_read) { 15 | RingBuffer rb{2}; 16 | rb.write(10); 17 | rb.write(11); 18 | auto result = rb.readAll(); 19 | EXPECT_EQ(2, result.size()); 20 | EXPECT_EQ(10, result[0]); 21 | EXPECT_EQ(11, result[1]); 22 | 23 | rb.write(12); 24 | result = rb.readAll(); 25 | EXPECT_EQ(11, result[0]); 26 | EXPECT_EQ(12, result[1]); 27 | } 28 | 29 | TEST(RingBufferTest, writes_can_be_cleared) { 30 | RingBuffer rb{10}; 31 | rb.write(3); 32 | rb.write(4); 33 | auto result = rb.readAll(); 34 | EXPECT_EQ(2, result.size()); 35 | EXPECT_EQ(3, result[0]); 36 | EXPECT_EQ(4, result[1]); 37 | rb.clear(); 38 | rb.write(5); 39 | result = rb.readAll(); 40 | EXPECT_EQ(1, result.size()); 41 | EXPECT_EQ(5, result[0]); 42 | } 43 | -------------------------------------------------------------------------------- /watchman/java/third-party/hamcrest/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "java-hamcrest-2-jar", 3 | out = "java-hamcrest-2.0.0.0.jar", 4 | sha1 = "0221cf2b5aabedf8cd76534996caa21b283ea5d0", 5 | url = "http://central.maven.org/maven2/org/hamcrest/hamcrest-junit/2.0.0.0/hamcrest-junit-2.0.0.0.jar", 6 | ) 7 | 8 | remote_file( 9 | name = "hamcrest-junit-2-jar", 10 | out = "hamcrest-junit-2.0.0.0.jar", 11 | sha1 = "0f1c8853ade0ecf707f5a261c830e98893983813", 12 | url = "http://central.maven.org/maven2/org/hamcrest/java-hamcrest/2.0.0.0/java-hamcrest-2.0.0.0.jar", 13 | ) 14 | 15 | java_library( 16 | name = "hamcrest-2", 17 | visibility = ["PUBLIC"], 18 | deps = [], 19 | exported_deps = [ 20 | ":hamcrest-junit-2", 21 | ":java-hamcrest-2", 22 | ], 23 | ) 24 | 25 | prebuilt_jar( 26 | name = "java-hamcrest-2", 27 | binary_jar = ":java-hamcrest-2-jar", 28 | visibility = ["PUBLIC"], 29 | ) 30 | 31 | prebuilt_jar( 32 | name = "hamcrest-junit-2", 33 | binary_jar = ":hamcrest-junit-2-jar", 34 | visibility = ["PUBLIC"], 35 | deps = [ 36 | ":java-hamcrest-2", 37 | ], 38 | ) 39 | -------------------------------------------------------------------------------- /watchman/query/QueryResult.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include "watchman/Clock.h" 13 | #include "watchman/thirdparty/jansson/jansson.h" 14 | #include "watchman/watchman_string.h" 15 | 16 | namespace watchman { 17 | 18 | struct QueryDebugInfo { 19 | std::vector cookieFileNames; 20 | 21 | json_ref render() const; 22 | }; 23 | 24 | struct RenderResult { 25 | std::vector results; 26 | std::optional templ; 27 | 28 | json_ref toJson() &&; 29 | }; 30 | 31 | struct QueryResult { 32 | bool isFreshInstance; 33 | RenderResult resultsArray; 34 | // Only populated if the query was set to dedup_results 35 | std::unordered_set dedupedFileNames; 36 | ClockSpec clockAtStartOfQuery; 37 | uint32_t stateTransCountAtStartOfQuery; 38 | std::optional savedStateInfo; 39 | QueryDebugInfo debugInfo; 40 | }; 41 | 42 | } // namespace watchman 43 | -------------------------------------------------------------------------------- /watchman/GroupLookup.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/GroupLookup.h" 9 | #include 10 | #include "watchman/Logging.h" 11 | 12 | #ifndef _WIN32 13 | #include 14 | #include 15 | #include 16 | #include 17 | #endif 18 | 19 | #ifndef _WIN32 20 | using namespace watchman; 21 | 22 | const struct group* w_get_group(const char* group_name) { 23 | // This explicit errno statement is necessary to distinguish between the 24 | // group not existing and an error. 25 | errno = 0; 26 | struct group* group = getgrnam(group_name); 27 | if (!group) { 28 | if (errno == 0) { 29 | logf(ERR, "group '{}' does not exist\n", group_name); 30 | } else { 31 | logf( 32 | ERR, 33 | "getting gid for '{}' failed: {}\n", 34 | group_name, 35 | folly::errnoStr(errno)); 36 | } 37 | return nullptr; 38 | } 39 | return group; 40 | } 41 | #endif // ndef _WIN32 42 | -------------------------------------------------------------------------------- /website/docs/expr/pcre.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: pcre & ipcre 3 | category: Expression Terms 4 | --- 5 | 6 | _To use this feature, you must configure watchman `--with-pcre`!_ 7 | 8 | The `pcre` expression performs a Perl Compatible Regular Expression match 9 | against the basename of the file. This pattern matches `test_plan.php` but not 10 | `mytest_plan`: 11 | 12 | ["pcre", "^test_"] 13 | 14 | You may optionally provide a third argument to change the scope of the match 15 | from the basename to the wholename of the file. 16 | 17 | ["pcre", "txt", "basename"] 18 | ["pcre", "txt", "wholename"] 19 | 20 | `pcre` is case sensitive; for case insensitive matching use `ipcre` instead; it 21 | behaves identically to `pcre` except that the match is performed ignoring case. 22 | 23 | _Since 2.9.9._ 24 | 25 | Starting in version 2.9.9, on macOS systems where the watched root is a case 26 | insensitive filesystem (this is the common case for macOS), `pcre` is equivalent 27 | to `ipcre`. 28 | 29 | _Since 4.7._ 30 | 31 | You can override the case sensitivity of all name matching operations used in 32 | the query by setting the `case_sensitive` field in your query. 33 | -------------------------------------------------------------------------------- /watchman/build/package/make-packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | cd "$(dirname "$0")" 8 | 9 | # buildkit truncates log output. 10 | # https://stackoverflow.com/questions/65819424/is-there-a-way-to-increase-the-log-size-in-docker-when-building-a-container 11 | export DOCKER_BUILDKIT=0 12 | 13 | DB="docker build --progress plain" 14 | 15 | UBUNTU_VERSIONS="18 20 22" 16 | 17 | # There may be an opportunity to run some of these in parallel. 18 | for uv in $UBUNTU_VERSIONS; do 19 | $DB --build-arg "UBUNTU_VERSION=$uv.04" -t "watchman-ubuntu-$uv-env" ubuntu-env 20 | 21 | $DB --build-arg "BASE_IMAGE=watchman-ubuntu-$uv-env" -t "watchman-ubuntu-$uv-build" watchman-build 22 | 23 | $DB --build-arg "BASE_IMAGE=watchman-ubuntu-$uv-build" -t "watchman-ubuntu-$uv-deb" watchman-deb 24 | 25 | mkdir -p "_debs/ubuntu-$uv" 26 | 27 | docker run --rm --mount "type=bind,source=$(pwd)/_debs,target=/_out" "watchman-ubuntu-$uv-deb" sh -c "cp /_debs/* /_out/ubuntu-$uv" 28 | done 29 | -------------------------------------------------------------------------------- /watchman/rust/watchman_client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "watchman_client" 3 | version = "0.9.0" 4 | authors = ["Wez Furlong"] 5 | edition = "2021" 6 | description = "a client for the Watchman file watching service" 7 | documentation = "https://docs.rs/watchman_client" 8 | repository = "https://github.com/facebook/watchman/" 9 | license = "MIT" 10 | exclude = ["examples/*"] 11 | 12 | [dependencies] 13 | anyhow = "1.0" 14 | bytes = { version = "1.0", features = ["serde"] } 15 | futures = { version = "0.3.13", features = ["async-await", "compat"] } 16 | maplit = "1.0" 17 | serde = { version = "1.0.126", features = ["derive", "rc"] } 18 | serde_bser = { version = "0.4", path = "../serde_bser" } 19 | thiserror = "1.0" 20 | tokio = { version = "1.7.1", features = ["full", "test-util"] } 21 | tokio-util = { version = "0.6", features = ["full"] } 22 | 23 | [target.'cfg(windows)'.dependencies] 24 | winapi = { version = "0.3", features = ["fileapi", "handleapi", "winbase", "winuser"] } 25 | 26 | [dev-dependencies] 27 | clap = { version = "4.5.7", features = ["derive"] } 28 | 29 | [lints.rust] 30 | unexpected_cfgs = { level = "warn", check-cfg = ["cfg(fbcode_build)"] } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Meta Platforms, Inc. and its affiliates. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /watchman/telemetry/WatchmanStats.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/telemetry/WatchmanStats.h" 9 | 10 | #include 11 | 12 | namespace watchman { 13 | 14 | void WatchmanStats::flush() { 15 | // This method is only really useful while testing to ensure that the service 16 | // data singleton instance has the latest stats. Since all our stats are now 17 | // quantile stat based, flushing the quantile stat map is sufficient for that 18 | // use case. 19 | facebook::fb303::ServiceData::get()->getQuantileStatMap()->flushAll(); 20 | } 21 | 22 | WatchmanStatsPtr getWatchmanStats() { 23 | // A running Watchman daemon only needs a single WatchmanStats instance. Avoid 24 | // atomic reference counts with RefPtr::singleton. We could use 25 | // folly::Singleton but that makes unit testing harder. 26 | static WatchmanStats* gWatchmanStats = new WatchmanStats; 27 | return WatchmanStatsPtr::singleton(*gWatchmanStats); 28 | } 29 | 30 | } // namespace watchman 31 | -------------------------------------------------------------------------------- /watchman/cmds/heapprof.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "watchman/Client.h" 12 | #include "watchman/watchman_cmd.h" 13 | 14 | using namespace watchman; 15 | 16 | #if defined(FOLLY_USE_JEMALLOC) 17 | 18 | // This command is present to manually trigger a heap profile dump when 19 | // jemalloc is in use. 20 | static UntypedResponse cmd_debug_prof_dump(Client*, const json_ref&) { 21 | if (!folly::usingJEMalloc()) { 22 | throw std::runtime_error("jemalloc is not in use"); 23 | } 24 | 25 | auto result = mallctl("prof.dump", nullptr, nullptr, nullptr, 0); 26 | UntypedResponse resp; 27 | resp.set( 28 | "prof.dump", 29 | w_string_to_json( 30 | fmt::format("mallctl prof.dump returned: {}", folly::errnoStr(result)) 31 | .c_str())); 32 | return resp; 33 | } 34 | W_CMD_REG("debug-prof-dump", cmd_debug_prof_dump, CMD_DAEMON, nullptr); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /watchman/query/GlobEscaping.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/query/GlobEscaping.h" 9 | #include 10 | 11 | namespace watchman { 12 | w_string convertLiteralPathToGlob(w_string_piece literal) { 13 | std::string pattern; 14 | pattern.reserve(literal.size()); 15 | for (auto ch : literal.view()) { 16 | switch (ch) { 17 | case '\\': 18 | case '*': 19 | case '[': 20 | case '?': 21 | pattern.push_back('\\'); 22 | break; 23 | } 24 | pattern.push_back(ch); 25 | } 26 | return w_string{pattern}; 27 | } 28 | 29 | w_string convertNoEscapeGlobToGlob(w_string_piece noescapePattern) { 30 | std::string pattern; 31 | pattern.reserve(noescapePattern.size()); 32 | for (auto ch : noescapePattern.view()) { 33 | switch (ch) { 34 | case '\\': 35 | pattern.push_back('\\'); 36 | break; 37 | } 38 | pattern.push_back(ch); 39 | } 40 | return w_string{pattern}; 41 | } 42 | } // namespace watchman 43 | -------------------------------------------------------------------------------- /watchman/integration/test_clock.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | from watchman.integration.lib import WatchmanTestCase 11 | 12 | 13 | @WatchmanTestCase.expand_matrix 14 | class TestClock(WatchmanTestCase.WatchmanTestCase): 15 | def test_clock(self) -> None: 16 | root = self.mkdtemp() 17 | self.watchmanCommand("watch", root) 18 | clock = self.watchmanCommand("clock", root) 19 | 20 | self.assertRegex(clock["clock"], "^c:\\d+:\\d+:\\d+:\\d+$") 21 | 22 | def test_clock_sync(self) -> None: 23 | root = self.mkdtemp() 24 | self.watchmanCommand("watch", root) 25 | clock1 = self.watchmanCommand("clock", root, {"sync_timeout": 5000}) 26 | self.assertRegex(clock1["clock"], "^c:\\d+:\\d+:\\d+:\\d+$") 27 | 28 | clock2 = self.watchmanCommand("clock", root, {"sync_timeout": 5000}) 29 | self.assertRegex(clock2["clock"], "^c:\\d+:\\d+:\\d+:\\d+$") 30 | 31 | self.assertNotEqual(clock1, clock2) 32 | -------------------------------------------------------------------------------- /watchman/rust/serde_bser/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Meta Platforms, Inc. and its affiliates. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /website/docs/expr/name.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: name & iname 3 | category: Expression Terms 4 | --- 5 | 6 | The `name` expression performs exact matches against file names. By default it 7 | is scoped to the basename of the file: 8 | 9 | ["name", "Makefile"] 10 | 11 | You may specify multiple names to match against by setting the second argument 12 | to an array: 13 | 14 | ["name", ["foo.txt", "Makefile"]] 15 | 16 | This second form can be accelerated and is preferred over an `anyof` 17 | construction. 18 | 19 | You may change the scope of the match via the optional third argument: 20 | 21 | ["name", "path/to/file.txt", "wholename"] 22 | ["name", ["path/to/one", "path/to/two"], "wholename"] 23 | 24 | Finally, you may specify case insensitive evaluation by using `iname` instead of 25 | `name`. 26 | 27 | _Since 2.9.9._ 28 | 29 | Starting in version 2.9.9, on macOS systems where the watched root is a case 30 | insensitive filesystem (this is the common case for macOS), `name` is equivalent 31 | to `iname`. 32 | 33 | _Since 4.7._ 34 | 35 | You can override the case sensitivity of all name matching operations used in 36 | the query by setting the `case_sensitive` field in your query. 37 | -------------------------------------------------------------------------------- /watchman/rust/watchman_client/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Meta Platforms, Inc. and its affiliates. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /watchman/saved_state/SavedStateFactory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "watchman/WatchmanConfig.h" 11 | #include "watchman/thirdparty/jansson/jansson.h" 12 | #include "watchman/watchman_string.h" 13 | 14 | namespace watchman { 15 | 16 | struct RootMetadata; 17 | class SCM; 18 | class SavedStateInterface; 19 | struct ClientContext; 20 | 21 | /** 22 | * Returns an appropriate SavedStateInterface implementation for the 23 | * specified storage type. Returns a managed pointer to the saved state 24 | * interface if successful. Throws if the storage type is not recognized, or 25 | * if the saved state interface does not successfully parse the saved state 26 | * config. 27 | */ 28 | std::unique_ptr getInterface( 29 | w_string_piece storageType, 30 | const json_ref& savedStateConfig, 31 | const SCM* scm, 32 | Configuration config, 33 | std::function collectRootMetadata, 34 | ClientContext clientInfo); 35 | 36 | } // namespace watchman 37 | -------------------------------------------------------------------------------- /watchman/Hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace watchman { 13 | 14 | // This is the Hash128to64 function from Google's cityhash (available 15 | // under the MIT License). We use it to reduce multiple 64 bit hashes 16 | // into a single hash. 17 | inline uint64_t hash_128_to_64(const uint64_t upper, const uint64_t lower) { 18 | // Murmur-inspired hashing. 19 | const uint64_t kMul = 0x9ddfea08eb382d69ULL; 20 | uint64_t a = (lower ^ upper) * kMul; 21 | a ^= (a >> 47); 22 | uint64_t b = (upper ^ a) * kMul; 23 | b ^= (b >> 47); 24 | b *= kMul; 25 | return b; 26 | } 27 | 28 | inline constexpr uint64_t hash_combine(std::initializer_list hashes) { 29 | const uint64_t* b = hashes.begin(); 30 | const uint64_t* e = hashes.end(); 31 | if (b == e) { 32 | return 0; 33 | } else { 34 | uint64_t rv = *b++; 35 | while (b != e) { 36 | rv = hash_128_to_64(rv, *b++); 37 | } 38 | return rv; 39 | } 40 | } 41 | 42 | } // namespace watchman 43 | -------------------------------------------------------------------------------- /watchman/fs/WindowsTime.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/fs/WindowsTime.h" 9 | #include 10 | #include "watchman/watchman_time.h" 11 | 12 | namespace watchman { 13 | 14 | #ifdef _WIN32 15 | 16 | namespace { 17 | 18 | // 100's of nanoseconds since the FILETIME epoch 19 | static constexpr uint64_t EPOCH = ((uint64_t)116444736000000000ULL); 20 | 21 | } // namespace 22 | 23 | // FILETIME is expressed in 100's of nanoseconds 24 | void FILETIME_LARGE_INTEGER_to_timespec(LARGE_INTEGER ft, timespec* ts) { 25 | static const uint32_t factor = WATCHMAN_NSEC_IN_SEC / 100; 26 | 27 | ft.QuadPart -= EPOCH; 28 | ts->tv_sec = ft.QuadPart / factor; 29 | ft.QuadPart -= ts->tv_sec * factor; 30 | ts->tv_nsec = ft.QuadPart * 100; 31 | } 32 | 33 | void FILETIME_to_timespec(const FILETIME* ft, timespec* ts) { 34 | LARGE_INTEGER li; 35 | 36 | li.HighPart = ft->dwHighDateTime; 37 | li.LowPart = ft->dwLowDateTime; 38 | 39 | FILETIME_LARGE_INTEGER_to_timespec(li, ts); 40 | } 41 | 42 | #endif 43 | 44 | } // namespace watchman 45 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/ruby-watchman.gemspec: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. All Rights Reserved. 2 | 3 | lib = File.expand_path('../lib', __FILE__) 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 5 | require 'ruby-watchman/version' 6 | 7 | Gem::Specification.new do |s| 8 | s.name = 'ruby-watchman' 9 | s.version = RubyWatchman::VERSION 10 | s.authors = ['Greg Hurrell'] 11 | s.email = ['glh@fb.com'] 12 | s.summary = 'Ruby implementation of Watchman binary protocol' 13 | s.description = <<-DESC.gsub(/^\s+/, '') 14 | A fast implementation of the Watchman binary protocol written in C. 15 | DESC 16 | s.homepage = 'https://github.com/facebook/watchman/tree/main/ruby/ruby-watchman' 17 | s.license = 'BSD' 18 | s.extensions = 'ext/ruby-watchman/extconf.rb' 19 | 20 | s.files = Dir[ 21 | 'ext/ruby-watchman/**/*.{c,h,rb}', 22 | 'ext/ruby-watchman/depend', 23 | 'lib/**/*.rb', 24 | 'spec/**/*.rb' 25 | ] 26 | s.test_files = s.files.grep(%r{^spec/}) 27 | s.require_paths = %w[lib] 28 | 29 | s.add_development_dependency 'bundler', '~> 1.5' 30 | s.add_development_dependency 'rake' 31 | s.add_development_dependency 'rspec', '3.0.0' 32 | end 33 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/ext/ruby-watchman/watchman.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include // @manual 9 | 10 | /** 11 | * @module RubyWatchman 12 | * 13 | * Methods for working with the Watchman binary protocol 14 | * 15 | * @see https://facebook.github.io/watchman/docs/bser.html 16 | */ 17 | extern VALUE mRubyWatchman; 18 | 19 | /** 20 | * Convert an object serialized using the Watchman binary protocol[0] into an 21 | * unpacked Ruby object 22 | */ 23 | extern VALUE RubyWatchman_load(VALUE self, VALUE serialized); 24 | 25 | /** 26 | * Serialize a Ruby object into the Watchman binary protocol format 27 | */ 28 | extern VALUE RubyWatchman_dump(VALUE self, VALUE serializable); 29 | 30 | /** 31 | * Issue `query` to the Watchman instance listening on `socket` (a `UNIXSocket` 32 | * instance) and return the result 33 | * 34 | * The query is serialized following the Watchman binary protocol and the 35 | * result is converted to native Ruby objects before returning to the caller. 36 | */ 37 | extern VALUE RubyWatchman_query(VALUE self, VALUE query, VALUE socket); 38 | -------------------------------------------------------------------------------- /watchman/java/third-party/immutables/BUCK: -------------------------------------------------------------------------------- 1 | remote_file( 2 | name = "value-jar", 3 | out = "value-2.1.5.jar", 4 | sha1 = "8da4fc0eb4655734ffe1b09284f4fc62d033b853", 5 | url = "http://central.maven.org/maven2/org/immutables/value/2.1.5/value-2.1.5.jar", 6 | ) 7 | 8 | remote_file( 9 | name = "value-processor-jar", 10 | out = "value-processor-2.1.5.jar", 11 | sha1 = "37ad0e3c1bd72ab735eaf714b2ce935dee18e4a8", 12 | url = "http://central.maven.org/maven2/org/immutables/value-processor/2.1.5/value-processor-2.1.5.jar", 13 | ) 14 | 15 | remote_file( 16 | name = "generator-jar", 17 | out = "generator-2.1.5.jar", 18 | sha1 = "8cd760cf8cdcbee6f60f11fc7ed8034dfc650444", 19 | url = "http://central.maven.org/maven2/org/immutables/generator/2.1.5/generator-2.1.5.jar", 20 | ) 21 | 22 | prebuilt_jar( 23 | name = "value", 24 | binary_jar = ":value-jar", 25 | visibility = [ 26 | "PUBLIC", 27 | ], 28 | ) 29 | 30 | prebuilt_jar( 31 | name = "value-processor", 32 | binary_jar = ":value-processor-jar", 33 | visibility = [ 34 | "PUBLIC", 35 | ], 36 | ) 37 | 38 | prebuilt_jar( 39 | name = "generator", 40 | binary_jar = ":generator-jar", 41 | visibility = [ 42 | "PUBLIC", 43 | ], 44 | ) 45 | -------------------------------------------------------------------------------- /watchman/python/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "pywatchman" 3 | version = "2.0.0" 4 | authors = [ 5 | { name = "Meta Source Control Team", email = "sourcecontrol-dev@fb.com" }, 6 | ] 7 | description = "Watchman client for Python" 8 | license = { file = "LICENSE" } 9 | readme = "README.md" 10 | requires-python = ">=3.8" 11 | classifiers = [ 12 | "Development Status :: 5 - Production/Stable", 13 | "Intended Audience :: Developers", 14 | "Topic :: System :: Filesystems", 15 | "License :: OSI Approved :: MIT License", 16 | "Operating System :: OS Independent", 17 | "Programming Language :: Python :: 3", 18 | "Programming Language :: Python :: 3.8", 19 | "Programming Language :: Python :: 3.9", 20 | "Programming Language :: Python :: 3.10", 21 | "Programming Language :: Python :: 3.11", 22 | ] 23 | keywords = [ 24 | "watchman", 25 | "inotify", 26 | "fsevents", 27 | "kevent", 28 | "kqueue", 29 | "portfs", 30 | "filesystem", 31 | "watcher", 32 | ] 33 | 34 | [project.urls] 35 | Homepage = "https://github.com/facebook/watchman" 36 | Issues = "https://github.com/facebook/watchman/issues" 37 | 38 | 39 | [build-system] 40 | requires = ["setuptools>=61.0", "wheel>=0.37.0"] 41 | build-backend = "setuptools.build_meta" 42 | -------------------------------------------------------------------------------- /watchman/test/lib/FakeWatcher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/test/lib/FakeWatcher.h" 9 | #include "watchman/fs/FileSystem.h" 10 | 11 | namespace watchman { 12 | 13 | FakeWatcher::FakeWatcher(FileSystem& fileSystem, bool failsToStart) 14 | : Watcher{"FakeWatcher", 0}, 15 | fileSystem_{fileSystem}, 16 | failsToStart_(failsToStart) {} 17 | 18 | bool FakeWatcher::start(const std::shared_ptr& /*root*/) { 19 | return !failsToStart_; 20 | } 21 | 22 | std::unique_ptr FakeWatcher::startWatchDir( 23 | const std::shared_ptr& root, 24 | const char* path) { 25 | (void)root; 26 | return fileSystem_.openDir(path); 27 | } 28 | 29 | bool FakeWatcher::waitNotify(int timeoutms) { 30 | (void)timeoutms; 31 | throw std::logic_error{"waitNotify not implemented"}; 32 | } 33 | 34 | Watcher::ConsumeNotifyRet FakeWatcher::consumeNotify( 35 | const std::shared_ptr& root, 36 | PendingChanges& coll) { 37 | (void)root; 38 | (void)coll; 39 | throw std::logic_error{"consumeNotify not implemented"}; 40 | } 41 | 42 | } // namespace watchman 43 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "staticdocs-starter", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "clean": "docusaurus clear", 13 | "serve": "docusaurus serve", 14 | "write-translations": "docusaurus write-translations", 15 | "write-heading-ids": "docusaurus write-heading-ids" 16 | }, 17 | "dependencies": { 18 | "@docusaurus/core": "2.1.0", 19 | "@docusaurus/preset-classic": "2.1.0", 20 | "@mdx-js/react": "^1.6.21", 21 | "clsx": "^1.1.1", 22 | "docusaurus-plugin-internaldocs-fb": "1.8.0", 23 | "prism-react-renderer": "^1.3.3", 24 | "react": "^17.0.2", 25 | "react-dom": "^17.0.2" 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.5%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | }, 39 | "engines": { 40 | "node": ">=16", 41 | "npm": "use yarn instead", 42 | "yarn": "^1.5" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /watchman/cli/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | use structopt::clap::AppSettings; 9 | use structopt::StructOpt; 10 | 11 | mod audit; 12 | mod rage; 13 | 14 | #[derive(StructOpt, Debug)] 15 | #[structopt(setting = AppSettings::DisableVersion, 16 | setting = AppSettings::VersionlessSubcommands)] 17 | struct MainCommand { 18 | #[structopt(subcommand)] 19 | subcommand: TopLevelSubcommand, 20 | } 21 | 22 | #[derive(StructOpt, Debug)] 23 | enum TopLevelSubcommand { 24 | Audit(audit::AuditCmd), 25 | Rage(rage::RageCmd), 26 | } 27 | 28 | impl TopLevelSubcommand { 29 | async fn run(&self) -> anyhow::Result<()> { 30 | use TopLevelSubcommand::*; 31 | match self { 32 | Audit(cmd) => cmd.run().await, 33 | Rage(cmd) => cmd.run().await, 34 | } 35 | } 36 | } 37 | 38 | #[tokio::main] 39 | async fn main() { 40 | let cmd = MainCommand::from_args(); 41 | match cmd.subcommand.run().await { 42 | Ok(()) => {} 43 | Err(e) => { 44 | eprintln!("error: {}", e); 45 | std::process::exit(1); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /watchman/root/watchlist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "watchman/thirdparty/jansson/jansson.h" 15 | 16 | namespace watchman { 17 | 18 | class Root; 19 | 20 | extern std::atomic live_roots; 21 | 22 | extern folly::Synchronized>> 23 | watched_roots; 24 | 25 | // Given a filename, walk the current set of watches. 26 | // If a watch is a prefix match for filename then we consider it to 27 | // be an enclosing watch and we'll return the root path and the relative 28 | // path to filename. 29 | // Returns NULL if there were no matches. 30 | // If multiple watches have the same prefix, it is undefined which one will 31 | // match. 32 | bool findEnclosingRoot( 33 | const w_string& fileName, 34 | w_string_piece& prefix, 35 | w_string_piece& relativePath); 36 | 37 | void w_root_free_watched_roots(); 38 | json_ref w_root_stop_watch_all(); 39 | json_ref w_root_watch_list_to_json(); 40 | 41 | } // namespace watchman 42 | -------------------------------------------------------------------------------- /watchman/thirdparty/jansson/utf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009-2012 Petri Lehtinen 3 | * 4 | * Jansson is free software; you can redistribute it and/or modify 5 | * it under the terms of the MIT license. See LICENSE for details. 6 | */ 7 | 8 | #ifndef UTF_H 9 | #define UTF_H 10 | 11 | #ifdef HAVE_CONFIG_H 12 | #include // @manual 13 | 14 | #ifdef HAVE_INTTYPES_H 15 | /* inttypes.h includes stdint.h in a standard environment, so there's 16 | no need to include stdint.h separately. If inttypes.h doesn't define 17 | int32_t, it's defined in config.h. */ 18 | #include 19 | #endif /* HAVE_INTTYPES_H */ 20 | 21 | #else /* !HAVE_CONFIG_H */ 22 | #ifdef _WIN32 23 | typedef int int32_t; 24 | #else /* !_WIN32 */ 25 | /* Assume a standard environment */ 26 | #include 27 | #endif /* _WIN32 */ 28 | 29 | #endif /* HAVE_CONFIG_H */ 30 | 31 | #include /* for size_t */ 32 | 33 | int utf8_encode(int codepoint, char* buffer, int* size); 34 | 35 | int utf8_check_first(char byte); 36 | int utf8_check_full(const char* buffer, int size, int32_t* codepoint); 37 | const char* utf8_iterate(const char* buffer, int32_t* codepoint); 38 | 39 | int utf8_check_string(const char* string, int length); 40 | void utf8_fix_string(char* string, size_t length); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /watchman/telemetry/WatchmanStructuredLogger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "eden/common/telemetry/ScribeLogger.h" 11 | #include "eden/common/telemetry/ScubaStructuredLogger.h" 12 | #include "eden/common/telemetry/SessionInfo.h" 13 | #include "eden/common/telemetry/StructuredLogger.h" 14 | 15 | namespace watchman { 16 | 17 | using DynamicEvent = facebook::eden::DynamicEvent; 18 | using SessionInfo = facebook::eden::SessionInfo; 19 | using ScribeLogger = facebook::eden::ScribeLogger; 20 | using ScubaStructuredLogger = facebook::eden::ScubaStructuredLogger; 21 | using StructuredLogger = facebook::eden::StructuredLogger; 22 | 23 | class WatchmanStructuredLogger : public ScubaStructuredLogger { 24 | public: 25 | explicit WatchmanStructuredLogger( 26 | std::shared_ptr scribeLogger, 27 | SessionInfo sessionInfo); 28 | virtual ~WatchmanStructuredLogger() override = default; 29 | 30 | protected: 31 | virtual DynamicEvent populateDefaultFields( 32 | std::optional type) override; 33 | }; 34 | 35 | std::shared_ptr getLogger(); 36 | 37 | } // namespace watchman 38 | -------------------------------------------------------------------------------- /website/docs/expr/size.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: size 3 | category: Expression Terms 4 | --- 5 | 6 | _Since version 3.1_ 7 | 8 | The size term allows the size of an existing file (not deleted) to be evaluated 9 | using simple relational operators as described in the table below. 10 | 11 | The size term must always be an array with 3 elements: 12 | 13 | ["size", "gt", 0] 14 | 15 | The second parameter describes the relational operator and the third parameter 16 | is the integer _operand_ to compare against. The example above evaluates to 17 | `true` if the file exists and its size is greater than zero. 18 | 19 | Possible relational operators are: 20 | 21 | | Operator | Meaning | Result | 22 | | -------- | --------------------- | ------------------------------------------- | 23 | | `eq` | Equal | `true` if file exists and `size == operand` | 24 | | `ne` | Not Equal | `true` if file exists and `size != operand` | 25 | | `gt` | Greater Than | `true` if file exists and `size > operand` | 26 | | `ge` | Greater Than Or Equal | `true` if file exists and `size >= operand` | 27 | | `lt` | Less Than | `true` if file exists and `size < operand` | 28 | | `le` | Less Than Or Equal | `true` if file exists and `size <= operand` | 29 | -------------------------------------------------------------------------------- /watchman/build/package/substcontrol.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | import sys 7 | 8 | DEPENDENCIES_BY_UBUNTU = { 9 | "18.04": [ 10 | "libgoogle-glog0v5", 11 | "libpcre2-8-0", 12 | "libdouble-conversion1", 13 | "libevent-2.1-6", 14 | "libsnappy1v5", 15 | ], 16 | "20.04": [ 17 | "libgoogle-glog0v5", 18 | "libboost-context1.71.0", 19 | "libdouble-conversion3", 20 | "libevent-2.1-7", 21 | "libsnappy1v5", 22 | ], 23 | "22.04": [ 24 | "libgoogle-glog0v5", 25 | "libboost-context1.74.0", 26 | "libdouble-conversion3", 27 | "libevent-2.1-7", 28 | "libsnappy1v5", 29 | ], 30 | } 31 | 32 | 33 | def main(): 34 | filename, package_version, ubuntu_version = sys.argv[1:] 35 | 36 | with open(filename, "r") as f: 37 | contents = f.read() 38 | 39 | contents = contents.replace("%VERSION%", package_version) 40 | contents = contents.replace( 41 | "%DEPENDS%", ", ".join(DEPENDENCIES_BY_UBUNTU[ubuntu_version]) 42 | ) 43 | 44 | with open(filename, "w") as f: 45 | f.write(contents) 46 | 47 | 48 | if __name__ == "__main__": 49 | main() 50 | -------------------------------------------------------------------------------- /watchman/root/reap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | #include "watchman/Logging.h" 10 | #include "watchman/root/Root.h" 11 | 12 | using namespace watchman; 13 | 14 | bool Root::considerReap() { 15 | if (idle_reap_age.count() == 0) { 16 | return false; 17 | } 18 | 19 | auto now = std::chrono::steady_clock::now(); 20 | 21 | if (now > inner.last_cmd_timestamp.load(std::memory_order_acquire) + 22 | idle_reap_age && 23 | (triggers.rlock()->empty()) && (now > inner.last_reap_timestamp) && 24 | !unilateralResponses->hasSubscribers()) { 25 | // We haven't had any activity in a while, and there are no registered 26 | // triggers or subscriptions against this watch. 27 | log(ERR, 28 | "root ", 29 | root_path, 30 | " has had no activity in ", 31 | idle_reap_age, 32 | " and has no triggers or subscriptions, cancelling watch. " 33 | "Set idle_reap_age_seconds in your .watchmanconfig to control this " 34 | "behavior\n"); 35 | return true; 36 | } 37 | 38 | inner.last_reap_timestamp = now; 39 | 40 | return false; 41 | } 42 | 43 | /* vim:ts=2:sw=2:et: 44 | */ 45 | -------------------------------------------------------------------------------- /watchman/node/README.md: -------------------------------------------------------------------------------- 1 | # fb-watchman 2 | 3 | `fb-watchman` is a filesystem watcher that uses the 4 | [Watchman](https://facebook.github.io/watchman/) file watching service from 5 | Facebook. 6 | 7 | Watchman provides file change notification services using very 8 | efficient recursive watches and also allows more advanced change matching and 9 | filesystem tree querying operations using 10 | [a powerful expression syntax](https://facebook.github.io/watchman/docs/file-query.html#expressions). 11 | 12 | ## Install 13 | 14 | You should [install Watchman]( 15 | https://facebook.github.io/watchman/docs/install.html) to make the most of this 16 | module. 17 | 18 | Then simply: 19 | 20 | ``` 21 | $ npm install fb-watchman 22 | ``` 23 | 24 | ## Key Concepts 25 | 26 | - Watchman recursively watches directories. 27 | - Each watched directory is called a `root`. 28 | - You must initiate a `watch` on a `root` using the `watch-project` command prior to subscribing to changes 29 | - Rather than separately watching many sibling directories, `watch-project` consolidates and re-uses existing watches relative to a project root (the location of your `.watchmanconfig` or source control repository root) 30 | - change notifications are relative to the project root 31 | 32 | ## How do I use it? 33 | 34 | [Read the NodeJS watchman documentation](https://facebook.github.io/watchman/docs/nodejs.html) 35 | -------------------------------------------------------------------------------- /watchman/query/GlobTree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace watchman { 15 | 16 | /** 17 | * A node in the tree of node matching rules. 18 | */ 19 | struct GlobTree { 20 | std::string pattern; 21 | 22 | // The list of child rules, excluding any ** rules 23 | std::vector> children; 24 | // The list of ** rules that exist under this node 25 | std::vector> doublestar_children; 26 | 27 | unsigned is_leaf : 1; // if true, generate files for matches 28 | unsigned had_specials : 1; // if false, can do simple string compare 29 | unsigned is_doublestar : 1; // pattern begins with ** 30 | 31 | GlobTree(const char* pattern, uint32_t pattern_len); 32 | 33 | // Produces a list of globs from the glob tree, effectively 34 | // performing the reverse of the original parsing operation. 35 | std::vector unparse() const; 36 | 37 | // A helper method for unparse 38 | void unparse_into( 39 | std::vector& globStrings, 40 | std::string_view relative) const; 41 | }; 42 | 43 | } // namespace watchman 44 | -------------------------------------------------------------------------------- /watchman/Connect.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/Connect.h" 9 | #include "watchman/WatchmanConfig.h" 10 | #include "watchman/sockname.h" 11 | #include "watchman/watchman_stream.h" 12 | 13 | using namespace watchman; 14 | 15 | ResultErrno> w_stm_connect(int timeoutms) { 16 | // Default to using unix domain sockets unless disabled by config 17 | auto use_unix_domain = Configuration().getBool("use-unix-domain", true); 18 | 19 | // We have to return some kind of error if use_unix_domain is false and 20 | // disabled_named_pipe is true. "Destination address required" seems to fit. 21 | int err = EDESTADDRREQ; 22 | 23 | if (use_unix_domain && !disable_unix_socket) { 24 | auto stm = w_stm_connect_unix(get_unix_sock_name().c_str(), timeoutms); 25 | if (stm.hasValue()) { 26 | return stm; 27 | } 28 | err = stm.error(); 29 | } 30 | 31 | #ifdef _WIN32 32 | if (!disable_named_pipe) { 33 | std::unique_ptr stm = 34 | w_stm_connect_named_pipe(get_named_pipe_sock_path().c_str(), timeoutms); 35 | if (stm) { 36 | return stm; 37 | } 38 | err = errno; 39 | } 40 | #endif 41 | 42 | return err; 43 | } 44 | -------------------------------------------------------------------------------- /watchman/thirdparty/deelevate_binding/include/deelevate.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | extern "C" { 8 | 9 | /// This function is for use by C/C++ code that wants to test whether the 10 | /// current session is elevated. The return value is 0 for a non-privileged 11 | /// process and non-zero for a privileged process. 12 | /// If an error occurs while obtaining this information, the program will 13 | /// terminate. 14 | int32_t deelevate_is_privileged_process(); 15 | 16 | /// This function is for use by C/C++ code that wants to ensure that execution 17 | /// will only continue if the current token has a Normal privilege level. 18 | /// This function will attempt to re-execute the program in the appropriate 19 | /// context. 20 | /// This function will only return if the current context has normal privs. 21 | void deelevate_requires_normal_privileges(); 22 | 23 | /// This function is for use by C/C++ code that wants to ensure that execution 24 | /// will only continue if the current token has an Elevated privilege level. 25 | /// This function will attempt to re-execute the program in the appropriate 26 | /// context. 27 | /// This function will only return if the current context has Elevated or 28 | /// High Integrity Admin privs. 29 | void deelevate_requires_elevated_privileges(); 30 | 31 | } // extern "C" 32 | -------------------------------------------------------------------------------- /website/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | /** 9 | * CSS files with the .module.css suffix will be treated as CSS modules 10 | * and scoped locally. 11 | */ 12 | 13 | .heroBanner { 14 | padding: 4rem 0; 15 | text-align: center; 16 | position: relative; 17 | overflow: hidden; 18 | } 19 | 20 | .logo { 21 | width: 200px; 22 | } 23 | 24 | .buttons { 25 | display: flex; 26 | align-items: center; 27 | justify-content: center; 28 | } 29 | 30 | .getStarted { 31 | color: white; 32 | --ifm-button-background-color: var(--ifm-color-primary-dark); 33 | --ifm-button-border-color: transparent; 34 | } 35 | 36 | .getStarted:hover { 37 | --ifm-button-background-color: var(--ifm-color-primary-darker); 38 | } 39 | 40 | [data-theme='dark'] .getStarted { 41 | color: black; 42 | } 43 | 44 | [data-theme='dark'] .getStarted:hover { 45 | --ifm-button-background-color: var(--ifm-color-primary-darker); 46 | } 47 | 48 | .introduction { 49 | width: 996px; 50 | margin: 0 auto; 51 | padding: 3rem 2rem; 52 | } 53 | 54 | @media screen and (max-width: 996px) { 55 | .heroBanner { 56 | padding: 2rem; 57 | } 58 | 59 | .introduction { 60 | width: 100%; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 |
2 | watchman-logo 3 |

Watchman

4 |

A file watching service.

5 |
6 | 7 | ## Purpose 8 | 9 | Watchman exists to watch files and record when they actually change. It can 10 | also trigger actions (such as rebuilding assets) when matching files change. 11 | 12 | ## Documentation 13 | 14 | Head on over to https://facebook.github.io/watchman/ 15 | 16 | ## License 17 | 18 | Watchman is made available under the terms of the MIT License. See the 19 | LICENSE file that accompanies this distribution for the full text of the 20 | license. 21 | 22 | ## Support 23 | 24 | Watchman is primarily maintained by the source control team at Meta Platforms, Inc. We support: 25 | 26 | * Windows and macOS builds 27 | * Linux builds on recent Ubuntu and Fedora releases 28 | * Watchman's [compatibility commitment](https://facebook.github.io/watchman/docs/compatibility.html) 29 | * Python, Rust, and JavaScript clients 30 | 31 | Support for additional operating systems, release packaging, and language bindings is community-maintained: 32 | 33 | * Homebrew 34 | * FreeBSD 35 | * Solaris 36 | 37 | Please submit a [GitHub issue](https://github.com/facebook/watchman/issues/) to report any troubles. 38 | 39 | ## Contributing 40 | 41 | Please see the [contributing document](CONTRIBUTING.md). 42 | -------------------------------------------------------------------------------- /watchman/Poison.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | #include "watchman/Logging.h" 10 | #include "watchman/WatchmanConfig.h" 11 | 12 | namespace watchman { 13 | 14 | folly::Synchronized poisoned_reason; 15 | 16 | void set_poison_state( 17 | w_string_piece dir, 18 | std::chrono::system_clock::time_point now, 19 | const char* syscall, 20 | const std::error_code& err) { 21 | if (!poisoned_reason.rlock()->empty()) { 22 | return; 23 | } 24 | 25 | auto why = fmt::format( 26 | "A non-recoverable condition has triggered. Watchman needs your help!\n" 27 | "The triggering condition was at timestamp={}: {}({}) -> {}\n" 28 | "All requests will continue to fail with this message until you resolve\n" 29 | "the underlying problem. You will find more information on fixing this at\n" 30 | "{}#poison-{}\n", 31 | std::chrono::system_clock::to_time_t(now), 32 | syscall, 33 | dir.view(), 34 | err.message(), 35 | cfg_get_trouble_url(), 36 | syscall); 37 | 38 | watchman::log(watchman::ERR, why); 39 | *poisoned_reason.wlock() = why; 40 | } 41 | 42 | } // namespace watchman 43 | 44 | /* vim:ts=2:sw=2:et: 45 | */ 46 | -------------------------------------------------------------------------------- /watchman/integration/test_two_deep.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | import time 12 | 13 | from watchman.integration.lib import WatchmanTestCase 14 | 15 | 16 | @WatchmanTestCase.expand_matrix 17 | class TestTwoDeep(WatchmanTestCase.WatchmanTestCase): 18 | def test_two_deep(self) -> None: 19 | root = self.mkdtemp() 20 | self.watchmanCommand("watch", root) 21 | 22 | os.makedirs(os.path.join(root, "foo", "bar")) 23 | 24 | # Guarantee that 111's mtime is greater than its parent dirs 25 | time.sleep(1) 26 | 27 | with open(os.path.join(root, "foo", "bar", "111"), "w") as f: 28 | f.write("111") 29 | 30 | self.assertFileList(root, files=["foo", "foo/bar", "foo/bar/111"]) 31 | 32 | res_111 = self.watchmanCommand("find", root, "foo/bar/111")["files"][0] 33 | st_111 = os.lstat(os.path.join(root, "foo", "bar", "111")) 34 | 35 | res_bar = self.watchmanCommand("find", root, "foo/bar")["files"][0] 36 | st_bar = os.lstat(os.path.join(root, "foo", "bar")) 37 | 38 | self.assertEqual(res_111["mtime"], int(st_111.st_mtime)) 39 | self.assertEqual(res_bar["mtime"], int(st_bar.st_mtime)) 40 | -------------------------------------------------------------------------------- /watchman/integration/test_info.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import json 11 | import os 12 | 13 | from watchman.integration.lib import WatchmanTestCase 14 | 15 | 16 | @WatchmanTestCase.expand_matrix 17 | class TestInfo(WatchmanTestCase.WatchmanTestCase): 18 | def test_sock_name(self) -> None: 19 | resp = self.watchmanCommand("get-sockname") 20 | self.assertEqual( 21 | resp["sockname"], 22 | self.watchmanInstance().getSockPath().legacy_sockpath(), 23 | ) 24 | 25 | def test_get_config_empty(self) -> None: 26 | root = self.mkdtemp() 27 | self.watchmanCommand("watch", root) 28 | self.assertEqual(self.get_config(root), {}) 29 | 30 | def test_get_config(self) -> None: 31 | config = {"test-key": "test-value"} 32 | root = self.mkdtemp() 33 | with open(os.path.join(root, ".watchmanconfig"), "w") as f: 34 | json.dump(config, f) 35 | self.watchmanCommand("watch", root) 36 | self.assertEqual(self.get_config(root), config) 37 | 38 | def get_config(self, root): 39 | resp = self.watchmanCommand("get-config", root) 40 | config = resp["config"] 41 | return config 42 | -------------------------------------------------------------------------------- /watchman/integration/test_big_file.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | import os.path 12 | 13 | from watchman.integration.lib import WatchmanTestCase 14 | 15 | 16 | @WatchmanTestCase.expand_matrix 17 | class TestBigFile(WatchmanTestCase.WatchmanTestCase): 18 | def test_big_file(self) -> None: 19 | root = self.mkdtemp() 20 | 21 | def check(file_size): 22 | with open(os.path.join(root, "big"), "w") as f: 23 | f.truncate(file_size) 24 | 25 | self.watchmanCommand("watch", root) 26 | 27 | result = self.watchmanCommand( 28 | "query", 29 | root, 30 | { 31 | "fields": [ 32 | "name", 33 | "size", 34 | ], 35 | }, 36 | ) 37 | 38 | self.assertEqual(len(result["files"]), 1) 39 | 40 | file = result["files"][0] 41 | self.assertEqual(file["name"], "big") 42 | self.assertEqual(file["size"], file_size) 43 | 44 | # This size overflows int32 45 | check(2**31) 46 | 47 | # This size overflows uint32 48 | check(2**32) 49 | -------------------------------------------------------------------------------- /watchman/integration/test_remove_then_add.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | import shutil 12 | 13 | from watchman.integration.lib import WatchmanTestCase 14 | 15 | 16 | @WatchmanTestCase.expand_matrix 17 | class TestRemoveThenAdd(WatchmanTestCase.WatchmanTestCase): 18 | def checkOSApplicability(self) -> None: 19 | if os.name == "linux" and os.getenv("TRAVIS"): 20 | self.skipTest("openvz and inotify unlinks == bad time") 21 | 22 | def test_remove_then_add(self) -> None: 23 | root = self.mkdtemp() 24 | os.mkdir(os.path.join(root, "foo")) 25 | 26 | self.watchmanCommand("watch", root) 27 | 28 | self.touchRelative(root, "foo", "222") 29 | os.mkdir(os.path.join(root, "foo", "bar")) 30 | 31 | self.assertFileList(root, files=["foo", "foo/bar", "foo/222"]) 32 | 33 | shutil.rmtree(os.path.join(root, "foo", "bar")) 34 | self.removeRelative(root, "foo", "222") 35 | shutil.rmtree(os.path.join(root, "foo")) 36 | 37 | self.assertFileList(root, files=[]) 38 | 39 | os.mkdir(os.path.join(root, "foo")) 40 | self.touchRelative(root, "foo", "222") 41 | 42 | self.assertFileList(root, files=["foo", "foo/222"]) 43 | -------------------------------------------------------------------------------- /watchman/thirdparty/libart/README.md: -------------------------------------------------------------------------------- 1 | libart [![Build Status](https://travis-ci.org/armon/libart.png)](https://travis-ci.org/armon/libart) 2 | ========= 3 | 4 | This library provides a C99 implementation of the Adaptive Radix 5 | Tree or ART. The ART operates similar to a traditional radix tree but 6 | avoids the wasted space of internal nodes by changing the node size. 7 | It makes use of 4 node sizes (4, 16, 48, 256), and can guarantee that 8 | the overhead is no more than 52 bytes per key, though in practice it is 9 | much lower. 10 | 11 | As a radix tree, it provides the following: 12 | * O(k) operations. In many cases, this can be faster than a hash table since 13 | the hash function is an O(k) operation, and hash tables have very poor cache locality. 14 | * Minimum / Maximum value lookups 15 | * Prefix compression 16 | * Ordered iteration 17 | * Prefix based iteration 18 | 19 | 20 | Usage 21 | ------- 22 | 23 | Building the test code will generate errors if libcheck is not available. 24 | To build the test code successfully, do the following:: 25 | 26 | $ cd deps/check-0.9.8/ 27 | $ ./configure 28 | $ make 29 | # make install 30 | # ldconfig (necessary on some Linux distros) 31 | $ cd ../../ 32 | $ scons 33 | $ ./test_runner 34 | 35 | 36 | References 37 | ---------- 38 | 39 | Related works: 40 | 41 | * [The Adaptive Radix Tree: ARTful Indexing for Main-Memory Databases](http://www-db.in.tum.de/~leis/papers/ART.pdf) 42 | 43 | -------------------------------------------------------------------------------- /watchman/benchmarks/string.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include 9 | #include "watchman/watchman_string.h" 10 | 11 | namespace { 12 | 13 | void string_allocate_and_deallocate(benchmark::State& state) { 14 | char c[] = "hello world, how are you?"; 15 | for (auto _ : state) { 16 | benchmark::DoNotOptimize(w_string{c, sizeof(c) - 1}); 17 | } 18 | } 19 | 20 | BENCHMARK(string_allocate_and_deallocate); 21 | 22 | void string_hash(benchmark::State& state) { 23 | char c[] = "if there are no branches in the hash function, constant is fine"; 24 | w_string str = c; 25 | for (auto _ : state) { 26 | benchmark::DoNotOptimize(str.hashValue()); 27 | } 28 | } 29 | 30 | BENCHMARK(string_hash); 31 | 32 | void string_piece_hash(benchmark::State& state) { 33 | char c[] = "if there are no branches in the hash function, constant is fine"; 34 | w_string_piece piece = c; 35 | for (auto _ : state) { 36 | benchmark::DoNotOptimize(piece.hashValue()); 37 | } 38 | } 39 | 40 | BENCHMARK(string_piece_hash); 41 | 42 | } // namespace 43 | 44 | int main(int argc, char** argv) { 45 | ::benchmark::Initialize(&argc, argv); 46 | if (::benchmark::ReportUnrecognizedArguments(argc, argv)) 47 | return 1; 48 | ::benchmark::RunSpecifiedBenchmarks(); 49 | } 50 | -------------------------------------------------------------------------------- /watchman/integration/test_fork.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | 12 | import pywatchman 13 | from watchman.integration.lib import WatchmanTestCase 14 | 15 | 16 | @WatchmanTestCase.expand_matrix 17 | class TestSince(WatchmanTestCase.WatchmanTestCase): 18 | def checkOSApplicability(self) -> None: 19 | if not getattr(os, "fork", None): 20 | self.skipTest("no fork on this system") 21 | 22 | def test_forkclient(self) -> None: 23 | client = self.getClient() 24 | 25 | client.query("version") 26 | 27 | pid = os.fork() 28 | if pid == 0: 29 | # I am the new process 30 | try: 31 | with self.assertRaises(pywatchman.UseAfterFork) as ctx: 32 | client.query("version") 33 | self.assertIn( 34 | "do not re-use a connection after fork", str(ctx.exception) 35 | ) 36 | 37 | # All good 38 | os._exit(0) 39 | except BaseException as exc: 40 | print("Error in child process: %s" % exc) 41 | os._exit(1) 42 | 43 | _pid, status = os.waitpid(pid, 0) 44 | self.assertEqual(status, 0, "child process exited 0") 45 | -------------------------------------------------------------------------------- /watchman/query/parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include "watchman/Clock.h" 12 | #include "watchman/fs/FileSystem.h" 13 | 14 | namespace watchman { 15 | 16 | struct Query; 17 | struct QueryFieldRenderer; 18 | class QueryFieldList; 19 | class Root; 20 | 21 | constexpr inline std::chrono::milliseconds kDefaultQuerySyncTimeout{60000}; 22 | 23 | std::shared_ptr parseQuery( 24 | const std::shared_ptr& root, 25 | const json_ref& query); 26 | 27 | // parse the old style since and find queries 28 | std::shared_ptr parseQueryLegacy( 29 | const std::shared_ptr& root, 30 | const json_ref& args, 31 | int start, 32 | uint32_t* next_arg, 33 | const char* clockspec, 34 | json_ref* expr_p); 35 | 36 | void w_query_legacy_field_list(watchman::QueryFieldList* flist); 37 | 38 | void parse_field_list( 39 | const std::optional& field_list, 40 | watchman::QueryFieldList* selected); 41 | json_ref field_list_to_json_name_array( 42 | const watchman::QueryFieldList& fieldList); 43 | 44 | void parse_suffixes(watchman::Query* res, const json_ref& query); 45 | void parse_globs(watchman::Query* res, const json_ref& query); 46 | 47 | } // namespace watchman 48 | -------------------------------------------------------------------------------- /watchman/rust/serde_bser/src/de/seq.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | use serde::de; 9 | 10 | use super::read::DeRead; 11 | use super::reentrant::ReentrantGuard; 12 | use super::Deserializer; 13 | use crate::errors::*; 14 | 15 | pub struct SeqAccess<'a, R> { 16 | de: &'a mut Deserializer, 17 | remaining: usize, 18 | } 19 | 20 | impl<'a, 'de, R> SeqAccess<'a, R> 21 | where 22 | R: 'a + DeRead<'de>, 23 | { 24 | /// Create a new `MapAccess`. 25 | /// 26 | /// `_guard` makes sure the caller is accounting for the recursion limit. 27 | pub fn new(de: &'a mut Deserializer, nitems: usize, _guard: &ReentrantGuard) -> Self { 28 | SeqAccess { 29 | de, 30 | remaining: nitems, 31 | } 32 | } 33 | } 34 | 35 | impl<'a, 'de, R> de::SeqAccess<'de> for SeqAccess<'a, R> 36 | where 37 | R: 'a + DeRead<'de>, 38 | { 39 | type Error = Error; 40 | 41 | fn next_element_seed(&mut self, seed: T) -> Result> 42 | where 43 | T: de::DeserializeSeed<'de>, 44 | { 45 | if self.remaining == 0 { 46 | Ok(None) 47 | } else { 48 | self.remaining -= 1; 49 | let value = seed.deserialize(&mut *self.de)?; 50 | Ok(Some(value)) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /watchman/rust/serde_bser/src/de/reentrant.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | //! Module to handle reentrant/recursion limits while deserializing. 9 | 10 | use std::cell::Cell; 11 | use std::rc::Rc; 12 | 13 | use crate::errors::*; 14 | 15 | /// Sets a limit on the amount of recursion during deserialization. This does 16 | /// not do any synchronization -- it is intended purely for single-threaded use. 17 | pub struct ReentrantLimit(Rc>); 18 | 19 | impl ReentrantLimit { 20 | /// Create a new reentrant limit. 21 | pub fn new(limit: usize) -> Self { 22 | ReentrantLimit(Rc::new(Cell::new(limit))) 23 | } 24 | 25 | /// Try to decrease the limit by 1. Return an RAII guard that when freed 26 | /// will increase the limit by 1. 27 | pub fn acquire>(&mut self, kind: S) -> Result { 28 | if self.0.get() == 0 { 29 | return Err(Error::DeRecursionLimitExceeded { kind: kind.into() }); 30 | } 31 | self.0.set(self.0.get() - 1); 32 | Ok(ReentrantGuard(self.0.clone())) 33 | } 34 | } 35 | 36 | /// RAII guard for reentrant limits. 37 | pub struct ReentrantGuard(Rc>); 38 | 39 | impl Drop for ReentrantGuard { 40 | fn drop(&mut self) { 41 | self.0.set(self.0.get() + 1); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /watchman/rust/watchman_client/examples/subscribe.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | //! This example shows how to initiate a subscription and print out 9 | //! file changes as they are reported 10 | use std::path::PathBuf; 11 | 12 | use clap::Parser; 13 | use watchman_client::prelude::*; 14 | 15 | /// Subscribe to watchman and stream file changes for a path 16 | #[derive(Debug, Parser)] 17 | struct Cli { 18 | #[arg(default_value = ".")] 19 | path: PathBuf, 20 | } 21 | 22 | #[tokio::main(flavor = "current_thread")] 23 | async fn main() { 24 | if let Err(err) = run().await { 25 | // Print a prettier error than the default 26 | eprintln!("{}", err); 27 | std::process::exit(1); 28 | } 29 | } 30 | 31 | async fn run() -> Result<(), Box> { 32 | let opt = Cli::parse(); 33 | let client = Connector::new().connect().await?; 34 | let resolved = client 35 | .resolve_root(CanonicalPath::canonicalize(opt.path)?) 36 | .await?; 37 | 38 | let (mut sub, initial) = client 39 | .subscribe::(&resolved, SubscribeRequest::default()) 40 | .await?; 41 | 42 | println!("{} {:#?}", sub.name(), initial); 43 | loop { 44 | let item = sub.next().await?; 45 | println!("{:#?}", item); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /watchman/integration/test_auth.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import pywatchman 11 | from watchman.integration.lib import WatchmanTestCase 12 | 13 | 14 | @WatchmanTestCase.expand_matrix 15 | class TestAuth(WatchmanTestCase.WatchmanTestCase): 16 | def requiresPersistentSession(self) -> bool: 17 | return True 18 | 19 | def test_dropPriv(self) -> None: 20 | root = self.mkdtemp() 21 | self.touchRelative(root, "111") 22 | 23 | self.watchmanCommand("watch", root) 24 | 25 | # pretend we are not the owner 26 | self.watchmanCommand("debug-drop-privs") 27 | 28 | # Should be able to watch something that is already watched 29 | self.watchmanCommand("watch", root) 30 | 31 | # can't make a new watch 32 | altroot = self.mkdtemp() 33 | with self.assertRaises(pywatchman.WatchmanError): 34 | self.watchmanCommand("watch", altroot) 35 | 36 | # Should not be able to delete a watch 37 | with self.assertRaises(pywatchman.WatchmanError): 38 | self.watchmanCommand("watch-del", root) 39 | 40 | # or register a trigger 41 | with self.assertRaises(pywatchman.WatchmanError): 42 | self.watchmanCommand("trigger", root, "trig", "*.js", "--", "false") 43 | -------------------------------------------------------------------------------- /watchman/saved_state/SavedStateFactory.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #include "watchman/saved_state/SavedStateFactory.h" 9 | #include "watchman/ClientContext.h" 10 | #include "watchman/Errors.h" 11 | #include "watchman/root/Root.h" 12 | #include "watchman/saved_state/LocalSavedStateInterface.h" 13 | 14 | #if HAVE_MANIFOLD 15 | #include "watchman/facebook/saved_state/ManifoldSavedStateInterface.h" // @manual 16 | #endif 17 | 18 | namespace watchman { 19 | 20 | std::unique_ptr getInterface( 21 | w_string_piece storageType, 22 | const json_ref& savedStateConfig, 23 | const SCM* scm, 24 | [[maybe_unused]] Configuration config, 25 | [[maybe_unused]] std::function collectRootMetadata, 26 | [[maybe_unused]] ClientContext clientInfo) { 27 | #if HAVE_MANIFOLD 28 | if (storageType == "manifold") { 29 | return std::make_unique( 30 | savedStateConfig, 31 | scm, 32 | std::move(config), 33 | std::move(collectRootMetadata), 34 | std::move(clientInfo)); 35 | } 36 | #endif 37 | if (storageType == "local") { 38 | return std::make_unique(savedStateConfig, scm); 39 | } 40 | QueryParseError::throwf("invalid storage type '{}'", storageType); 41 | } 42 | 43 | } // namespace watchman 44 | -------------------------------------------------------------------------------- /watchman/integration/eden/test_eden_unmount.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import pywatchman 11 | from watchman.integration.lib import WatchmanEdenTestCase 12 | 13 | 14 | def populate(repo): 15 | repo.write_file(".watchmanconfig", '{"ignore_dirs":[".buckd"]}') 16 | repo.write_file("hello", "hola\n") 17 | repo.commit("initial commit.") 18 | 19 | 20 | class TestEdenUnmount(WatchmanEdenTestCase.WatchmanEdenTestCase): 21 | def test_eden_unmount(self) -> None: 22 | root = self.makeEdenMount(populate) 23 | self.watchmanCommand("watch", root) 24 | 25 | clock = self.watchmanCommand("clock", root) 26 | self.touchRelative(root, "newfile") 27 | 28 | self.eden.unmount(root) 29 | 30 | with self.assertRaises(pywatchman.CommandError) as ctx: 31 | self.watchmanCommand("query", root, {"fields": ["name"], "since": clock}) 32 | 33 | self.assertRegex(str(ctx.exception), "unable to resolve root") 34 | 35 | def test_eden_unmount_watch(self) -> None: 36 | root = self.makeEdenMount(populate) 37 | self.eden.unmount(root) 38 | 39 | with self.assertRaises(pywatchman.CommandError) as ctx: 40 | self.watchmanCommand("watch", root) 41 | 42 | self.assertRegex(str(ctx.exception), "unable to resolve root") 43 | -------------------------------------------------------------------------------- /watchman/integration/test_case_sensitive.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # pyre-unsafe 7 | 8 | 9 | import os 10 | 11 | from watchman.integration.lib import WatchmanTestCase 12 | 13 | 14 | @WatchmanTestCase.expand_matrix 15 | class TestCaseSensitive(WatchmanTestCase.WatchmanTestCase): 16 | def test_changeCase(self) -> None: 17 | root = self.mkdtemp() 18 | os.mkdir(os.path.join(root, "foo")) 19 | self.watchmanCommand("watch", root) 20 | self.assertFileList(root, ["foo"]) 21 | 22 | os.rename(os.path.join(root, "foo"), os.path.join(root, "FOO")) 23 | self.touchRelative(root, "FOO", "bar") 24 | self.assertFileList(root, ["FOO", "FOO/bar"]) 25 | 26 | os.rename(os.path.join(root, "FOO", "bar"), os.path.join(root, "FOO", "BAR")) 27 | self.assertFileList(root, ["FOO", "FOO/BAR"]) 28 | 29 | os.rename(os.path.join(root, "FOO"), os.path.join(root, "foo")) 30 | self.assertFileList(root, ["foo", "foo/BAR"]) 31 | 32 | os.mkdir(os.path.join(root, "foo", "baz")) 33 | self.touchRelative(root, "foo", "baz", "file") 34 | self.assertFileList(root, ["foo", "foo/BAR", "foo/baz", "foo/baz/file"]) 35 | 36 | os.rename(os.path.join(root, "foo"), os.path.join(root, "Foo")) 37 | 38 | self.assertFileList(root, ["Foo", "Foo/BAR", "Foo/baz", "Foo/baz/file"]) 39 | -------------------------------------------------------------------------------- /watchman/integration/test_kqueue_and_fsevents_recrawl.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | import os.path 12 | import sys 13 | 14 | from watchman.integration.lib import WatchmanTestCase 15 | 16 | 17 | @WatchmanTestCase.expand_matrix 18 | class TestKQueueAndFSEventsRecrawl(WatchmanTestCase.WatchmanTestCase): 19 | def checkOSApplicability(self) -> None: 20 | if sys.platform != "darwin": 21 | self.skipTest("N/A unless macOS") 22 | 23 | def test_recrawl(self) -> None: 24 | root = self.mkdtemp() 25 | watch = self.watchmanCommand("watch", root) 26 | 27 | # On macOS, we may not always use kqueue+fsevents 28 | if watch["watcher"] != "kqueue+fsevents": 29 | return 30 | 31 | os.mkdir(os.path.join(root, "foo")) 32 | filelist = ["foo"] 33 | 34 | self.assertFileList(root, filelist) 35 | 36 | self.suspendWatchman() 37 | 38 | filelist = ["foo"] 39 | for i in range(3000): 40 | self.touchRelative(root, "foo", str(i)) 41 | filelist.append(f"foo/{i}") 42 | 43 | self.resumeWatchman() 44 | 45 | self.watchmanCommand( 46 | "debug-kqueue-and-fsevents-recrawl", root, os.path.join(root, "foo") 47 | ) 48 | 49 | self.assertFileList(root, filelist) 50 | -------------------------------------------------------------------------------- /watchman/integration/test_remove.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | import shutil 12 | 13 | from watchman.integration.lib import WatchmanTestCase 14 | 15 | 16 | @WatchmanTestCase.expand_matrix 17 | class TestRemove(WatchmanTestCase.WatchmanTestCase): 18 | def test_remove(self) -> None: 19 | root = self.mkdtemp() 20 | os.makedirs(os.path.join(root, "one", "two")) 21 | self.touchRelative(root, "one", "onefile") 22 | self.touchRelative(root, "one", "two", "twofile") 23 | self.touchRelative(root, "top") 24 | 25 | self.watchmanCommand("watch", root) 26 | self.assertFileList( 27 | root, files=["one", "one/onefile", "one/two", "one/two/twofile", "top"] 28 | ) 29 | 30 | shutil.rmtree(os.path.join(root, "one")) 31 | 32 | self.assertFileList(root, files=["top"]) 33 | 34 | self.touchRelative(root, "one") 35 | self.assertFileList(root, files=["top", "one"]) 36 | 37 | self.removeRelative(root, "one") 38 | self.assertFileList(root, files=["top"]) 39 | 40 | shutil.rmtree(root) 41 | os.makedirs(os.path.join(root, "notme")) 42 | 43 | self.assertWaitFor( 44 | lambda: not self.rootIsWatched(root), 45 | message="%s should be cancelled" % root, 46 | ) 47 | -------------------------------------------------------------------------------- /watchman/integration/test_perms.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | import unittest 12 | 13 | import pywatchman 14 | from watchman.integration.lib import WatchmanTestCase 15 | 16 | 17 | def is_root() -> bool: 18 | return hasattr(os, "geteuid") and os.geteuid() == 0 19 | 20 | 21 | @WatchmanTestCase.expand_matrix 22 | class TestPerms(WatchmanTestCase.WatchmanTestCase): 23 | def checkOSApplicability(self) -> None: 24 | if os.name == "nt": 25 | self.skipTest("N/A on Windows") 26 | 27 | @unittest.skipIf(is_root(), "N/A if root") 28 | def test_permDeniedSubDir(self) -> None: 29 | root = self.mkdtemp() 30 | subdir = os.path.join(root, "subdir") 31 | os.mkdir(subdir) 32 | os.chmod(subdir, 0) 33 | self.watchmanCommand("watch", root) 34 | res = self.watchmanCommand( 35 | "query", root, {"expression": ["exists"], "fields": ["name"]} 36 | ) 37 | self.assertRegex(res["warning"], "Marking this portion of the tree deleted") 38 | 39 | @unittest.skipIf(is_root(), "N/A if root") 40 | def test_permDeniedRoot(self) -> None: 41 | root = self.mkdtemp() 42 | os.chmod(root, 0) 43 | with self.assertRaisesRegex(pywatchman.CommandError, "(open|opendir|realpath)"): 44 | self.watchmanCommand("watch", root) 45 | -------------------------------------------------------------------------------- /watchman/integration/test_absroot.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import os 11 | import os.path 12 | 13 | import pywatchman 14 | from watchman.integration.lib import WatchmanTestCase 15 | from watchman.integration.lib.path_utils import norm_absolute_path 16 | 17 | 18 | @WatchmanTestCase.expand_matrix 19 | class TestAbsoluteRoot(WatchmanTestCase.WatchmanTestCase): 20 | def test_dot(self) -> None: 21 | root = self.mkdtemp() 22 | 23 | save_dir = os.getcwd() 24 | try: 25 | os.chdir(root) 26 | 27 | dot = "" if os.name == "nt" else "." 28 | 29 | if self.transport == "cli": 30 | res = self.watchmanCommand("watch", dot) 31 | self.assertEqual(root, norm_absolute_path(res["watch"])) 32 | else: 33 | with self.assertRaises(pywatchman.WatchmanError) as ctx: 34 | self.watchmanCommand("watch", dot) 35 | 36 | self.assertIn("must be absolute", str(ctx.exception)) 37 | 38 | finally: 39 | os.chdir(save_dir) 40 | 41 | def test_root(self) -> None: 42 | if os.name != "nt": 43 | with self.assertRaises(pywatchman.WatchmanError) as ctx: 44 | self.watchmanCommand("watch", "/") 45 | 46 | self.assertIn("cannot watch", str(ctx.exception)) 47 | -------------------------------------------------------------------------------- /watchman/integration/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | add_fb_python_library(integration_lib 7 | SOURCES 8 | lib/__init__.py 9 | lib/Interrupt.py 10 | lib/TempDir.py 11 | lib/WatchmanEdenTestCase.py 12 | lib/WatchmanInstance.py 13 | lib/WatchmanSCMTestCase.py 14 | lib/WatchmanTestCase.py 15 | lib/node.py 16 | lib/path_utils.py 17 | ) 18 | 19 | file(GLOB TEST_MODULES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "test_*.py") 20 | 21 | # TODO: hook up these tests: 22 | list(REMOVE_ITEM TEST_MODULES 23 | test_eden_journal.py 24 | test_eden_pathgen.py 25 | test_eden_sha1.py 26 | test_eden_since.py 27 | test_eden_subscribe.py 28 | test_eden_unmount.py 29 | test_eden_watch_root.py 30 | test_nodejs.py 31 | test_wm_wait.py 32 | test_pcre.py 33 | ) 34 | 35 | add_fb_python_unittest(test_py 36 | SOURCES 37 | ${TEST_MODULES} 38 | 39 | DEPENDS 40 | pywatchman 41 | integration_lib 42 | 43 | WORKING_DIRECTORY 44 | ${CMAKE_BINARY_DIR} 45 | 46 | ENV 47 | "YARN_PATH=${YARN}" 48 | "NODE_BIN=${NODE}" 49 | "HGUSER=John Smith " 50 | "NOSCMLOG=1" 51 | "WATCHMAN_EMPTY_ENV_VAR=" 52 | "WATCHMAN_NO_SPAWN=1" 53 | "WATCHMAN_BINARY=$" 54 | "WATCHMAN_WAIT_PATH=$" 55 | "WATCHMAN_SRC_DIR=${CMAKE_SOURCE_DIR}/watchman" 56 | ) 57 | -------------------------------------------------------------------------------- /watchman/rust/watchman_client/examples/state.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | use std::path::PathBuf; 9 | 10 | use clap::Parser; 11 | use watchman_client::prelude::*; 12 | 13 | /// Exercise the state-enter and state-leave commands 14 | #[derive(Debug, Parser)] 15 | struct Cli { 16 | #[arg(default_value = ".")] 17 | path: PathBuf, 18 | } 19 | 20 | #[tokio::main(flavor = "current_thread")] 21 | async fn main() -> Result<(), Box> { 22 | if let Err(err) = run().await { 23 | // Print a prettier error than the default 24 | eprintln!("{}", err); 25 | std::process::exit(1); 26 | } 27 | Ok(()) 28 | } 29 | 30 | async fn run() -> Result<(), Box> { 31 | let opt = Cli::parse(); 32 | let client = Connector::new().connect().await?; 33 | let resolved = client 34 | .resolve_root(CanonicalPath::canonicalize(opt.path)?) 35 | .await?; 36 | 37 | println!("resolved watch to {:?}", resolved); 38 | 39 | client 40 | .state_enter(&resolved, "woot", SyncTimeout::Default, None) 41 | .await?; 42 | println!("asserted woot state"); 43 | tokio::time::sleep(std::time::Duration::from_secs(10)).await; 44 | client 45 | .state_leave(&resolved, "woot", SyncTimeout::Default, None) 46 | .await?; 47 | println!("vacated woot state"); 48 | 49 | Ok(()) 50 | } 51 | -------------------------------------------------------------------------------- /watchman/integration/test_bulkstat.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | # pyre-unsafe 7 | 8 | 9 | from watchman.integration.lib import WatchmanInstance, WatchmanTestCase 10 | 11 | 12 | @WatchmanTestCase.expand_matrix 13 | class TestBulkStat(WatchmanTestCase.WatchmanTestCase): 14 | def test_bulkstat_on(self) -> None: 15 | config = {"_use_bulkstat": True} 16 | with WatchmanInstance.Instance(config=config) as inst: 17 | inst.start() 18 | self.getClient(inst, replace_cached=True) 19 | 20 | root = self.mkdtemp() 21 | # pyre-fixme[16]: `TestBulkStat` has no attribute `client`. 22 | self.client.query("watch", root) 23 | 24 | self.touchRelative(root, "foo") 25 | self.touchRelative(root, "bar") 26 | self.assertFileList(root, ["foo", "bar"]) 27 | 28 | def test_bulkstat_off(self) -> None: 29 | config = {"_use_bulkstat": False} 30 | with WatchmanInstance.Instance(config=config) as inst: 31 | inst.start() 32 | self.getClient(inst, replace_cached=True) 33 | 34 | root = self.mkdtemp() 35 | # pyre-fixme[16]: `TestBulkStat` has no attribute `client`. 36 | self.client.query("watch", root) 37 | 38 | self.touchRelative(root, "foo") 39 | self.touchRelative(root, "bar") 40 | self.assertFileList(root, ["foo", "bar"]) 41 | -------------------------------------------------------------------------------- /watchman/java/BUCK: -------------------------------------------------------------------------------- 1 | java_binary( 2 | name = "watchman", 3 | deps = [ 4 | ":watchman-lib", 5 | ], 6 | ) 7 | 8 | zip_file( 9 | name = "watchman-lib.src", 10 | srcs = glob(["src/**/*.java"]), 11 | licenses = [ 12 | "LICENSE", 13 | ], 14 | visibility = [ 15 | "PUBLIC", 16 | ], 17 | ) 18 | 19 | java_library( 20 | name = "watchman-lib", 21 | srcs = [ 22 | ":watchman-lib.src", 23 | ], 24 | annotation_processor_deps = [ 25 | "//third-party/guava:guava", 26 | "//third-party/immutables:generator", 27 | "//third-party/immutables:value-processor", 28 | ], 29 | annotation_processors = [ 30 | "org.immutables.value.processor.Processor", 31 | ], 32 | source = "7", 33 | target = "7", 34 | tests = [ 35 | ":watchman-tests", 36 | ], 37 | visibility = [ 38 | "PUBLIC", 39 | ], 40 | deps = [ 41 | "//third-party/guava:guava", 42 | "//third-party/immutables:value", 43 | "//third-party/jna:jna", 44 | "//third-party/jna:jna-platform", 45 | "//third-party/jsr-305:jsr-305", 46 | "//third-party/nuprocess:nuprocess", 47 | ], 48 | ) 49 | 50 | java_test( 51 | name = "watchman-tests", 52 | srcs = glob(["test/**/*.java"]), 53 | source = "7", 54 | target = "7", 55 | deps = [ 56 | ":watchman-lib", 57 | "//third-party/guava:guava", 58 | "//third-party/hamcrest:hamcrest-2", 59 | "//third-party/java/junit:junit", 60 | "//third-party/mockito:mockito", 61 | ], 62 | ) 63 | -------------------------------------------------------------------------------- /watchman/thirdparty/libart/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, Armon Dadgar 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the organization nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL ARMON DADGAR BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | -------------------------------------------------------------------------------- /watchman/cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | # @generated by autocargo from //watchman/cli:cli 2 | 3 | [package] 4 | name = "watchmanctl" 5 | version = "0.1.0" 6 | authors = ["Source Control Oncall oncall+source_control@xmail.facebook.com"] 7 | edition = "2021" 8 | repository = "https://github.com/facebook/watchman" 9 | license = "MIT" 10 | 11 | [dependencies] 12 | ahash = "0.8" 13 | anyhow = "1.0.86" 14 | duct = "0.13.6" 15 | jwalk = "0.6" 16 | serde = { version = "1.0.185", features = ["derive", "rc"] } 17 | serde_json = { version = "1.0.132", features = ["float_roundtrip", "unbounded_depth"] } 18 | structopt = "0.3.26" 19 | sysinfo = "0.30.11" 20 | tabular = "0.2.0" 21 | tokio = { version = "1.41.0", features = ["full", "test-util", "tracing"] } 22 | watchman_client = { version = "0.9.0", path = "../rust/watchman_client" } 23 | 24 | [target.'cfg(target_os = "linux")'.dependencies] 25 | nix = { version = "0.29.0", features = ["dir", "event", "hostname", "inotify", "ioctl", "mman", "mount", "net", "poll", "ptrace", "reboot", "resource", "sched", "term", "time", "user", "zerocopy"] } 26 | 27 | [target.'cfg(target_os = "macos")'.dependencies] 28 | nix = { version = "0.29.0", features = ["dir", "event", "hostname", "inotify", "ioctl", "mman", "mount", "net", "poll", "ptrace", "reboot", "resource", "sched", "term", "time", "user", "zerocopy"] } 29 | 30 | [target.'cfg(unix)'.dependencies] 31 | nix = { version = "0.29.0", features = ["dir", "event", "hostname", "inotify", "ioctl", "mman", "mount", "net", "poll", "ptrace", "reboot", "resource", "sched", "term", "time", "user", "zerocopy"] } 32 | 33 | [features] 34 | default = [] 35 | fb = [] 36 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-present Meta Platforms, Inc. All Rights Reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | * Neither the name Facebook nor the names of its contributors may be used to 14 | endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 24 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /watchman/ruby/ruby-watchman/Rakefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. All Rights Reserved. 2 | 3 | require 'rubygems' 4 | require 'rake/clean' 5 | require 'rspec/core/rake_task' 6 | require File.expand_path('lib/ruby-watchman/version.rb', File.dirname(__FILE__)) 7 | 8 | CLEAN.include Rake::FileList['*.gem', '**/*.so', '**/*.bundle', '**/*.o', '**/mkmf.log', '**/Makefile'] 9 | 10 | RSpec::Core::RakeTask.new(:spec) 11 | 12 | task :default => :all 13 | 14 | desc 'Build and run specs' 15 | task :all => [:make, :spec] 16 | 17 | file 'ext/ruby-watchman/Makefile' => %w[ 18 | ext/ruby-watchman/depend 19 | ext/ruby-watchman/extconf.rb 20 | ] do 21 | Dir.chdir('ext/ruby-watchman') { ruby './extconf.rb' } 22 | end 23 | 24 | desc 'Build extension' 25 | task :make => %w[ 26 | ext/ruby-watchman/Makefile 27 | ext/ruby-watchman/watchman.c 28 | ext/ruby-watchman/watchman.h 29 | ] do 30 | Dir.chdir('ext/ruby-watchman') { system 'make' } 31 | end 32 | EXT_FILE = "ext/ruby-watchman/ext.#{RbConfig::CONFIG['DLEXT']}" 33 | file EXT_FILE => :make 34 | 35 | GEM_FILE_DEPENDENCIES = Dir[ 36 | 'ext/ruby-watchman/**/*.{c,h,rb}', 37 | 'ext/ruby-watchman/depend', 38 | 'lib/**/*.rb', 39 | 'spec/**/*.rb' 40 | ] + [EXT_FILE] # not actually included in gem, but we want to be sure it builds 41 | 42 | GEM_FILE = "ruby-watchman-#{RubyWatchman::VERSION}.gem" 43 | 44 | file GEM_FILE => GEM_FILE_DEPENDENCIES do 45 | system 'gem build ruby-watchman.gemspec' 46 | end 47 | 48 | desc 'Build gem ("gem build")' 49 | task :build => GEM_FILE 50 | 51 | desc 'Publish gem ("gem push")' 52 | task :push => :build do 53 | system "gem push #{GEM_FILE}" 54 | end 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /built/ 2 | /external 3 | buck-out 4 | buck-cache 5 | .buckd 6 | .idea 7 | *.iml 8 | /Makefile.in 9 | /test-driver 10 | /aclocal.m4 11 | /autom4te.cache/ 12 | /configure 13 | /depcomp 14 | /install-sh 15 | /missing 16 | /config.log 17 | .deps/ 18 | .windeps 19 | /*.in 20 | /Makefile 21 | *.o 22 | /config.status 23 | *.swp 24 | /compile 25 | /stamp-h1 26 | /config.h* 27 | /thirdparty/jansson/jansson_config.h 28 | /compile 29 | /tests/*.t 30 | /*.t 31 | .dirstamp 32 | *.a 33 | /tests/integration/.watchman.* 34 | *.rpm 35 | /config.sub 36 | /config.guess 37 | /configure.lineno 38 | /python/build 39 | /python/dist/ 40 | /watchman/python/pywatchman.egg-info/ 41 | *.pyc 42 | *.pyd 43 | *.so 44 | *.obj 45 | *.exe 46 | *.dll 47 | *.pdb 48 | /test-suite.log 49 | /tests/*.log 50 | /tests/*.trs 51 | /a 52 | /arc 53 | /node/package-lock.json 54 | /node/node_modules 55 | /node/bser/node_modules 56 | /website/node_modules 57 | /website/build 58 | /website/src/watchman/docs 59 | /website/src/watchman/*.js 60 | /website/core/metadata.js 61 | /website/.sass-cache 62 | /website/_site 63 | /npm-debug.log 64 | /Debug 65 | .deps 66 | *.dep 67 | *.nativecodeanalysis.xml 68 | /watchman-test.log 69 | Watchman.vcxproj.* 70 | Watchman.vcxproj 71 | *.opensdf 72 | *.sdf 73 | *.sln 74 | *.suo 75 | m4/ 76 | .libs/ 77 | *.lo 78 | *.la 79 | /tests/integration/cppclient.t 80 | libtool 81 | ltmain.sh 82 | cppclient/watchmanclient.pc 83 | /website/.jekyll-metadata 84 | /CMakeCache.txt 85 | /CMakeFiles 86 | /*.cmake 87 | /Testing 88 | /install_manifest.txt 89 | *.vcxproj 90 | *.dir 91 | /x64 92 | /Release 93 | /Debug 94 | *.filters 95 | /.vs 96 | /external 97 | /common 98 | /eden 99 | -------------------------------------------------------------------------------- /watchman/python/pywatchman/capabilities.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Meta Platforms, Inc. and affiliates. 2 | # 3 | # This source code is licensed under the MIT license found in the 4 | # LICENSE file in the root directory of this source tree. 5 | 6 | 7 | import re 8 | 9 | 10 | def parse_version(vstr) -> int: 11 | res = 0 12 | for n in vstr.split("."): 13 | res = res * 1000 14 | res = res + int(n) 15 | return res 16 | 17 | 18 | cap_versions = { 19 | "cmd-watch-del-all": "3.1.1", 20 | "cmd-watch-project": "3.1", 21 | "relative_root": "3.3", 22 | "term-dirname": "3.1", 23 | "term-idirname": "3.1", 24 | "wildmatch": "3.7", 25 | } 26 | 27 | 28 | def check(version, name: str): 29 | if name in cap_versions: 30 | return version >= parse_version(cap_versions[name]) 31 | return False 32 | 33 | 34 | def synthesize(vers, opts): 35 | """Synthesize a capability enabled version response 36 | This is a very limited emulation for relatively recent feature sets 37 | """ 38 | parsed_version = parse_version(vers["version"]) 39 | vers["capabilities"] = {} 40 | for name in opts["optional"]: 41 | vers["capabilities"][name] = check(parsed_version, name) 42 | failed = False # noqa: F841 T25377293 Grandfathered in 43 | for name in opts["required"]: 44 | have = check(parsed_version, name) 45 | vers["capabilities"][name] = have 46 | if not have: 47 | vers["error"] = ( 48 | "client required capabilities [" 49 | + name 50 | + "] not supported by this server" 51 | ) 52 | return vers 53 | -------------------------------------------------------------------------------- /watchman/RingBuffer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | namespace watchman { 13 | 14 | /** 15 | * Fixed-size, lock-free ring buffer. Used for low-latency event logging. 16 | */ 17 | template 18 | class RingBuffer { 19 | public: 20 | explicit RingBuffer(uint32_t capacity) 21 | : ring_{capacity}, lastClear_{ring_.currentHead()} {} 22 | 23 | void clear() { 24 | lastClear_.store(ring_.currentHead(), std::memory_order_release); 25 | } 26 | 27 | void write(const T& entry) { 28 | ring_.write(entry); 29 | } 30 | 31 | std::vector readAll() const { 32 | auto lastClear = lastClear_.load(std::memory_order_acquire); 33 | 34 | std::vector entries; 35 | 36 | auto head = ring_.currentHead(); 37 | T entry; 38 | while (head.moveBackward() && head >= lastClear && 39 | ring_.tryRead(entry, head)) { 40 | entries.push_back(std::move(entry)); 41 | } 42 | std::reverse(entries.begin(), entries.end()); 43 | return entries; 44 | } 45 | 46 | private: 47 | RingBuffer(RingBuffer&&) = delete; 48 | RingBuffer(const RingBuffer&) = delete; 49 | RingBuffer& operator=(RingBuffer&&) = delete; 50 | RingBuffer& operator=(const RingBuffer&) = delete; 51 | 52 | folly::LockFreeRingBuffer ring_; 53 | std::atomic::Cursor> lastClear_; 54 | }; 55 | 56 | } // namespace watchman 57 | -------------------------------------------------------------------------------- /watchman/integration/test_log.py: -------------------------------------------------------------------------------- 1 | # vim:ts=4:sw=4:et: 2 | # Copyright (c) Meta Platforms, Inc. and affiliates. 3 | # 4 | # This source code is licensed under the MIT license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # pyre-unsafe 8 | 9 | 10 | import pywatchman 11 | from watchman.integration.lib import WatchmanTestCase 12 | 13 | 14 | @WatchmanTestCase.expand_matrix 15 | class TestLog(WatchmanTestCase.WatchmanTestCase): 16 | def test_invalidNumArgsLogLevel(self) -> None: 17 | for params in [["log-level"], ["log-level", "debug", "extra"]]: 18 | with self.assertRaises(pywatchman.WatchmanError) as ctx: 19 | self.watchmanCommand(*params) 20 | 21 | self.assertIn("wrong number of arguments", str(ctx.exception)) 22 | 23 | def test_invalidLevelLogLevel(self) -> None: 24 | with self.assertRaises(pywatchman.WatchmanError) as ctx: 25 | self.watchmanCommand("log-level", "invalid") 26 | 27 | self.assertIn("invalid log level", str(ctx.exception)) 28 | 29 | def test_invalidNumArgsLog(self) -> None: 30 | for params in [["log"], ["log", "debug"], ["log", "debug", "test", "extra"]]: 31 | with self.assertRaises(pywatchman.WatchmanError) as ctx: 32 | self.watchmanCommand(*params) 33 | 34 | self.assertIn("wrong number of arguments", str(ctx.exception)) 35 | 36 | def test_invalidLevelLog(self) -> None: 37 | with self.assertRaises(pywatchman.WatchmanError) as ctx: 38 | self.watchmanCommand("log", "invalid", "test") 39 | 40 | self.assertIn("invalid log level", str(ctx.exception)) 41 | --------------------------------------------------------------------------------