Commits

Anonymous committed 4f5298d

Repository.create_commit supports message encoding

Now the 'Repository.create_commit' method expects one more argument,
the message encoding. If 'None', it defaults to UTF-8.

Comments (0)

Files changed (2)

 }
 
 char *
-py_str_to_c_str(PyObject *value)
+py_str_to_c_str(PyObject *value, const char *encoding)
 {
     char *c_str;
 
 
     /* Case 2: text string */
     if (PyUnicode_Check(value)) {
-        value = PyUnicode_AsUTF8String(value);
+        if (encoding == NULL)
+            value = PyUnicode_AsUTF8String(value);
+        else
+            value = PyUnicode_AsEncodedString(value, encoding, "strict");
         if (value == NULL)
             return NULL;
         c_str = PyString_AsString(value);
                          signature->when.time, signature->when.offset);
 }
 
-static int
-signature_converter(PyObject *value, git_signature **signature)
+static git_signature *
+py_signature_to_git_signature(PyObject *value, const char* encoding)
 {
     PyObject *py_name;
     char *name, *email;
     long long time;
     int offset;
     int err;
+    git_signature *signature;
 
     if (!PyArg_ParseTuple(value, "OsLi", &py_name, &email, &time, &offset))
-        return 0;
+        return NULL;
 
-    name = py_str_to_c_str(py_name);
+    name = py_str_to_c_str(py_name, encoding);
 
-    err = git_signature_new(signature, name, email, time, offset);
+    err = git_signature_new(&signature, name, email, time, offset);
     if (err < 0) {
         Error_set(err);
-        return 0;
+        return NULL;
     }
 
-    return 1;
+    return signature;
 }
 
 static PyObject *
 static PyObject *
 Repository_create_commit(Repository *self, PyObject *args)
 {
+    PyObject *py_author, *py_committer;
+    PyObject *py_oid, *py_message, *py_parents, *py_parent;
     git_signature *author, *committer;
-    char *message, *update_ref;
+    char *message, *update_ref, *encoding;
     git_oid oid;
     git_tree *tree;
-    PyObject *py_oid, *py_message, *py_parents, *py_parent;
     int parent_count;
     git_commit **parents;
     int err, i;
     size_t len;
 
-    if (!PyArg_ParseTuple(args, "zO&O&OOO!",
+    if (!PyArg_ParseTuple(args, "zO!O!zOOO!",
                           &update_ref,
-                          signature_converter, &author,
-                          signature_converter, &committer,
+                          &PyTuple_Type, &py_author,
+                          &PyTuple_Type, &py_committer,
+                          &encoding,
                           &py_message,
                           &py_oid,
                           &PyList_Type, &py_parents))
         return NULL;
 
+    author = py_signature_to_git_signature(py_author, encoding);
+    if (author == NULL)
+        return NULL;
+    committer = py_signature_to_git_signature(py_committer, encoding);
+    if (committer == NULL)
+        return NULL;
+
     len = py_str_to_git_oid(py_oid, &oid);
     if (len == 0)
         return NULL;
 
-    message = py_str_to_c_str(py_message);
+    message = py_str_to_c_str(py_message, encoding);
 
     err = git_tree_lookup_prefix(&tree, self->repo, &oid, (unsigned int)len);
     if (err < 0)
     }
 
     err = git_commit_create(&oid, self->repo, update_ref, author, committer,
-        NULL, message, tree, parent_count, (const git_commit**)parents);
+        encoding, message, tree, parent_count, (const git_commit**)parents);
     git_tree_close(tree);
     free_parents(parents, parent_count);
     if (err < 0)
 static PyObject *
 Repository_create_tag(Repository *self, PyObject *args)
 {
-    PyObject *py_oid;
+    PyObject *py_oid, *py_tagger;
     char *tag_name, *message;
     git_signature *tagger;
     git_oid oid;
     char hex[GIT_OID_HEXSZ + 1];
     size_t len;
 
-    if (!PyArg_ParseTuple(args, "sOiO&s",
+    if (!PyArg_ParseTuple(args, "sOiO!s",
                           &tag_name,
                           &py_oid,
                           &target_type,
-                          signature_converter, &tagger,
+                          &PyTuple_Type, &py_tagger,
                           &message))
         return NULL;
 
+    tagger = py_signature_to_git_signature(py_tagger, NULL);
+    if (tagger == NULL)
+        return NULL;
+
     len = py_str_to_git_oid(py_oid, &oid);
     if (len == 0)
         return NULL;
     int err;
 
     /* 1- Get the C name */
-    c_name = py_str_to_c_str(py_name);
+    c_name = py_str_to_c_str(py_name, NULL);
     if (c_name == NULL)
         return NULL;
 
     if (encoding == NULL)
         Py_RETURN_NONE;
 
-    return PyString_FromString(encoding);
+    return PyUnicode_DecodeASCII(encoding, strlen(encoding), "strict");
 }
 
 static PyObject *
 {
     char *name;
 
-    name = py_str_to_c_str(py_name);
+    name = py_str_to_c_str(py_name, NULL);
     if (name == NULL)
         return -1;
 
         return Tree_getitem_by_index(self, value);
 
     /* Case 2: byte or text string */
-    name = py_str_to_c_str(value);
+    name = py_str_to_c_str(value, NULL);
     if (name == NULL)
         return NULL;
     entry = git_tree_entry_byname(self->tree, name);
     }
 
     /* Case 2: byte or text string */
-    path = py_str_to_c_str(value);
+    path = py_str_to_c_str(value, NULL);
     if (!path)
         return -1;
     idx = git_index_find(self->index, path);
     char *path;
     int idx;
 
-    path = py_str_to_c_str(value);
+    path = py_str_to_c_str(value, NULL);
     if (!path)
         return -1;
     idx = git_index_find(self->index, path);
     int err;
 
     /* 1- Get the C name */
-    c_name = py_str_to_c_str(py_name);
+    c_name = py_str_to_c_str(py_name, NULL);
     if (c_name == NULL)
         return NULL;
 
     int err;
 
     /* 1- Get the C name */
-    c_name = py_str_to_c_str(py_name);
+    c_name = py_str_to_c_str(py_name, NULL);
     if (c_name == NULL)
         return -1;
 

test/test_commit.py

         self.assertEqual('c2792cfa289ae6321ecf2cd5806c2194b0fd070c',
                          parents[0].hex)
         self.assertEqual(None, commit.message_encoding)
-        #self.assertEqual('Second test data commit.', commit.message_short)
         self.assertEqual(('Second test data commit.\n\n'
                           'This commit has some additional text.\n'),
                          commit.message)
 
         parents = [COMMIT_SHA[:5]]
         self.assertRaises(ValueError, repo.create_commit, None, author,
-                          committer, message, too_short_prefix, parents)
-        
-        sha = repo.create_commit(None, author, committer, message,
+                          committer, None, message, too_short_prefix, parents)
+
+        sha = repo.create_commit(None, author, committer, None, message,
                                  tree_prefix, parents)
         commit = repo[sha]
 
                          commit.hex)
         self.assertEqual(None, commit.message_encoding)
         self.assertEqual(message, commit.message)
-        #self.assertEqual('New commit.', commit.message_short)
+        self.assertEqual(12346, commit.commit_time)
+        self.assertEqual(committer, commit.committer)
+        self.assertEqual(author, commit.author)
+        self.assertEqual(tree, commit.tree.hex)
+        self.assertEqual(1, len(commit.parents))
+        self.assertEqual(COMMIT_SHA, commit.parents[0].hex)
+
+    def test_new_commit_encoding(self):
+        repo = self.repo
+        message = 'New commit.\n\nMessage with non-ascii chars: ééé.\n'
+        committer = ('John Doe', 'jdoe@example.com', 12346, 0)
+        author = ('J. David Ibáñez', 'jdavid@example.com', 12345, 0)
+        tree = '967fce8df97cc71722d3c2a5930ef3e6f1d27b12'
+        tree_prefix = tree[:5]
+
+        parents = [COMMIT_SHA[:5]]
+        sha = repo.create_commit(None, author, committer, 'iso-8859-1',
+                                 message, tree_prefix, parents)
+        commit = repo[sha]
+
+        self.assertEqual(GIT_OBJ_COMMIT, commit.type)
+        self.assertEqual('iso-8859-1', commit.message_encoding)
+        self.assertEqual(message, commit.message)
         self.assertEqual(12346, commit.commit_time)
         self.assertEqual(committer, commit.committer)
         self.assertEqual(author, commit.author)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.