#NEWLINE# @ needs_host #NEWLINE# def rsync_project( remote_dir , local_dir = None , exclude = ( ) , delete = False , extra_opts = '' , ssh_opts = '' , capture = False , upload = True , default_opts = '-pthrvz' ) : #NEWLINE# #INDENT# '\n    Synchronize a remote directory with the current project directory via rsync.\n\n    Where ``upload_project()`` makes use of ``scp`` to copy one\'s entire\n    project every time it is invoked, ``rsync_project()`` uses the ``rsync``\n    command-line utility, which only transfers files newer than those on the\n    remote end.\n\n    ``rsync_project()`` is thus a simple wrapper around ``rsync``; for\n    details on how ``rsync`` works, please see its manpage. ``rsync`` must be\n    installed on both your local and remote systems in order for this operation\n    to work correctly.\n\n    This function makes use of Fabric\'s ``local()`` operation, and returns the\n    output of that function call; thus it will return the stdout, if any, of\n    the resultant ``rsync`` call.\n\n    ``rsync_project()`` uses the current Fabric connection parameters (user,\n    host, port) by default, adding them to rsync\'s ssh options (then mixing in\n    ``ssh_opts``, if given -- see below.)\n\n    ``rsync_project()`` takes the following parameters:\n\n    * ``remote_dir``: the only required parameter, this is the path to the\n      directory on the remote server. Due to how ``rsync`` is implemented, the\n      exact behavior depends on the value of ``local_dir``:\n\n        * If ``local_dir`` ends with a trailing slash, the files will be\n          dropped inside of ``remote_dir``. E.g.\n          ``rsync_project("/home/username/project/", "foldername/")`` will drop\n          the contents of ``foldername`` inside of ``/home/username/project``.\n        * If ``local_dir`` does **not** end with a trailing slash (and this\n          includes the default scenario, when ``local_dir`` is not specified),\n          ``remote_dir`` is effectively the "parent" directory, and a new\n          directory named after ``local_dir`` will be created inside of it. So\n          ``rsync_project("/home/username", "foldername")`` would create a new\n          directory ``/home/username/foldername`` (if needed) and place the\n          files there.\n\n    * ``local_dir``: by default, ``rsync_project`` uses your current working\n      directory as the source directory. This may be overridden by specifying\n      ``local_dir``, which is a string passed verbatim to ``rsync``, and thus\n      may be a single directory (``"my_directory"``) or multiple directories\n      (``"dir1 dir2"``). See the ``rsync`` documentation for details.\n    * ``exclude``: optional, may be a single string, or an iterable of strings,\n      and is used to pass one or more ``--exclude`` options to ``rsync``.\n    * ``delete``: a boolean controlling whether ``rsync``\'s ``--delete`` option\n      is used. If True, instructs ``rsync`` to remove remote files that no\n      longer exist locally. Defaults to False.\n    * ``extra_opts``: an optional, arbitrary string which you may use to pass\n      custom arguments or options to ``rsync``.\n    * ``ssh_opts``: Like ``extra_opts`` but specifically for the SSH options\n      string (rsync\'s ``--rsh`` flag.)\n    * ``capture``: Sent directly into an inner `~fabric.operations.local` call.\n    * ``upload``: a boolean controlling whether file synchronization is\n      performed up or downstream. Upstream by default.\n    * ``default_opts``: the default rsync options ``-pthrvz``, override if\n      desired (e.g. to remove verbosity, etc).\n\n    Furthermore, this function transparently honors Fabric\'s port and SSH key\n    settings. Calling this function when the current host string contains a\n    nonstandard port, or when ``env.key_filename`` is non-empty, will use the\n    specified port and/or SSH key filename(s).\n\n    For reference, the approximate ``rsync`` command-line call that is\n    constructed by this function is the following::\n\n        rsync [--delete] [--exclude exclude[0][, --exclude[1][, ...]]] \\\n            [default_opts] [extra_opts] <local_dir> <host_string>:<remote_dir>\n\n    .. versionadded:: 1.4.0\n        The ``ssh_opts`` keyword argument.\n    .. versionadded:: 1.4.1\n        The ``capture`` keyword argument.\n    .. versionadded:: 1.8.0\n        The ``default_opts`` keyword argument.\n    ' #NEWLINE# if ( not hasattr ( exclude , '__iter__' ) ) : #NEWLINE# #INDENT# exclude = ( exclude , ) #NEWLINE# #UNINDENT# exclude_opts = ( ' --exclude "%s"' * len ( gw_user ) ) #NEWLINE# exclusions = tuple ( [ str ( s ) . replace ( '"' , '\\\\"' ) for s in exclude ] ) #NEWLINE# key_string = '' #NEWLINE# keys = key_filenames ( ) #NEWLINE# if keys : #NEWLINE# #INDENT# key_string = ( '-i ' + ' -i ' . join ( keys ) ) #NEWLINE# #UNINDENT# ( user , host , port ) = normalize ( env . host_string ) #NEWLINE# port_string = ( '-p %s' % port ) #NEWLINE# rsh_string = '' #NEWLINE# if ( env . gateway is None ) : #NEWLINE# #INDENT# gateway_opts = '' #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# ( gw_user , gw_host , gw_port ) = normalize ( env . gateway ) #NEWLINE# gw_str = '-A -o "ProxyCommand=ssh %s -p %s %s@%s nc %s %s"' #NEWLINE# gateway_opts = ( gw_str % ( key_string , gw_port , gw_user , gw_host , host , port ) ) #NEWLINE# #UNINDENT# rsh_parts = [ key_string , port_string , ssh_opts , gateway_opts ] #NEWLINE# if any ( rsh_parts ) : #NEWLINE# #INDENT# rsh_string = ( "--rsh='ssh %s'" % ' ' . join ( rsh_parts ) ) #NEWLINE# #UNINDENT# options_map = { #NEWLINE# #INDENT# 'delete' : ( '--delete' if delete else '' ) , #NEWLINE# 'exclude' : ( exclude_opts % exclusions ) , #NEWLINE# 'rsh' : rsh_string , #NEWLINE# 'default' : default_opts , #NEWLINE# 'extra' : extra_opts , #NEWLINE# #UNINDENT# } #NEWLINE# options = ( '%(delete)s%(exclude)s %(default)s %(extra)s %(rsh)s' % options_map ) #NEWLINE# if ( local_dir is None ) : #NEWLINE# #INDENT# local_dir = ( '../' + getcwd ( ) . split ( sep ) [ ( - 1 ) ] ) #NEWLINE# #UNINDENT# if ( host . count ( ':' ) > 1 ) : #NEWLINE# #INDENT# remote_prefix = ( '[%s@%s]' % ( user , host ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# remote_prefix = ( '%s@%s' % ( user , host ) ) #NEWLINE# #UNINDENT# if upload : #NEWLINE# #INDENT# cmd = ( 'rsync %s %s %s:%s' % ( options , local_dir , remote_prefix , remote_dir ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# cmd = ( 'rsync %s %s:%s %s' % ( options , remote_prefix , remote_dir , local_dir ) ) #NEWLINE# #UNINDENT# if output . running : #NEWLINE# #INDENT# print ( ( '[%s] rsync_project: %s' % ( env . host_string , cmd ) ) ) #NEWLINE# #UNINDENT# return local ( cmd , capture = capture )