)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"00dcaffed7e2ab73fcebaec3d46649d4d068dd3c","unresolved":false,"context_lines":[{"line_number":8,"context_line":""},{"line_number":9,"context_line":"Do not replace the upload-marker DELETE with a POST-with-X-Delete-After;"},{"line_number":10,"context_line":"that will leave the marker in listings, tempting clients to try to abort"},{"line_number":11,"context_line":"it."},{"line_number":12,"context_line":""},{"line_number":13,"context_line":"Only consider the freshly-created manifest for Complete operations;"},{"line_number":14,"context_line":"attempting to abort an MPU or upload more segment data for an MPU after"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"ff570b3c_0e3ced2e","line":11,"updated":"2020-06-08 23:53:31.000000000","message":"I understand this to be a design idea that was rejected, if so this comment doesn\u0027t seem appropriate for a commit message","commit_id":"1b8f08a409f85c6072728ff062383334db02c9ca"}],"swift/common/middleware/s3api/controllers/multi_upload.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"80dc7d47af25a21b2be6f0843f33d42ca5953aff","unresolved":false,"context_lines":[{"line_number":116,"context_line":"                    \u0027object\u0027, \u0027upload-id\u0027)) \u003d\u003d upload_id"},{"line_number":117,"context_line":"                recently_completed \u003d cutoff \u003c S3Timestamp("},{"line_number":118,"context_line":"                    resp.sw_headers.get(\u0027x-timestamp\u0027))"},{"line_number":119,"context_line":"                print(dict(resp.headers), upload_id)"},{"line_number":120,"context_line":"                if upload_id_matches and recently_completed:"},{"line_number":121,"context_line":"                    return resp"},{"line_number":122,"context_line":"            except NoSuchKey:"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_688012c0","line":119,"updated":"2020-06-07 16:09:47.000000000","message":"remove print","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"521e53797a60de94115b94c10ab0c14fbb9b577a","unresolved":false,"context_lines":[{"line_number":116,"context_line":"                    \u0027object\u0027, \u0027upload-id\u0027)) \u003d\u003d upload_id"},{"line_number":117,"context_line":"                recently_completed \u003d cutoff \u003c S3Timestamp("},{"line_number":118,"context_line":"                    resp.sw_headers.get(\u0027x-timestamp\u0027))"},{"line_number":119,"context_line":"                print(dict(resp.headers), upload_id)"},{"line_number":120,"context_line":"                if upload_id_matches and recently_completed:"},{"line_number":121,"context_line":"                    return resp"},{"line_number":122,"context_line":"            except NoSuchKey:"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_b0da8548","line":119,"in_reply_to":"ff570b3c_688012c0","updated":"2020-06-08 17:52:58.000000000","message":"Done","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"80dc7d47af25a21b2be6f0843f33d42ca5953aff","unresolved":false,"context_lines":[{"line_number":128,"context_line":"            req.headers[\u0027X-Amz-Copy-Source\u0027] \u003d copy_source"},{"line_number":129,"context_line":""},{"line_number":130,"context_line":""},{"line_number":131,"context_line":"def _make_complete_body(req, s3_etag, yielded_anything):"},{"line_number":132,"context_line":"    result_elem \u003d Element(\u0027CompleteMultipartUploadResult\u0027)"},{"line_number":133,"context_line":""},{"line_number":134,"context_line":"    # NOTE: boto with sig v4 appends port to HTTP_HOST value at"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_680bf27b","line":131,"updated":"2020-06-07 16:09:47.000000000","message":"interesting little method extraction here","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"80dc7d47af25a21b2be6f0843f33d42ca5953aff","unresolved":false,"context_lines":[{"line_number":621,"context_line":"            req, self.app, upload_id,"},{"line_number":622,"context_line":"            completed_grace_period\u003dself.conf.completed_grace_period)"},{"line_number":623,"context_line":"        headers \u003d {\u0027Accept\u0027: \u0027application/json\u0027,"},{"line_number":624,"context_line":"                   sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027): upload_id}"},{"line_number":625,"context_line":"        for key, val in resp.headers.items():"},{"line_number":626,"context_line":"            _key \u003d key.lower()"},{"line_number":627,"context_line":"            if _key.startswith(\u0027x-amz-meta-\u0027):"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_e84542b5","line":624,"updated":"2020-06-07 16:09:47.000000000","message":"so these headers will be used to set the upload-id in sysmeta if we end up in the code path that creates the manifests","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"80dc7d47af25a21b2be6f0843f33d42ca5953aff","unresolved":false,"context_lines":[{"line_number":648,"context_line":"        manifest \u003d []"},{"line_number":649,"context_line":"        previous_number \u003d 0"},{"line_number":650,"context_line":"        try:"},{"line_number":651,"context_line":"            xml \u003d req.xml(MAX_COMPLETE_UPLOAD_BODY_SIZE)"},{"line_number":652,"context_line":"            if not xml:"},{"line_number":653,"context_line":"                raise InvalidRequest(msg\u003d\u0027You must specify at least one part\u0027)"},{"line_number":654,"context_line":"            if \u0027content-md5\u0027 in req.headers:"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_28157a9c","line":651,"updated":"2020-06-07 16:09:47.000000000","message":"cool so we do all the same validation of the request regardless","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"80dc7d47af25a21b2be6f0843f33d42ca5953aff","unresolved":false,"context_lines":[{"line_number":680,"context_line":"                    \u0027path\u0027: \u0027/%s/%s/%s/%d\u0027 % ("},{"line_number":681,"context_line":"                        container, req.object_name, upload_id, part_number),"},{"line_number":682,"context_line":"                    \u0027etag\u0027: etag})"},{"line_number":683,"context_line":"                s3_etag_hasher.update(binascii.a2b_hex(etag))"},{"line_number":684,"context_line":"        except (XMLSyntaxError, DocumentInvalid):"},{"line_number":685,"context_line":"            # NB: our schema definitions catch uploads with no parts here"},{"line_number":686,"context_line":"            raise MalformedXML()"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_081876d0","line":683,"updated":"2020-06-07 16:09:47.000000000","message":"and this is how we validate the manifest s3etag later","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"80dc7d47af25a21b2be6f0843f33d42ca5953aff","unresolved":false,"context_lines":[{"line_number":692,"context_line":""},{"line_number":693,"context_line":"        s3_etag \u003d \u0027%s-%d\u0027 % (s3_etag_hasher.hexdigest(), len(manifest))"},{"line_number":694,"context_line":"        s3_etag_header \u003d sysmeta_header(\u0027object\u0027, \u0027etag\u0027)"},{"line_number":695,"context_line":"        if resp.sysmeta_headers.get(s3_etag_header) \u003d\u003d s3_etag:"},{"line_number":696,"context_line":"            # This header should only already be present if the upload marker"},{"line_number":697,"context_line":"            # has been cleaned up and the current target uses the same"},{"line_number":698,"context_line":"            # upload-id; assuming the segments to use haven\u0027t changed, the work"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_883ac630","line":695,"updated":"2020-06-07 16:09:47.000000000","message":"so the idea here is *this* resp came form the manifest (the NoSuchKey path) not the upload-id marker in the normal case","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"80dc7d47af25a21b2be6f0843f33d42ca5953aff","unresolved":false,"context_lines":[{"line_number":697,"context_line":"            # has been cleaned up and the current target uses the same"},{"line_number":698,"context_line":"            # upload-id; assuming the segments to use haven\u0027t changed, the work"},{"line_number":699,"context_line":"            # is already done"},{"line_number":700,"context_line":"            return HTTPOk(body\u003d_make_complete_body(req, s3_etag, False),"},{"line_number":701,"context_line":"                          content_type\u003d\u0027application/xml\u0027)"},{"line_number":702,"context_line":"        headers[s3_etag_header] \u003d s3_etag"},{"line_number":703,"context_line":"        # Leave base header value blank; SLO will populate"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_e81ee2b8","line":700,"updated":"2020-06-07 16:09:47.000000000","message":"since this early response doesn\u0027t do validation it\u0027s always quick and doesn\u0027t have to yield whitespace and won\u0027t ever want the trailing newline.","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"80dc7d47af25a21b2be6f0843f33d42ca5953aff","unresolved":false,"context_lines":[{"line_number":748,"context_line":"                                if not yielded_anything:"},{"line_number":749,"context_line":"                                    yield (b\u0027\u003c?xml version\u003d\"1.0\" \u0027"},{"line_number":750,"context_line":"                                           b\u0027encoding\u003d\"UTF-8\"?\u003e\\n\u0027)"},{"line_number":751,"context_line":"                                yielded_anything \u003d True"},{"line_number":752,"context_line":"                                yield chunk"},{"line_number":753,"context_line":"                                continue"},{"line_number":754,"context_line":"                            body.append(chunk)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_8823e604","line":751,"updated":"2020-06-07 16:09:47.000000000","message":"i can\u0027t exactly see how different the response bodies are in the (not yielded anything) case and when this takes more than 10s","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"521e53797a60de94115b94c10ab0c14fbb9b577a","unresolved":false,"context_lines":[{"line_number":748,"context_line":"                                if not yielded_anything:"},{"line_number":749,"context_line":"                                    yield (b\u0027\u003c?xml version\u003d\"1.0\" \u0027"},{"line_number":750,"context_line":"                                           b\u0027encoding\u003d\"UTF-8\"?\u003e\\n\u0027)"},{"line_number":751,"context_line":"                                yielded_anything \u003d True"},{"line_number":752,"context_line":"                                yield chunk"},{"line_number":753,"context_line":"                                continue"},{"line_number":754,"context_line":"                            body.append(chunk)"}],"source_content_type":"text/x-python","patch_set":2,"id":"ff570b3c_5097a9ec","line":751,"in_reply_to":"ff570b3c_8823e604","updated":"2020-06-08 17:52:58.000000000","message":"With (not yielded_anything), you get\n\n xml declaration\n newline\n s3api response xml\n\nbut when the response takes longer, you get\n\n xml declaration\n newline\n whitespace yielded out from SLO\n newline\n s3api response xml\n\nThe extra newline is mainly for readability when doing this from curl or the like, similar to what we do in bulk with to_yield and separator: https://github.com/openstack/swift/blob/2.25.0/swift/common/middleware/bulk.py#L545-L549","commit_id":"17003aa508cb490f5a51f11a86a9ae80d6fb177f"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"9995a186ffc93f956764da5ea80dd3759aea70f3","unresolved":false,"context_lines":[{"line_number":575,"context_line":"        upload_id \u003d req.params[\u0027uploadId\u0027]"},{"line_number":576,"context_line":"        _get_upload_info(req, self.app, upload_id)"},{"line_number":577,"context_line":""},{"line_number":578,"context_line":"        # First check to see if this multi-part upload was already"},{"line_number":579,"context_line":"        # completed.  Look in the primary container, if the object exists,"},{"line_number":580,"context_line":"        # then it was completed and we return an error here."},{"line_number":581,"context_line":"        container \u003d req.container_name + MULTIUPLOAD_SUFFIX"},{"line_number":582,"context_line":"        obj \u003d \u0027%s/%s\u0027 % (req.object_name, upload_id)"},{"line_number":583,"context_line":"        req.get_response(self.app, container\u003dcontainer, obj\u003dobj)"}],"source_content_type":"text/x-python","patch_set":3,"id":"ff570b3c_9ff8024a","line":580,"range":{"start_line":578,"start_character":10,"end_line":580,"end_character":60},"updated":"2020-06-10 17:15:55.000000000","message":"Off-topic: these comments are lying.","commit_id":"1b8f08a409f85c6072728ff062383334db02c9ca"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"9995a186ffc93f956764da5ea80dd3759aea70f3","unresolved":false,"context_lines":[{"line_number":582,"context_line":"        obj \u003d \u0027%s/%s\u0027 % (req.object_name, upload_id)"},{"line_number":583,"context_line":"        req.get_response(self.app, container\u003dcontainer, obj\u003dobj)"},{"line_number":584,"context_line":""},{"line_number":585,"context_line":"        # The completed object was not found so this"},{"line_number":586,"context_line":"        # must be a multipart upload abort."},{"line_number":587,"context_line":"        # We must delete any uploaded segments for this UploadID and then"},{"line_number":588,"context_line":"        # delete the object in the main container as well"},{"line_number":589,"context_line":"        query \u003d {"}],"source_content_type":"text/x-python","patch_set":3,"id":"ff570b3c_1fed128b","line":586,"range":{"start_line":585,"start_character":10,"end_line":586,"end_character":43},"updated":"2020-06-10 17:15:55.000000000","message":"Here, too.","commit_id":"1b8f08a409f85c6072728ff062383334db02c9ca"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"9995a186ffc93f956764da5ea80dd3759aea70f3","unresolved":false,"context_lines":[{"line_number":778,"context_line":"                try:"},{"line_number":779,"context_line":"                    req.get_response(self.app, \u0027DELETE\u0027, container, obj)"},{"line_number":780,"context_line":"                except NoSuchKey:"},{"line_number":781,"context_line":"                    # We know that this existed long enough for us to HEAD"},{"line_number":782,"context_line":"                    pass"},{"line_number":783,"context_line":""},{"line_number":784,"context_line":"                yield _make_complete_body(req, s3_etag, yielded_anything)"}],"source_content_type":"text/x-python","patch_set":3,"id":"ff570b3c_36ac91ed","line":781,"updated":"2020-06-10 17:15:55.000000000","message":"Oh yeah, this comment is out of date now... I maybe *should* update this one in this patch.","commit_id":"1b8f08a409f85c6072728ff062383334db02c9ca"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"00dcaffed7e2ab73fcebaec3d46649d4d068dd3c","unresolved":false,"context_lines":[{"line_number":779,"context_line":"                    req.get_response(self.app, \u0027DELETE\u0027, container, obj)"},{"line_number":780,"context_line":"                except NoSuchKey:"},{"line_number":781,"context_line":"                    # We know that this existed long enough for us to HEAD"},{"line_number":782,"context_line":"                    pass"},{"line_number":783,"context_line":""},{"line_number":784,"context_line":"                yield _make_complete_body(req, s3_etag, yielded_anything)"},{"line_number":785,"context_line":"            except ErrorResponse as err_resp:"}],"source_content_type":"text/x-python","patch_set":3,"id":"ff570b3c_f1219cfe","line":782,"updated":"2020-06-08 23:53:31.000000000","message":"this is about the earliest you can introduce an error\n\nI think this is mostly fine since even if a client timesout a request (because it\u0027s not properly reading whitespace) it\u0027ll keep retrying with backoff and eventually the server will finish the original request and cleanup the marker\n\n... then the next POST will \"just work\"","commit_id":"1b8f08a409f85c6072728ff062383334db02c9ca"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":117,"context_line":""},{"line_number":118,"context_line":"def _check_upload_info(req, app, upload_id):"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    _get_upload_info(req, app, upload_id)"},{"line_number":121,"context_line":""},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"class PartController(Controller):"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_25ce7259","side":"PARENT","line":120,"updated":"2020-06-25 15:12:36.000000000","message":"so instead of a return None wrapper called check we just use _get and ignore the return","commit_id":"a47d5a11521f0aca5aab4cdfc48a9a4be3eb4ead"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":114,"context_line":"                    \u0027object\u0027, \u0027upload-id\u0027)) \u003d\u003d upload_id:"},{"line_number":115,"context_line":"                return resp"},{"line_number":116,"context_line":"        except NoSuchKey:"},{"line_number":117,"context_line":"            pass"},{"line_number":118,"context_line":"        raise NoSuchUpload(upload_id\u003dupload_id)"},{"line_number":119,"context_line":"    finally:"},{"line_number":120,"context_line":"        # ...making sure to restore any copy-source before returning"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_256af218","line":117,"updated":"2020-06-25 15:12:36.000000000","message":"this is really the money, if I pull out the \"extra HEAD + check upload-id\" all the tests break great!","commit_id":"02548717acb4b59d3fdc90fa32097d1eac00a3a6"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":184,"context_line":"                                  err_msg)"},{"line_number":185,"context_line":""},{"line_number":186,"context_line":"        upload_id \u003d req.params[\u0027uploadId\u0027]"},{"line_number":187,"context_line":"        _get_upload_info(req, self.app, upload_id)"},{"line_number":188,"context_line":""},{"line_number":189,"context_line":"        req.container_name +\u003d MULTIUPLOAD_SUFFIX"},{"line_number":190,"context_line":"        req.object_name \u003d \u0027%s/%s/%d\u0027 % (req.object_name, upload_id,"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_e5b3dae7","line":187,"updated":"2020-06-25 15:12:36.000000000","message":"so but... this *can* still raise error various s3api exceptions - _check_upload_info didn\u0027t seem like such a bad name?","commit_id":"02548717acb4b59d3fdc90fa32097d1eac00a3a6"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":611,"context_line":"        Handles Complete Multipart Upload."},{"line_number":612,"context_line":"        \"\"\""},{"line_number":613,"context_line":"        upload_id \u003d req.params[\u0027uploadId\u0027]"},{"line_number":614,"context_line":"        resp \u003d _get_upload_info(req, self.app, upload_id)"},{"line_number":615,"context_line":"        headers \u003d {\u0027Accept\u0027: \u0027application/json\u0027,"},{"line_number":616,"context_line":"                   sysmeta_header(\u0027object\u0027, \u0027upload-id\u0027): upload_id}"},{"line_number":617,"context_line":"        for key, val in resp.headers.items():"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_a5bd62b8","line":614,"updated":"2020-06-25 15:12:36.000000000","message":"so only POST really needs the resp","commit_id":"02548717acb4b59d3fdc90fa32097d1eac00a3a6"}],"swift/common/middleware/s3api/utils.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":122,"context_line":""},{"line_number":123,"context_line":"    @classmethod"},{"line_number":124,"context_line":"    def now(cls):"},{"line_number":125,"context_line":"        return cls(time.time())"},{"line_number":126,"context_line":""},{"line_number":127,"context_line":""},{"line_number":128,"context_line":"def mktime(timestamp_str, time_format\u003d\u0027%Y-%m-%dT%H:%M:%S\u0027):"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_05b52eee","side":"PARENT","line":125,"updated":"2020-06-25 15:12:36.000000000","message":"i guess this just shadows the utils.Timestamp impl, which is even kinda better...","commit_id":"a47d5a11521f0aca5aab4cdfc48a9a4be3eb4ead"}],"test/functional/s3api/test_multi_upload.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"ba8664148a2c7377c96a50d3e2d3661e83a23f94","unresolved":false,"context_lines":[{"line_number":327,"context_line":"        swift_etag \u003d \u0027\"%s\"\u0027 % md5(concatted_etags).hexdigest()"},{"line_number":328,"context_line":"        # TODO: GET via swift api, check against swift_etag"},{"line_number":329,"context_line":""},{"line_number":330,"context_line":"        if tf.cluster_info[\u0027s3api\u0027].get(\u0027completed_grace_period\u0027, 0) \u003e 10:"},{"line_number":331,"context_line":"            # Should be safe to retry"},{"line_number":332,"context_line":"            status, headers, body \u003d \\"},{"line_number":333,"context_line":"                self._complete_multi_upload(bucket, key, upload_id, xml)"}],"source_content_type":"text/x-python","patch_set":4,"id":"bf51134e_8b6a1a17","line":330,"updated":"2020-06-23 16:05:01.000000000","message":"I can\u0027t find where this gets set in my greps?","commit_id":"008d720f1abb4f379e301d0073560c4fee41fa19"}],"test/unit/common/middleware/s3api/test_multi_upload.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":849,"context_line":"        content_md5 \u003d base64.b64encode(hashlib.md5("},{"line_number":850,"context_line":"            XML.encode(\u0027ascii\u0027)).digest())"},{"line_number":851,"context_line":"        self.swift.register(\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X\u0027,"},{"line_number":852,"context_line":"                            swob.HTTPNotFound, {}, None)"},{"line_number":853,"context_line":"        recent_ts \u003d S3Timestamp.now(delta\u003d-1000000).internal  # 10s ago"},{"line_number":854,"context_line":"        self.swift.register(\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket/object\u0027,"},{"line_number":855,"context_line":"                            swob.HTTPOk,"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_25f7928d","line":852,"updated":"2020-06-25 15:12:36.000000000","message":"yeah see you later marker!","commit_id":"02548717acb4b59d3fdc90fa32097d1eac00a3a6"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":885,"context_line":"            XML.encode(\u0027ascii\u0027)).digest())"},{"line_number":886,"context_line":"        self.swift.register(\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket+segments/object/X\u0027,"},{"line_number":887,"context_line":"                            swob.HTTPNotFound, {}, None)"},{"line_number":888,"context_line":"        recent_ts \u003d S3Timestamp.now(delta\u003d-1000000).internal"},{"line_number":889,"context_line":"        self.swift.register(\u0027HEAD\u0027, \u0027/v1/AUTH_test/bucket/object\u0027,"},{"line_number":890,"context_line":"                            swob.HTTPOk,"},{"line_number":891,"context_line":"                            {\u0027x-object-meta-foo\u0027: \u0027bar\u0027,"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_65c34a58","line":888,"updated":"2020-06-25 15:12:36.000000000","message":"yeah, delta\u003d - but there\u0027s not really a behavior difference based on the age anymore","commit_id":"02548717acb4b59d3fdc90fa32097d1eac00a3a6"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":903,"context_line":"        elem \u003d fromstring(body, \u0027CompleteMultipartUploadResult\u0027)"},{"line_number":904,"context_line":"        self.assertNotIn(\u0027Etag\u0027, headers)"},{"line_number":905,"context_line":"        self.assertEqual(elem.find(\u0027ETag\u0027).text, S3_ETAG)"},{"line_number":906,"context_line":"        self.assertEqual(status.split()[0], \u0027200\u0027)"},{"line_number":907,"context_line":""},{"line_number":908,"context_line":"        self.assertEqual(self.swift.calls, ["},{"line_number":909,"context_line":"            # Bucket exists"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_85477ebc","line":906,"updated":"2020-06-25 15:12:36.000000000","message":"does this make sense?  etag mismatch is still 200?","commit_id":"02548717acb4b59d3fdc90fa32097d1eac00a3a6"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c6c07de448d5a0ae4690ef8437ddc29e7d996dba","unresolved":false,"context_lines":[{"line_number":903,"context_line":"        elem \u003d fromstring(body, \u0027CompleteMultipartUploadResult\u0027)"},{"line_number":904,"context_line":"        self.assertNotIn(\u0027Etag\u0027, headers)"},{"line_number":905,"context_line":"        self.assertEqual(elem.find(\u0027ETag\u0027).text, S3_ETAG)"},{"line_number":906,"context_line":"        self.assertEqual(status.split()[0], \u0027200\u0027)"},{"line_number":907,"context_line":""},{"line_number":908,"context_line":"        self.assertEqual(self.swift.calls, ["},{"line_number":909,"context_line":"            # Bucket exists"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_c06e72fe","line":906,"in_reply_to":"bf51134e_85477ebc","updated":"2020-06-26 16:14:28.000000000","message":"Yes, because we do the PUT and lay down a new manifest.","commit_id":"02548717acb4b59d3fdc90fa32097d1eac00a3a6"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"05a16c1fbefd8488dc927821c8cbf6c605a1d8ff","unresolved":false,"context_lines":[{"line_number":950,"context_line":"        status, headers, body \u003d self.call_s3api(req)"},{"line_number":951,"context_line":"        elem \u003d fromstring(body, \u0027Error\u0027)"},{"line_number":952,"context_line":"        self.assertEqual(elem.find(\u0027Code\u0027).text, \u0027NoSuchUpload\u0027)"},{"line_number":953,"context_line":"        self.assertEqual(status.split()[0], \u0027404\u0027)"},{"line_number":954,"context_line":""},{"line_number":955,"context_line":"        self.assertEqual(self.swift.calls, ["},{"line_number":956,"context_line":"            # Bucket exists"}],"source_content_type":"text/x-python","patch_set":5,"id":"bf51134e_e50f5a85","line":953,"updated":"2020-06-25 15:12:36.000000000","message":"this seems reasonable, i\u0027ve had two uploads going in s3 for the same key and last-write-wins; but I didn\u0027t try complete the looser after the fact!","commit_id":"02548717acb4b59d3fdc90fa32097d1eac00a3a6"}]}
