rust/hg-cpython/src/copy_tracing.rs
changeset 46057 e0313b0a6f7e
parent 45945 50c5ee3bdf9a
child 46149 294d5aca4ff5
equal deleted inserted replaced
46056:c407513a44a3 46057:e0313b0a6f7e
     9 use cpython::PyTuple;
     9 use cpython::PyTuple;
    10 use cpython::Python;
    10 use cpython::Python;
    11 
    11 
    12 use hg::copy_tracing::combine_changeset_copies;
    12 use hg::copy_tracing::combine_changeset_copies;
    13 use hg::copy_tracing::ChangedFiles;
    13 use hg::copy_tracing::ChangedFiles;
       
    14 use hg::copy_tracing::DataHolder;
    14 use hg::copy_tracing::RevInfo;
    15 use hg::copy_tracing::RevInfo;
    15 use hg::utils::hg_path::HgPathBuf;
    16 use hg::copy_tracing::RevInfoMaker;
    16 use hg::Revision;
    17 use hg::Revision;
    17 
    18 
    18 /// Combines copies information contained into revision `revs` to build a copy
    19 /// Combines copies information contained into revision `revs` to build a copy
    19 /// map.
    20 /// map.
    20 ///
    21 ///
    55     //
    56     //
    56     // No errors are expected from the Python side, and they will should only
    57     // No errors are expected from the Python side, and they will should only
    57     // happens in case of programing error or severe data corruption. Such
    58     // happens in case of programing error or severe data corruption. Such
    58     // errors will raise panic and the rust-cpython harness will turn them into
    59     // errors will raise panic and the rust-cpython harness will turn them into
    59     // Python exception.
    60     // Python exception.
    60     let rev_info_maker = |rev: Revision| -> RevInfo {
    61     let rev_info_maker: RevInfoMaker<PyBytes> =
    61         let res: PyTuple = rev_info
    62         Box::new(|rev: Revision, d: &mut DataHolder<PyBytes>| -> RevInfo {
    62             .call(py, (rev,), None)
    63             let res: PyTuple = rev_info
    63             .expect("rust-copy-tracing: python call to `rev_info` failed")
    64                 .call(py, (rev,), None)
    64             .cast_into(py)
    65                 .expect("rust-copy-tracing: python call to `rev_info` failed")
    65             .expect(
       
    66                 "rust-copy_tracing: python call to `rev_info` returned \
       
    67                 unexpected non-Tuple value",
       
    68             );
       
    69         let p1 = res.get_item(py, 0).extract(py).expect(
       
    70             "rust-copy-tracing: \
       
    71             rev_info return is invalid, first item is a not a revision",
       
    72         );
       
    73         let p2 = res.get_item(py, 1).extract(py).expect(
       
    74             "rust-copy-tracing: \
       
    75             rev_info return is invalid, second item is a not a revision",
       
    76         );
       
    77 
       
    78         let changes = res.get_item(py, 2);
       
    79 
       
    80         let files;
       
    81         if !changes
       
    82             .hasattr(py, "copied_from_p1")
       
    83             .expect("rust-copy-tracing: python call to `hasattr` failed")
       
    84         {
       
    85             files = ChangedFiles::new_empty();
       
    86         } else {
       
    87             let p1_copies: PyDict = changes
       
    88                 .getattr(py, "copied_from_p1")
       
    89                 .expect(
       
    90                     "rust-copy-tracing: retrieval of python attribute \
       
    91                     `copied_from_p1` failed",
       
    92                 )
       
    93                 .cast_into(py)
    66                 .cast_into(py)
    94                 .expect(
    67                 .expect(
    95                     "rust-copy-tracing: failed to convert `copied_from_p1` \
    68                     "rust-copy_tracing: python call to `rev_info` returned \
    96                     to PyDict",
    69                     unexpected non-Tuple value",
    97                 );
    70                 );
    98             let p1_copies: PyResult<_> = p1_copies
    71             let p1 = res.get_item(py, 0).extract(py).expect(
    99                 .items(py)
    72                 "rust-copy-tracing: rev_info return is invalid, first item \
   100                 .iter()
    73                 is a not a revision",
   101                 .map(|(key, value)| {
    74             );
   102                     let key = key.extract::<PyBytes>(py).expect(
    75             let p2 = res.get_item(py, 1).extract(py).expect(
   103                         "rust-copy-tracing: conversion of copy destination to\
    76                 "rust-copy-tracing: rev_info return is invalid, first item \
   104                         PyBytes failed",
    77                 is a not a revision",
   105                     );
    78             );
   106                     let key = key.data(py);
       
   107                     let value = value.extract::<PyBytes>(py).expect(
       
   108                         "rust-copy-tracing: conversion of copy source to \
       
   109                         PyBytes failed",
       
   110                     );
       
   111                     let value = value.data(py);
       
   112                     Ok((
       
   113                         HgPathBuf::from_bytes(key),
       
   114                         HgPathBuf::from_bytes(value),
       
   115                     ))
       
   116                 })
       
   117                 .collect();
       
   118 
    79 
   119             let p2_copies: PyDict = changes
    80             let files = match res.get_item(py, 2).extract::<PyBytes>(py) {
   120                 .getattr(py, "copied_from_p2")
    81                 Ok(raw) => {
   121                 .expect(
    82                     // Give responsability for the raw bytes lifetime to
   122                     "rust-copy-tracing: retrieval of python attribute \
    83                     // hg-core
   123                     `copied_from_p2` failed",
    84                     d.data = Some(raw);
   124                 )
    85                     let addrs = d.data.as_ref().expect(
   125                 .cast_into(py)
    86                         "rust-copy-tracing: failed to get a reference to the \
   126                 .expect(
    87                         raw bytes for copy data").data(py);
   127                     "rust-copy-tracing: failed to convert `copied_from_p2` \
    88                     ChangedFiles::new(addrs)
   128                     to PyDict",
    89                 }
   129                 );
    90                 // value was presumably None, meaning they was no copy data.
   130             let p2_copies: PyResult<_> = p2_copies
    91                 Err(_) => ChangedFiles::new_empty(),
   131                 .items(py)
    92             };
   132                 .iter()
       
   133                 .map(|(key, value)| {
       
   134                     let key = key.extract::<PyBytes>(py).expect(
       
   135                         "rust-copy-tracing: conversion of copy destination to \
       
   136                         PyBytes failed");
       
   137                     let key = key.data(py);
       
   138                     let value = value.extract::<PyBytes>(py).expect(
       
   139                         "rust-copy-tracing: conversion of copy source to \
       
   140                         PyBytes failed",
       
   141                     );
       
   142                     let value = value.data(py);
       
   143                     Ok((
       
   144                         HgPathBuf::from_bytes(key),
       
   145                         HgPathBuf::from_bytes(value),
       
   146                     ))
       
   147                 })
       
   148                 .collect();
       
   149 
    93 
   150             let removed: PyObject = changes.getattr(py, "removed").expect(
    94             (p1, p2, files)
   151                 "rust-copy-tracing: retrieval of python attribute \
    95         });
   152                     `removed` failed",
       
   153             );
       
   154             let removed: PyResult<_> = removed
       
   155                 .iter(py)
       
   156                 .expect(
       
   157                     "rust-copy-tracing: getting a python iterator over the \
       
   158                     `removed` set failed",
       
   159                 )
       
   160                 .map(|filename| {
       
   161                     let filename = filename
       
   162                         .expect(
       
   163                             "rust-copy-tracing: python iteration over the \
       
   164                             `removed` set failed",
       
   165                         )
       
   166                         .extract::<PyBytes>(py)
       
   167                         .expect(
       
   168                             "rust-copy-tracing: \
       
   169                             conversion of `removed` item to PyBytes failed",
       
   170                         );
       
   171                     let filename = filename.data(py);
       
   172                     Ok(HgPathBuf::from_bytes(filename))
       
   173                 })
       
   174                 .collect();
       
   175 
       
   176             let merged: PyObject = changes.getattr(py, "merged").expect(
       
   177                 "rust-copy-tracing: retrieval of python attribute \
       
   178                     `merged` failed",
       
   179             );
       
   180             let merged: PyResult<_> = merged
       
   181                 .iter(py)
       
   182                 .expect(
       
   183                     "rust-copy-tracing: getting a python iterator over the \
       
   184                     `merged` set failed",
       
   185                 )
       
   186                 .map(|filename| {
       
   187                     let filename = filename
       
   188                         .expect(
       
   189                             "rust-copy-tracing: python iteration over the \
       
   190                             `merged` set failed",
       
   191                         )
       
   192                         .extract::<PyBytes>(py)
       
   193                         .expect(
       
   194                             "rust-copy-tracing: \
       
   195                             conversion of `merged` item to PyBytes failed",
       
   196                         );
       
   197                     let filename = filename.data(py);
       
   198                     Ok(HgPathBuf::from_bytes(filename))
       
   199                 })
       
   200                 .collect();
       
   201 
       
   202             let salvaged: PyObject = changes.getattr(py, "salvaged").expect(
       
   203                 "rust-copy-tracing: retrieval of python attribute \
       
   204                     `salvaged` failed",
       
   205             );
       
   206             let salvaged: PyResult<_> = salvaged
       
   207                 .iter(py)
       
   208                 .expect(
       
   209                     "rust-copy-tracing: getting a python iterator over the \
       
   210                     `salvaged` set failed",
       
   211                 )
       
   212                 .map(|filename| {
       
   213                     let filename = filename
       
   214                         .expect(
       
   215                             "rust-copy-tracing: python iteration over the \
       
   216                             `salvaged` set failed",
       
   217                         )
       
   218                         .extract::<PyBytes>(py)
       
   219                         .expect(
       
   220                             "rust-copy-tracing: \
       
   221                             conversion of `salvaged` item to PyBytes failed",
       
   222                         );
       
   223                     let filename = filename.data(py);
       
   224                     Ok(HgPathBuf::from_bytes(filename))
       
   225                 })
       
   226                 .collect();
       
   227             files = ChangedFiles::new(
       
   228                 removed.unwrap(),
       
   229                 merged.unwrap(),
       
   230                 salvaged.unwrap(),
       
   231                 p1_copies.unwrap(),
       
   232                 p2_copies.unwrap(),
       
   233             );
       
   234         }
       
   235 
       
   236         (p1, p2, files)
       
   237     };
       
   238     let children: PyResult<_> = children
    96     let children: PyResult<_> = children
   239         .items(py)
    97         .items(py)
   240         .iter()
    98         .iter()
   241         .map(|(k, v)| {
    99         .map(|(k, v)| {
   242             let v: &PyList = v.cast_as(py)?;
   100             let v: &PyList = v.cast_as(py)?;
   248 
   106 
   249     let res = combine_changeset_copies(
   107     let res = combine_changeset_copies(
   250         revs?,
   108         revs?,
   251         children?,
   109         children?,
   252         target_rev,
   110         target_rev,
   253         &rev_info_maker,
   111         rev_info_maker,
   254         &is_ancestor_wrap,
   112         &is_ancestor_wrap,
   255     );
   113     );
   256     let out = PyDict::new(py);
   114     let out = PyDict::new(py);
   257     for (dest, source) in res.into_iter() {
   115     for (dest, source) in res.into_iter() {
   258         out.set_item(
   116         out.set_item(