def METHOD_NAME(project_dir, name, value):
    """Set a substitution path property in a gradle `local.properties` file.
    Given the path to a gradle project directory, this helper will set the named
    property to the given path value in that directory's `local.properties` file.
    If the named property already exists with the correct value then it will
    silently succeed; if the named property already exists with a different value
    then it will noisily fail.
    """
    project_dir = Path(project_dir).resolve()
    properties_file = project_dir / "local.properties"
    step_msg(f"Configuring local publication in project at {properties_file}")
    name_eq = name + "="
    abs_value = Path(value).resolve()
    # Check if the named property already exists.
    if properties_file.exists():
        with properties_file.open() as f:
            for ln in f:
                # Not exactly a thorough parser, but should be good enough...
                if ln.startswith(name_eq):
                    cur_value = ln[len(name_eq):].strip()
                    if Path(project_dir, cur_value).resolve() != abs_value:
                        fatal_error(f"Conflicting property {name}={cur_value} (not {abs_value})")
                    return
    # The file does not contain the required property, append it.
    # Note that the project probably expects a path relative to the project root.
    ancestor = Path(os.path.commonpath([project_dir, abs_value]))
    relpath = Path(".")
    for _ in project_dir.parts[len(ancestor.parts):]:
        relpath /= ".."
    for nm in abs_value.parts[len(ancestor.parts):]:
        relpath /= nm
    step_msg(f"Setting relative path from {project_dir} to {abs_value} as {relpath}")
    with properties_file.open("a") as f:
        f.write(f"{name}={relpath}\n")