Commit 94711cad3b83445dfcf45a6e0b29b045e06a29f6

Carlos Martín Nieto 2011-05-17T12:12:59

Merge upstream/development

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..f90540b
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+*.c eol=lf
+*.h eol=lf
diff --git a/README.md b/README.md
index dae6a76..7cfde59 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ Under Unix-like systems, like Linux, *BSD and Mac OS X, libgit2 expects `pthread
 they should be installed by default on all systems. Under Windows, libgit2 uses the native Windows API
 for threading.
 
-Additionally, he following libraries may be used as replacement for built-in functionality:
+Additionally, the following libraries may be used as replacement for built-in functionality:
 
 * LibSSL **(optional)** <http://www.openssl.org/>
 
@@ -88,6 +88,9 @@ The waf build system for libgit2 accepts the following flags:
 	--with-sqlite
 		Enable sqlite support.
 
+	--with-redis
+		Enable redis support.
+
 You can run `./waf --help` to see a full list of install options and
 targets.
 
diff --git a/include/git2.h b/include/git2.h
index ff55aef..0d0e548 100644
--- a/include/git2.h
+++ b/include/git2.h
@@ -26,9 +26,9 @@
 #ifndef INCLUDE_git_git_h__
 #define INCLUDE_git_git_h__
 
-#define LIBGIT2_VERSION "0.11.0"
+#define LIBGIT2_VERSION "0.12.0"
 #define LIBGIT2_VER_MAJOR 0
-#define LIBGIT2_VER_MINOR 11
+#define LIBGIT2_VER_MINOR 12
 #define LIBGIT2_VER_REVISION 0
 
 #include "git2/common.h"
diff --git a/include/git2/common.h b/include/git2/common.h
index ab267e6..9a27ac2 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -84,92 +84,6 @@
  * @{
  */
 
-/** Operation completed successfully. */
-#define GIT_SUCCESS 0
-
-/**
- * Operation failed, with unspecified reason.
- * This value also serves as the base error code; all other
- * error codes are subtracted from it such that all errors
- * are < 0, in typical POSIX C tradition.
- */
-#define GIT_ERROR -1
-
-/** Input was not a properly formatted Git object id. */
-#define GIT_ENOTOID (GIT_ERROR - 1)
-
-/** Input does not exist in the scope searched. */
-#define GIT_ENOTFOUND (GIT_ERROR - 2)
-
-/** Not enough space available. */
-#define GIT_ENOMEM (GIT_ERROR - 3)
-
-/** Consult the OS error information. */
-#define GIT_EOSERR (GIT_ERROR - 4)
-
-/** The specified object is of invalid type */
-#define GIT_EOBJTYPE (GIT_ERROR - 5)
-
-/** The specified object has its data corrupted */
-#define GIT_EOBJCORRUPTED (GIT_ERROR - 6)
-
-/** The specified repository is invalid */
-#define GIT_ENOTAREPO (GIT_ERROR - 7)
-
-/** The object or config variable type is invalid or doesn't match */
-#define GIT_EINVALIDTYPE (GIT_ERROR - 8)
-
-/** The object cannot be written because it's missing internal data */
-#define GIT_EMISSINGOBJDATA (GIT_ERROR - 9)
-
-/** The packfile for the ODB is corrupted */
-#define GIT_EPACKCORRUPTED (GIT_ERROR - 10)
-
-/** Failed to acquire or release a file lock */
-#define GIT_EFLOCKFAIL (GIT_ERROR - 11)
-
-/** The Z library failed to inflate/deflate an object's data */
-#define GIT_EZLIB (GIT_ERROR - 12)
-
-/** The queried object is currently busy */
-#define GIT_EBUSY (GIT_ERROR - 13)
-
-/** The index file is not backed up by an existing repository */
-#define GIT_EBAREINDEX (GIT_ERROR - 14)
-
-/** The name of the reference is not valid */
-#define GIT_EINVALIDREFNAME (GIT_ERROR - 15)
-
-/** The specified reference has its data corrupted */
-#define GIT_EREFCORRUPTED  (GIT_ERROR - 16)
-
-/** The specified symbolic reference is too deeply nested */
-#define GIT_ETOONESTEDSYMREF (GIT_ERROR - 17)
-
-/** The pack-refs file is either corrupted or its format is not currently supported */
-#define GIT_EPACKEDREFSCORRUPTED (GIT_ERROR - 18)
-
-/** The path is invalid */
-#define GIT_EINVALIDPATH (GIT_ERROR - 19)
-
-/** The revision walker is empty; there are no more commits left to iterate */
-#define GIT_EREVWALKOVER (GIT_ERROR - 20)
-
-/** The state of the reference is not valid */
-#define GIT_EINVALIDREFSTATE (GIT_ERROR - 21)
-
-/** This feature has not been implemented yet */
-#define GIT_ENOTIMPLEMENTED (GIT_ERROR - 22)
-
-/** A reference with this name already exists */
-#define GIT_EEXISTS (GIT_ERROR - 23)
-
-/** The given integer literal is too large to be parsed */
-#define GIT_EOVERFLOW (GIT_ERROR - 24)
-
-/** The given literal is not a valid number */
-#define GIT_ENOTNUM (GIT_ERROR - 25)
-
 GIT_BEGIN_DECL
 
 typedef struct {
diff --git a/include/git2/errors.h b/include/git2/errors.h
index 627e67c..7e957b8 100644
--- a/include/git2/errors.h
+++ b/include/git2/errors.h
@@ -25,6 +25,8 @@
 #ifndef INCLUDE_git_errors_h__
 #define INCLUDE_git_errors_h__
 
+#include "common.h"
+
 /**
  * @file git2/errors.h
  * @brief Git error handling routines and variables
@@ -33,8 +35,106 @@
  */
 GIT_BEGIN_DECL
 
+typedef enum {
+	GIT_SUCCESS = 0,
+	GIT_ERROR = -1,
+
+	/** Input was not a properly formatted Git object id. */
+	GIT_ENOTOID = -2,
+
+	/** Input does not exist in the scope searched. */
+	GIT_ENOTFOUND = -3,
+
+	/** Not enough space available. */
+	GIT_ENOMEM = -4,
+
+	/** Consult the OS error information. */
+	GIT_EOSERR = -5,
+
+	/** The specified object is of invalid type */
+	GIT_EOBJTYPE = -6,
+
+	/** The specified repository is invalid */
+	GIT_ENOTAREPO = -7,
+
+	/** The object type is invalid or doesn't match */
+	GIT_EINVALIDTYPE = -8,
+
+	/** The object cannot be written because it's missing internal data */
+	GIT_EMISSINGOBJDATA = -9,
+
+	/** The packfile for the ODB is corrupted */
+	GIT_EPACKCORRUPTED = -10,
+
+	/** Failed to acquire or release a file lock */
+	GIT_EFLOCKFAIL = -11,
+
+	/** The Z library failed to inflate/deflate an object's data */
+	GIT_EZLIB = -12,
+
+	/** The queried object is currently busy */
+	GIT_EBUSY = -13,
+
+	/** The index file is not backed up by an existing repository */
+	GIT_EBAREINDEX = -14,
+
+	/** The name of the reference is not valid */
+	GIT_EINVALIDREFNAME = -15,
+
+	/** The specified reference has its data corrupted */
+	GIT_EREFCORRUPTED  = -16,
+
+	/** The specified symbolic reference is too deeply nested */
+	GIT_ETOONESTEDSYMREF = -17,
+
+	/** The pack-refs file is either corrupted or its format is not currently supported */
+	GIT_EPACKEDREFSCORRUPTED = -18,
+
+	/** The path is invalid */
+	GIT_EINVALIDPATH = -19,
+
+	/** The revision walker is empty; there are no more commits left to iterate */
+	GIT_EREVWALKOVER = -20,
+
+	/** The state of the reference is not valid */
+	GIT_EINVALIDREFSTATE = -21,
+
+	/** This feature has not been implemented yet */
+	GIT_ENOTIMPLEMENTED = -22,
+
+	/** A reference with this name already exists */
+	GIT_EEXISTS = -23,
+
+	/** The given integer literal is too large to be parsed */
+	GIT_EOVERFLOW = -24,
+
+	/** The given literal is not a valid number */
+	GIT_ENOTNUM = -25,
+
+	/** Streaming error */
+	GIT_ESTREAM = -26,
+
+	/** invalid arguments to function */
+	GIT_EINVALIDARGS = -27,
+
+	/** The specified object has its data corrupted */
+	GIT_EOBJCORRUPTED = -28,
+} git_error;
+
+/**
+ * Return a detailed error string with the latest error
+ * that occurred in the library.
+ * @return a string explaining the error
+ */
+GIT_EXTERN(const char *) git_lasterror(void);
+
 /**
  * strerror() for the Git library
+ *
+ * Get a string description for a given error code.
+ * NOTE: This method will be eventually deprecated in favor
+ * of the new `git_lasterror`.
+ *
  * @param num The error code to explain
  * @return a string explaining the error code
  */
diff --git a/include/git2/index.h b/include/git2/index.h
index 7991de9..2d8975c 100644
--- a/include/git2/index.h
+++ b/include/git2/index.h
@@ -232,10 +232,10 @@ GIT_EXTERN(int) git_index_append(git_index *index, const char *path, int stage);
  * @param source_entry new entry object
  * @return 0 on success, otherwise an error code
  */
-GIT_EXTERN(int) git_index_apppend2(git_index *index, const git_index_entry *source_entry);
+GIT_EXTERN(int) git_index_append2(git_index *index, const git_index_entry *source_entry);
 
 /**
- * Remove an entry from the index 
+ * Remove an entry from the index
  *
  * @param index an existing index object
  * @param position position of the entry to remove
diff --git a/include/git2/thread-utils.h b/include/git2/thread-utils.h
index fb8644b..e26876b 100644
--- a/include/git2/thread-utils.h
+++ b/include/git2/thread-utils.h
@@ -35,6 +35,7 @@
 
 #if defined(__APPLE__) && defined(__MACH__)
 # undef GIT_TLS
+# define GIT_TLS
 
 #elif defined(__GNUC__) || \
       defined(__SUNPRO_C) || \
diff --git a/src/backends/hiredis.c b/src/backends/hiredis.c
index 707412b..2533a16 100644
--- a/src/backends/hiredis.c
+++ b/src/backends/hiredis.c
@@ -53,7 +53,7 @@ int hiredis_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_backe
     reply = redisCommand(backend->db, "HMGET %b %s %s", oid->id, GIT_OID_RAWSZ,
             "type", "size");
 
-    if (reply->type == REDIS_REPLY_ARRAY) {
+    if (reply && reply->type == REDIS_REPLY_ARRAY) {
         if (reply->element[0]->type != REDIS_REPLY_NIL &&
                 reply->element[0]->type != REDIS_REPLY_NIL) {
             *type_p = (git_otype) atoi(reply->element[0]->str);
@@ -83,7 +83,7 @@ int hiredis_backend__read(void **data_p, size_t *len_p, git_otype *type_p, git_o
     reply = redisCommand(backend->db, "HMGET %b %s %s %s", oid->id, GIT_OID_RAWSZ,
             "type", "size", "data");
 
-    if (reply->type == REDIS_REPLY_ARRAY) {
+    if (reply && reply->type == REDIS_REPLY_ARRAY) {
         if (reply->element[0]->type != REDIS_REPLY_NIL &&
                 reply->element[1]->type != REDIS_REPLY_NIL &&
                 reply->element[2]->type != REDIS_REPLY_NIL) {
@@ -118,7 +118,7 @@ int hiredis_backend__exists(git_odb_backend *_backend, const git_oid *oid) {
     found = 0;
 
     reply = redisCommand(backend->db, "exists %b", oid->id, GIT_OID_RAWSZ);
-    if (reply->type != REDIS_REPLY_NIL && reply->type != REDIS_REPLY_ERROR)
+    if (reply && reply->type != REDIS_REPLY_NIL && reply->type != REDIS_REPLY_ERROR)
         found = 1;
 
 
@@ -144,7 +144,8 @@ int hiredis_backend__write(git_oid *id, git_odb_backend *_backend, const void *d
             "size %d "
             "data %b ", id->id, GIT_OID_RAWSZ,
             (int) type, len, data, len);
-    error = reply->type == REDIS_REPLY_ERROR ? GIT_ERROR : GIT_SUCCESS;
+
+    error = (reply == NULL || reply->type == REDIS_REPLY_ERROR) ? GIT_ERROR : GIT_SUCCESS;
 
     freeReplyObject(reply);
     return error;
diff --git a/src/blob.c b/src/blob.c
index 5e3c22f..9871693 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -62,7 +62,7 @@ int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *b
 	git_odb_stream *stream;
 
 	if ((error = git_odb_open_wstream(&stream, repo->db, len, GIT_OBJ_BLOB)) < GIT_SUCCESS)
-		return error;
+		return git__rethrow(error, "Failed to create blob. Can't open write stream");
 
 	stream->write(stream, buffer, len);
 
@@ -81,7 +81,7 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
 	git_odb_stream *stream;
 
 	if (repo->path_workdir == NULL)
-		return GIT_ENOTFOUND;
+		return git__throw(GIT_ENOTFOUND, "Failed to create blob. No workdir given");
 
 	git__joinpath(full_path, repo->path_workdir, path);
 
@@ -106,7 +106,7 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat
 		if (read_len < 0) {
 			gitfo_close(fd);
 			stream->free(stream);
-			return GIT_EOSERR;
+			return git__throw(GIT_EOSERR, "Failed to create blob. Can't read full file");
 		}
 
 		stream->write(stream, buffer, read_len);
diff --git a/src/cache.c b/src/cache.c
index fd42e2c..433fc3d 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -29,10 +29,7 @@
 #include "thread-utils.h"
 #include "cache.h"
 
-#define GIT_CACHE_OPENADR 3
-
-
-void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr)
+int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr)
 {
 	size_t i;
 
@@ -52,12 +49,15 @@ void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_p
 	cache->free_obj = free_ptr;
 
 	cache->nodes = git__malloc((size + 1) * sizeof(cache_node));
+	if (cache->nodes == NULL)
+		return GIT_ENOMEM;
 
 	for (i = 0; i < (size + 1); ++i) {
 		git_mutex_init(&cache->nodes[i].lock);
 		cache->nodes[i].ptr = NULL;
-		cache->nodes[i].lru = 0;
 	}
+
+	return GIT_SUCCESS;
 }
 
 void git_cache_free(git_cache *cache)
@@ -77,85 +77,53 @@ void git_cache_free(git_cache *cache)
 void *git_cache_get(git_cache *cache, const git_oid *oid)
 {
 	const uint32_t *hash;
-	size_t i, pos, found = 0;
 	cache_node *node = NULL;
+	void *result = NULL;
 
 	hash = (const uint32_t *)oid->id;
+	node = &cache->nodes[hash[0] & cache->size_mask];
 
-	for (i = 0; !found && i < GIT_CACHE_OPENADR; ++i) {
-		pos = hash[i] & cache->size_mask;
-		node = &cache->nodes[pos];
-
-		git_mutex_lock(&node->lock);
-		{
-			if (node->ptr && git_cached_obj_compare(node->ptr, oid) == 0) {
-				git_cached_obj_incref(node->ptr);
-				node->lru = ++cache->lru_count;
-				found = 1;
-			}
+	git_mutex_lock(&node->lock);
+	{
+		if (node->ptr && git_cached_obj_compare(node->ptr, oid) == 0) {
+			git_cached_obj_incref(node->ptr);
+			result = node->ptr;
 		}
-		git_mutex_unlock(&node->lock);
 	}
+	git_mutex_unlock(&node->lock);
 
-
-	return found ? node->ptr : NULL;
+	return result;
 }
 
 void *git_cache_try_store(git_cache *cache, void *entry)
 {
-	cache_node *nodes[GIT_CACHE_OPENADR], *lru_node;
 	const uint32_t *hash;
 	const git_oid *oid;
-	size_t i;
+	cache_node *node = NULL;
 
 	oid = &((git_cached_obj*)entry)->oid;
 	hash = (const uint32_t *)oid->id;
+	node = &cache->nodes[hash[0] & cache->size_mask];
 
 	/* increase the refcount on this object, because
 	 * the cache now owns it */
 	git_cached_obj_incref(entry);
-
-	for (i = 0; i < GIT_CACHE_OPENADR; ++i) {
-		size_t pos = hash[i] & cache->size_mask;
-
-		nodes[i] = &cache->nodes[pos];
-		git_mutex_lock(&nodes[i]->lock);
-	}
-
-	lru_node = nodes[0];
-
-	for (i = 0; i < GIT_CACHE_OPENADR; ++i) {
-
-		if (nodes[i]->ptr == NULL) {
-			nodes[i]->ptr = entry;
-			nodes[i]->lru = ++cache->lru_count;
-			break;
-		} else if (git_cached_obj_compare(nodes[i]->ptr, oid) == 0) {
-			git_cached_obj_decref(entry, cache->free_obj);
-			entry = nodes[i]->ptr;
-			nodes[i]->lru = ++cache->lru_count;
-			break;
-		}
-
-		if (nodes[i]->lru < lru_node->lru)
-			lru_node = nodes[i];
-	}
-
-	if (i == GIT_CACHE_OPENADR) {
-		void *old_entry = lru_node->ptr;
-		assert(old_entry);
-
-		git_cached_obj_decref(old_entry, cache->free_obj);
-		lru_node->ptr = entry;
-		lru_node->lru = ++cache->lru_count;
+	git_mutex_lock(&node->lock);
+
+	if (node->ptr == NULL) {
+		node->ptr = entry;
+	} else if (git_cached_obj_compare(node->ptr, oid) == 0) {
+		git_cached_obj_decref(entry, cache->free_obj);
+		entry = node->ptr;
+	} else {
+		git_cached_obj_decref(node->ptr, cache->free_obj);
+		node->ptr = entry;
 	}
 
 	/* increase the refcount again, because we are
 	 * returning it to the user */
 	git_cached_obj_incref(entry);
-
-	for (i = 0; i < GIT_CACHE_OPENADR; ++i)
-		git_mutex_unlock(&nodes[i]->lock);
+	git_mutex_unlock(&node->lock);
 
 	return entry;
 }
diff --git a/src/cache.h b/src/cache.h
index 975aaff..4794dea 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -19,7 +19,6 @@ typedef struct {
 typedef struct {
 	git_cached_obj *ptr;
 	git_mutex lock;
-	unsigned int lru;
 } cache_node;
 
 typedef struct {
@@ -31,7 +30,7 @@ typedef struct {
 } git_cache;
 
 
-void git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr);
+int git_cache_init(git_cache *cache, size_t size, git_cached_obj_freeptr free_ptr);
 void git_cache_free(git_cache *cache);
 
 void *git_cache_try_store(git_cache *cache, void *entry);
diff --git a/src/commit.c b/src/commit.c
index 0c37ec5..54d7a47 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -286,7 +286,7 @@ int commit_parse_buffer(git_commit *commit, const void *data, size_t len)
 
 	if (buffer < buffer_end) {
 		const char *line_end;
-		size_t message_len = buffer_end - buffer;
+		size_t message_len;
 
 		/* Long message */
 		message_len = buffer_end - buffer;
diff --git a/src/common.h b/src/common.h
index 5ad878e..f4f11fd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -50,10 +50,14 @@ typedef SSIZE_T ssize_t;
 
 #include "git2/common.h"
 #include "git2/types.h"
-#include "util.h"
+#include "git2/errors.h"
 #include "thread-utils.h"
 #include "bswap.h"
 
 #define GIT_PATH_MAX 4096
+extern int git__throw(int error, const char *, ...) GIT_FORMAT_PRINTF(2, 3);
+extern int git__rethrow(int error, const char *, ...) GIT_FORMAT_PRINTF(2, 3);
+
+#include "util.h"
 
 #endif /* INCLUDE_common_h__ */
diff --git a/src/errors.c b/src/errors.c
index 1ef2baa..1fb68ee 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -1,6 +1,35 @@
+/*
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2,
+ * as published by the Free Software Foundation.
+ *
+ * In addition to the permissions in the GNU General Public License,
+ * the authors give you unlimited permission to link the compiled
+ * version of this file into combinations with other programs,
+ * and to distribute those combinations without any restriction
+ * coming from the use of this file.  (The General Public License
+ * restrictions do apply in other respects; for example, they cover
+ * modification of the file, and distribution when not linked into
+ * a combined executable.)
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
 #include "common.h"
+#include "git2/thread-utils.h" /* for GIT_TLS */
 #include "thread-utils.h" /* for GIT_TLS */
 
+#include <stdarg.h>
+
+static GIT_TLS char g_last_error[1024];
+
 static struct {
 	int num;
 	const char *str;
@@ -46,3 +75,38 @@ const char *git_strerror(int num)
 
 	return "Unknown error";
 }
+
+int git__rethrow(int error, const char *msg, ...)
+{
+	char new_error[1024];
+	char *old_error = NULL;
+
+	va_list va;
+
+	va_start(va, msg);
+	vsnprintf(new_error, sizeof(new_error), msg, va);
+	va_end(va);
+
+	old_error = strdup(g_last_error);
+	snprintf(g_last_error, sizeof(g_last_error), "%s \n    - %s", new_error, old_error);
+	free(old_error);
+
+	return error;
+}
+
+int git__throw(int error, const char *msg, ...)
+{
+	va_list va;
+
+	va_start(va, msg);
+	vsnprintf(g_last_error, sizeof(g_last_error), msg, va);
+	va_end(va);
+
+	return error;
+}
+
+const char *git_lasterror(void)
+{
+	return g_last_error;
+}
+
diff --git a/src/fileops.c b/src/fileops.c
index 5dd4a38..45dd8f4 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -10,7 +10,7 @@ int gitfo_mkdir_2file(const char *file_path)
 
 	error = git__dirname_r(target_folder_path, sizeof(target_folder_path), file_path);
 	if (error < GIT_SUCCESS)
-		return error;
+		return git__throw(GIT_EINVALIDPATH, "Failed to recursively build `%s` tree structure. Unable to parse parent folder name", file_path);
 
 	/* Does the containing folder exist? */
 	if (gitfo_isdir(target_folder_path)) {
@@ -19,7 +19,7 @@ int gitfo_mkdir_2file(const char *file_path)
 		/* Let's create the tree structure */
 		error = gitfo_mkdir_recurs(target_folder_path, mode);
 		if (error < GIT_SUCCESS)
-			return error;
+			return error;	/* The callee already takes care of setting the correct error message. */
 	}
 
 	return GIT_SUCCESS;
@@ -164,19 +164,19 @@ int gitfo_read_file(gitfo_buf *obj, const char *path)
 
 	if (((size = gitfo_size(fd)) < 0) || !git__is_sizet(size+1)) {
 		gitfo_close(fd);
-		return GIT_ERROR;
+		return git__throw(GIT_ERROR, "Failed to read file `%s`. Either an error occured while calculating its size or the file is too large", path);
 	}
 	len = (size_t) size;
 
 	if ((buff = git__malloc(len + 1)) == NULL) {
 		gitfo_close(fd);
-		return GIT_ERROR;
+		return GIT_ENOMEM;
 	}
 
 	if (gitfo_read(fd, buff, len) < 0) {
 		gitfo_close(fd);
 		free(buff);
-		return GIT_ERROR;
+		return git__throw(GIT_ERROR, "Failed to read file `%s`", path);
 	}
 	buff[len] = '\0';
 
@@ -197,13 +197,15 @@ void gitfo_free_buf(gitfo_buf *obj)
 
 int gitfo_mv(const char *from, const char *to)
 {
+	int error;
+
 #ifdef GIT_WIN32
 	/*
 	 * Win32 POSIX compilance my ass. If the destination
 	 * file exists, the `rename` call fails. This is as
 	 * close as it gets with the Win32 API.
 	 */
-	return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
+	error = MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR;
 #else
 	/* Don't even try this on Win32 */
 	if (!link(from, to)) {
@@ -214,16 +216,21 @@ int gitfo_mv(const char *from, const char *to)
 	if (!rename(from, to))
 		return GIT_SUCCESS;
 
-	return GIT_EOSERR;
+	error = GIT_EOSERR;
 #endif
+
+	if (error < GIT_SUCCESS)
+		return git__throw(error, "Failed to move file from `%s`to `%s`", from, to);
+
+	return GIT_SUCCESS;
 }
 
 int gitfo_mv_force(const char *from, const char *to)
 {
 	if (gitfo_mkdir_2file(to) < GIT_SUCCESS)
-		return GIT_EOSERR;
+		return GIT_EOSERR;	/* The callee already takes care of setting the correct error message. */
 
-	return gitfo_mv(from, to);
+	return gitfo_mv(from, to);	/* The callee already takes care of setting the correct error message. */
 }
 
 int gitfo_map_ro(git_map *out, git_file fd, git_off_t begin, size_t len)
@@ -338,7 +345,7 @@ int gitfo_dirent(
 	struct dirent *de;
 
 	if (!wd_len || path_sz < wd_len + 2)
-		return GIT_ERROR;
+		return git__throw(GIT_EINVALIDARGS, "Failed to process `%s` tree structure. Path is either empty or buffer size is too short", path);
 
 	while (path[wd_len - 1] == '/')
 		wd_len--;
@@ -347,7 +354,7 @@ int gitfo_dirent(
 
 	dir = opendir(path);
 	if (!dir)
-		return GIT_EOSERR;
+		return git__throw(GIT_EOSERR, "Failed to process `%s` tree structure. An error occured while opening the directory", path);
 
 	while ((de = readdir(dir)) != NULL) {
 		size_t de_len;
@@ -364,14 +371,14 @@ int gitfo_dirent(
 		de_len = strlen(de->d_name);
 		if (path_sz < wd_len + de_len + 1) {
 			closedir(dir);
-			return GIT_ERROR;
+			return git__throw(GIT_ERROR, "Failed to process `%s` tree structure. Buffer size is too short", path);
 		}
 
 		strcpy(path + wd_len, de->d_name);
 		result = fn(arg, path);
 		if (result < GIT_SUCCESS) {
 			closedir(dir);
-			return result;
+			return result;	/* The callee is reponsible for setting the correct error message */
 		}
 		if (result > 0) {
 			closedir(dir);
@@ -399,7 +406,7 @@ int retrieve_path_root_offset(const char *path)
 	if (*(path + offset) == '/')
 		return offset;
 
-	return GIT_ERROR;
+	return -1;	/* Not a real error. Rather a signal than the path is not rooted */
 }
 
 
@@ -438,7 +445,11 @@ int gitfo_mkdir_recurs(const char *path, int mode)
 		error = gitfo_mkdir(path, mode);
 
 	free(path_copy);
-	return error;
+
+	if (error < GIT_SUCCESS)
+		return git__throw(error, "Failed to recursively create `%s` tree structure", path);
+
+	return GIT_SUCCESS;
 }
 
 static int retrieve_previous_path_component_start(const char *path)
@@ -484,7 +495,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path)
 	if (root_path_offset < 0) {
 		error = gitfo_getcwd(buffer_out, size);
 		if (error < GIT_SUCCESS)
-			return error;
+			return error;	/* The callee already takes care of setting the correct error message. */
 
 		len = strlen(buffer_out);
 		buffer_out += len;
@@ -529,7 +540,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path)
 
 			/* Are we escaping out of the root dir? */
 			if (len < 0)
-				return GIT_EINVALIDPATH;
+				return git__throw(GIT_EINVALIDPATH, "Failed to normalize path `%s`. The path escapes out of the root directory", path);
 
 			buffer_out = (char *)buffer_out_start + len;
 			continue;
@@ -537,7 +548,7 @@ int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path)
 
 		/* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */
 		if (only_dots && segment_len > 0)
-			return GIT_EINVALIDPATH;
+			return git__throw(GIT_EINVALIDPATH, "Failed to normalize path `%s`. The path contains a segment with three `.` or more", path);
 
 		*buffer_out++ = '/';
 		len++;
@@ -557,21 +568,21 @@ int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path)
 
 	/* Let's make sure the filename isn't empty nor a dot */
 	if (path_len == 0 || (path_len == 1 && *path == '.'))
-		return GIT_EINVALIDPATH;
+		return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path is either empty or equals `.`", path);
 
 	/* Let's make sure the filename doesn't end with "/", "/." or "/.." */
 	for (i = 1; path_len > i && i < 4; i++) {
 		if (!strncmp(path + path_len - i, pattern, i))
-			return GIT_EINVALIDPATH;
+			return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path);
 	}
 
 	error =  gitfo_prettify_dir_path(buffer_out, size, path);
 	if (error < GIT_SUCCESS)
-		return error;
+		return error;	/* The callee already takes care of setting the correct error message. */
 
 	path_len = strlen(buffer_out);
-	if (path_len < 2)
-		return GIT_EINVALIDPATH;
+	if (path_len < 2)	/* TODO: Fixme. We should also take of detecting Windows rooted path (probably through usage of retrieve_path_root_offset) */
+		return git__throw(GIT_EINVALIDPATH, "Failed to normalize file path `%s`. The path points to a folder", path);
 
 	/* Remove the trailing slash */
 	buffer_out[path_len - 1] = '\0';
@@ -616,11 +627,11 @@ int gitfo_getcwd(char *buffer_out, size_t size)
 #ifdef GIT_WIN32
 	cwd_buffer = _getcwd(buffer_out, size);
 #else
-	cwd_buffer = getcwd(buffer_out, size); //TODO: Fixme. Ensure the required headers are correctly included
+	cwd_buffer = getcwd(buffer_out, size);
 #endif
 
 	if (cwd_buffer == NULL)
-		return GIT_EOSERR;
+		return git__throw(GIT_EOSERR, "Failed to retrieve current working directory");
 
 	posixify_path(buffer_out);
 
diff --git a/src/index.c b/src/index.c
index 130d1fd..f643e73 100644
--- a/src/index.c
+++ b/src/index.c
@@ -421,7 +421,7 @@ int git_index_add2(git_index *index, const git_index_entry *source_entry)
 	return index_insert(index, source_entry, 1);
 }
 
-int git_index_apppend2(git_index *index, const git_index_entry *source_entry)
+int git_index_append2(git_index *index, const git_index_entry *source_entry)
 {
 	return index_insert(index, source_entry, 0);
 }
diff --git a/src/odb.c b/src/odb.c
index 43d0ef9..f09b6d7 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -221,7 +221,7 @@ static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend
  *
  ***********************************************************/
 
-int backend_sort_cmp(const void *a, const void *b)
+static int backend_sort_cmp(const void *a, const void *b)
 {
 	const backend_internal *backend_a = *(const backend_internal **)(a);
 	const backend_internal *backend_b = *(const backend_internal **)(b);
@@ -234,15 +234,19 @@ int backend_sort_cmp(const void *a, const void *b)
 
 int git_odb_new(git_odb **out)
 {
+	int error;
+
 	git_odb *db = git__calloc(1, sizeof(*db));
 	if (!db)
 		return GIT_ENOMEM;
 
-	git_cache_init(&db->cache, GIT_DEFAULT_CACHE_SIZE, &free_odb_object);
+	error = git_cache_init(&db->cache, GIT_DEFAULT_CACHE_SIZE, &free_odb_object);
+	if (error < GIT_SUCCESS)
+		return error;
 
-	if (git_vector_init(&db->backends, 4, backend_sort_cmp) < 0) {
+	if ((error = git_vector_init(&db->backends, 4, backend_sort_cmp)) < GIT_SUCCESS) {
 		free(db);
-		return GIT_ENOMEM;
+		return error;
 	}
 
 	*out = db;
@@ -444,7 +448,7 @@ int git_odb_read_header(size_t *len_p, git_otype *type_p, git_odb *db, const git
 			return error;
 
 		*len_p = object->raw.len;
-		*type_p = object->raw.len;
+		*type_p = object->raw.type;
 		git_odb_object_close(object);
 	}
 
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 4f475f2..873dbfa 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -336,7 +336,6 @@ static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
 {
 	unsigned char head[64], *buf;
 	z_stream zs;
-	int z_status;
 	obj_hdr hdr;
 	size_t used;
 
@@ -350,7 +349,7 @@ static int inflate_disk_obj(git_rawobj *out, gitfo_buf *obj)
 	 * inflate the initial part of the io buffer in order
 	 * to parse the object header (type and size).
 	 */
-	if ((z_status = start_inflate(&zs, obj, head, sizeof(head))) < Z_OK)
+	if (start_inflate(&zs, obj, head, sizeof(head)) < Z_OK)
 		return GIT_ERROR;
 
 	if ((used = get_object_header(&hdr, head)) == 0)
diff --git a/src/refs.c b/src/refs.c
index ea96819..c4d3d6a 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -122,7 +122,8 @@ static int reference_create(
 	else if (type == GIT_REF_OID)
 		size = sizeof(reference_oid);
 	else
-		return GIT_EINVALIDREFSTATE;
+		return git__throw(GIT_EINVALIDARGS,
+			"Invalid reference type. Use either GIT_REF_OID or GIT_REF_SYMBOLIC as type specifier");
 
 	reference = git__malloc(size);
 	if (reference == NULL)
@@ -159,11 +160,9 @@ static int reference_read(gitfo_buf *file_content, time_t *mtime, const char *re
 	/* Determine the full path of the file */
 	git__joinpath(path, repo_path, ref_name);
 
-	if (gitfo_stat(path, &st) < 0)
-		return GIT_ENOTFOUND;
-
-	if (S_ISDIR(st.st_mode))
-		return GIT_EOBJCORRUPTED;
+	if (gitfo_stat(path, &st) < 0 || S_ISDIR(st.st_mode))
+		return git__throw(GIT_ENOTFOUND,
+			"Cannot read reference file '%s'", ref_name);
 
 	if (mtime)
 		*mtime = st.st_mtime;
@@ -205,7 +204,8 @@ static int loose_update(git_reference *ref)
 	else if (ref->type == GIT_REF_OID)
 		error = loose_parse_oid(ref, &ref_file);
 	else
-		error = GIT_EINVALIDREFSTATE;
+		error = git__throw(GIT_EOBJCORRUPTED,
+			"Invalid reference type (%d) for loose reference", ref->type);
 
 	gitfo_free_buf(&ref_file);
 
@@ -229,7 +229,8 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
 	ref_sym = (reference_symbolic *)ref;
 
 	if (file_content->len < (header_len + 1))
-		return GIT_EREFCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED,
+			"Failed to parse loose reference. Object too short");
 
 	/* 
 	 * Assume we have already checked for the header
@@ -246,7 +247,8 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
 	/* remove newline at the end of file */
 	eol = strchr(ref_sym->target, '\n');
 	if (eol == NULL)
-		return GIT_EREFCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED,
+			"Failed to parse loose reference. Missing EOL");
 
 	*eol = '\0';
 	if (eol[-1] == '\r')
@@ -257,6 +259,7 @@ static int loose_parse_symbolic(git_reference *ref, gitfo_buf *file_content)
 
 static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
 {
+	int error;
 	reference_oid *ref_oid;
 	char *buffer;
 
@@ -265,17 +268,19 @@ static int loose_parse_oid(git_reference *ref, gitfo_buf *file_content)
 
 	/* File format: 40 chars (OID) + newline */
 	if (file_content->len < GIT_OID_HEXSZ + 1)
-		return GIT_EREFCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED,
+			"Failed to parse loose reference. Reference too short");
 
-	if (git_oid_mkstr(&ref_oid->oid, buffer) < GIT_SUCCESS)
-		return GIT_EREFCORRUPTED;
+	if ((error = git_oid_mkstr(&ref_oid->oid, buffer)) < GIT_SUCCESS)
+		return git__rethrow(GIT_EOBJCORRUPTED, "Failed to parse loose reference.");
 
 	buffer = buffer + GIT_OID_HEXSZ;
 	if (*buffer == '\r')
 		buffer++;
 
 	if (*buffer != '\n')
-		return GIT_EREFCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED,
+			"Failed to parse loose reference. Missing EOL");
 
 	return GIT_SUCCESS;
 }
@@ -387,7 +392,7 @@ static int loose_write(git_reference *ref)
 		strcpy(ref_contents, GIT_SYMREF);
 		strcat(ref_contents, ref_sym->target);
 	} else {
-		error = GIT_EINVALIDREFSTATE;
+		error = git__throw(GIT_EOBJCORRUPTED, "Failed to write reference. Invalid reference type");
 		goto unlock;
 	}
 
diff --git a/src/repository.c b/src/repository.c
index 8cc2644..1072b22 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -124,16 +124,16 @@ static int check_repository_dirs(git_repository *repo)
 	char path_aux[GIT_PATH_MAX];
 
 	if (gitfo_isdir(repo->path_repository) < GIT_SUCCESS)
-		return GIT_ENOTAREPO;
+		return git__throw(GIT_ENOTAREPO, "`%s` is not a folder", repo->path_repository);
 
 	/* Ensure GIT_OBJECT_DIRECTORY exists */
 	if (gitfo_isdir(repo->path_odb) < GIT_SUCCESS)
-		return GIT_ENOTAREPO;
+		return git__throw(GIT_ENOTAREPO, "`%s` does not exist", repo->path_odb);
 
 	/* Ensure HEAD file exists */
 	git__joinpath(path_aux, repo->path_repository, GIT_HEAD_FILE);
 	if (gitfo_exists(path_aux) < 0)
-		return GIT_ENOTAREPO;
+		return git__throw(GIT_ENOTAREPO, "HEAD file is missing");
 
 	return GIT_SUCCESS;
 }
@@ -145,12 +145,12 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa
 
 	/* Git directory name */
 	if (git__basename_r(buffer, sizeof(buffer), repository_path) < 0)
-		return GIT_EINVALIDPATH;
+		return git__throw(GIT_EINVALIDPATH, "Unable to parse folder name from `%s`", repository_path);
 
 	if (strcmp(buffer, DOT_GIT) == 0) {
 		/* Path to working dir */
 		if (git__dirname_r(buffer, sizeof(buffer), repository_path) < 0)
-			return GIT_EINVALIDPATH;
+			return git__throw(GIT_EINVALIDPATH, "Unable to parse parent folder name from `%s`", repository_path);
 		path_work_tree = buffer;
 	}
 
@@ -159,13 +159,19 @@ static int guess_repository_dirs(git_repository *repo, const char *repository_pa
 
 static git_repository *repository_alloc()
 {
+	int error;
+
 	git_repository *repo = git__malloc(sizeof(git_repository));
 	if (!repo)
 		return NULL;
 
 	memset(repo, 0x0, sizeof(git_repository));
 
-	git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free);
+	error = git_cache_init(&repo->objects, GIT_DEFAULT_CACHE_SIZE, &git_object__free);
+	if (error < GIT_SUCCESS) {
+		free(repo);
+		return NULL;
+	}
 
 	if (git_repository__refcache_init(&repo->references) < GIT_SUCCESS) {
 		free(repo);
@@ -177,7 +183,7 @@ static git_repository *repository_alloc()
 
 static int init_odb(git_repository *repo)
 {
-	return git_odb_open(&repo->db, repo->path_odb);
+	return git_odb_open(&repo->db, repo->path_odb);	/* TODO: Move odb.c to new error handling */
 }
 
 int git_repository_open3(git_repository **repo_out,
@@ -192,7 +198,7 @@ int git_repository_open3(git_repository **repo_out,
 	assert(repo_out);
 
 	if (object_database == NULL)
-		return GIT_ERROR;
+		return git__throw(GIT_EINVALIDARGS, "Failed to open repository. `object_database` can't be null");
 
 	repo = repository_alloc();
 	if (repo == NULL)
@@ -218,7 +224,7 @@ int git_repository_open3(git_repository **repo_out,
 
 cleanup:
 	git_repository_free(repo);
-	return error;
+	return git__rethrow(error, "Failed to open repository");
 }
 
 
@@ -259,7 +265,7 @@ int git_repository_open2(git_repository **repo_out,
 
 cleanup:
 	git_repository_free(repo);
-	return error;
+	return git__rethrow(error, "Failed to open repository");
 }
 
 int git_repository_open(git_repository **repo_out, const char *path)
@@ -290,7 +296,7 @@ int git_repository_open(git_repository **repo_out, const char *path)
 
 cleanup:
 	git_repository_free(repo);
-	return error;
+	return git__rethrow(error, "Failed to open repository");
 }
 
 void git_repository_free(git_repository *repo)
@@ -322,7 +328,7 @@ int git_repository_index(git_index **index_out, git_repository *repo)
 	assert(index_out && repo);
 
 	if (repo->index == NULL) {
-		error = git_index_open_inrepo(&repo->index, repo);
+		error = git_index_open_inrepo(&repo->index, repo);	/* TODO: move index.c to new error handling */
 		if (error < GIT_SUCCESS)
 			return error;
 
@@ -349,7 +355,7 @@ static int repo_init_reinit(repo_init *results)
 static int repo_init_createhead(git_repository *repo)
 {
 	git_reference *head_reference;
-	return  git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE);
+	return git_reference_create_symbolic(&head_reference, repo, GIT_HEAD_FILE, GIT_REFS_HEADS_MASTER_FILE);	/* TODO: finalize moving refs.c to new error handling */
 }
 
 static int repo_init_check_head_existence(char * repository_path)
@@ -363,6 +369,7 @@ static int repo_init_check_head_existence(char * repository_path)
 static int repo_init_structure(repo_init *results)
 {
 	const int mode = 0755; /* or 0777 ? */
+	int error;
 
 	char temp_path[GIT_PATH_MAX];
 	char *git_dir = results->path_repository;
@@ -372,23 +379,27 @@ static int repo_init_structure(repo_init *results)
 
 	/* Creates the '/objects/info/' directory */
 	git__joinpath(temp_path, git_dir, GIT_OBJECTS_INFO_DIR);
-	if (gitfo_mkdir_recurs(temp_path, mode) < GIT_SUCCESS)
-		return GIT_ERROR;
+	error = gitfo_mkdir_recurs(temp_path, mode);
+	if (error < GIT_SUCCESS)
+		return error;
 
 	/* Creates the '/objects/pack/' directory */
 	git__joinpath(temp_path, git_dir, GIT_OBJECTS_PACK_DIR);
-	if (gitfo_mkdir(temp_path, mode))
-		return GIT_ERROR;
+	error = gitfo_mkdir(temp_path, mode);
+	if (error < GIT_SUCCESS)
+		return git__throw(error, "Unable to create `%s` folder", temp_path);
 
 	/* Creates the '/refs/heads/' directory */
 	git__joinpath(temp_path, git_dir, GIT_REFS_HEADS_DIR);
-	if (gitfo_mkdir_recurs(temp_path, mode))
-		return GIT_ERROR;
+	error = gitfo_mkdir_recurs(temp_path, mode);
+	if (error < GIT_SUCCESS)
+		return error;
 
 	/* Creates the '/refs/tags/' directory */
 	git__joinpath(temp_path, git_dir, GIT_REFS_TAGS_DIR);
-	if (gitfo_mkdir(temp_path, mode))
-		return GIT_ERROR;
+	error = gitfo_mkdir(temp_path, mode);
+	if (error < GIT_SUCCESS)
+		return git__throw(error, "Unable to create `%s` folder", temp_path);
 
 	/* TODO: what's left? templates? */
 
@@ -467,7 +478,7 @@ int git_repository_init(git_repository **repo_out, const char *path, unsigned is
 cleanup:
 	free(results.path_repository);
 	git_repository_free(repo);
-	return error;
+	return git__rethrow(error, "Failed to (re)init the repository `%s`", path);
 }
 
 int git_repository_is_empty(git_repository *repo)
@@ -477,10 +488,10 @@ int git_repository_is_empty(git_repository *repo)
 
 	error = git_reference_lookup(&head, repo, "HEAD");
 	if (error < GIT_SUCCESS)
-		return error;
+		return git__throw(error, "Failed to determine the emptiness of the repository. An error occured while retrieving the HEAD reference");
 
 	if (git_reference_type(head) != GIT_REF_SYMBOLIC)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to determine the emptiness of the repository. HEAD is probably in detached state");
 
 	return git_reference_resolve(&branch, head) == GIT_SUCCESS ? 0 : 1;
 }
diff --git a/src/revwalk.c b/src/revwalk.c
index 7879848..8163851 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -210,7 +210,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
 		git_oid oid;
 
 		if (git_oid_mkstr(&oid, (char *)buffer + STRLEN("parent ")) < GIT_SUCCESS)
-			return GIT_EOBJCORRUPTED;
+			return git__throw(GIT_EOBJCORRUPTED, "Failed to parse commit. Parent object is corrupted");
 
 		commit->parents[i] = commit_lookup(walk, &oid);
 		if (commit->parents[i] == NULL)
@@ -222,14 +222,14 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
 	commit->out_degree = (unsigned short)parents;
 
 	if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse commit. Object is corrupted");
 
 	buffer = memchr(buffer, '>', buffer_end - buffer);
 	if (buffer == NULL)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse commit. Can't find author");
 
 	if (git__strtol32(&commit_time, (char *)buffer + 2, NULL, 10) < GIT_SUCCESS)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse commit. Can't parse commit time");
 
 	commit->time = (time_t)commit_time;
 	commit->parsed = 1;
@@ -245,11 +245,11 @@ static int commit_parse(git_revwalk *walk, commit_object *commit)
 		return GIT_SUCCESS;
 
 	if ((error = git_odb_read(&obj, walk->repo->db, &commit->oid)) < GIT_SUCCESS)
-		return error;
+		return git__rethrow(error, "Failed to parse commit. Can't read object");
 
 	if (obj->raw.type != GIT_OBJ_COMMIT) {
 		git_odb_object_close(obj);
-		return GIT_EOBJTYPE;
+		return git__throw(GIT_EOBJTYPE, "Failed to parse commit. Object is no commit object");
 	}
 
 	error = commit_quick_parse(walk, commit, &obj->raw);
@@ -305,7 +305,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
 
 	commit = commit_lookup(walk, oid);
 	if (commit == NULL)
-		return GIT_ENOTFOUND;
+		return git__throw(GIT_ENOTFOUND, "Failed to push commit. Object not found");
 
 	commit->uninteresting = uninteresting;
 
diff --git a/src/signature.c b/src/signature.c
index e801462..62bd28b 100644
--- a/src/signature.c
+++ b/src/signature.c
@@ -115,22 +115,22 @@ static int parse_timezone_offset(const char *buffer, long *offset_out)
 	}
 
 	if (offset_start[0] != '-' && offset_start[0] != '+')
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. It doesn't start with '+' or '-'");
 
 	if (git__strtol32(&dec_offset, offset_start + 1, &offset_end, 10) < GIT_SUCCESS)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. It isn't a number");
 
 	if (offset_end - offset_start != 5)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Invalid length");
 
 	hours = dec_offset / 100;
 	mins = dec_offset % 100;
 
 	if (hours > 14)	// see http://www.worldtimezone.com/faq.html 
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Hour value too large");;
 
 	if (mins > 59)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Minute value too large");
 
 	offset = (hours * 60) + mins;
 
@@ -157,19 +157,19 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
 
 	line_end = memchr(buffer, '\n', buffer_end - buffer);
 	if (!line_end)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. No newline found");;
 
 	if (buffer + (header_len + 1) > line_end)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short");
 
 	if (memcmp(buffer, header, header_len) != 0)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Expected prefix '%s' doesn't match actual", header);
 
 	buffer += header_len;
 
 	/* Parse name */
 	if ((name_end = memchr(buffer, '<', buffer_end - buffer)) == NULL)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail start");
 
 	name_length = name_end - buffer - 1;
 	sig->name = git__malloc(name_length + 1);
@@ -181,11 +181,11 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
 	buffer = name_end + 1;
 
 	if (buffer >= line_end)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly");
 
 	/* Parse email */
 	if ((email_end = memchr(buffer, '>', buffer_end - buffer)) == NULL)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail end");
 
 	email_length = email_end - buffer;
 	sig->email = git__malloc(email_length + 1);
@@ -197,10 +197,10 @@ int git_signature__parse(git_signature *sig, const char **buffer_out,
 	buffer = email_end + 1;
 
 	if (buffer >= line_end)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly");
 
 	if (git__strtol32(&time, buffer, &buffer, 10) < GIT_SUCCESS)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Timestamp isn't a number");
 
 	sig->when.time = (time_t)time;
 
diff --git a/src/tag.c b/src/tag.c
index 148eb28..849429b 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -90,13 +90,13 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
 	int error;
 
 	if ((error = git__parse_oid(&tag->target, &buffer, buffer_end, "object ")) < 0)
-		return error;
+		return git__rethrow(error, "Failed to parse tag. Object field invalid");
 
 	if (buffer + 5 >= buffer_end)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Object too short");
 
 	if (memcmp(buffer, "type ", 5) != 0)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Type field not found");
 	buffer += 5;
 
 	tag->type = GIT_OBJ_BAD;
@@ -105,7 +105,7 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
 		size_t type_length = strlen(tag_types[i]);
 
 		if (buffer + type_length >= buffer_end)
-			return GIT_EOBJCORRUPTED;
+			return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Object too short");
 
 		if (memcmp(buffer, tag_types[i], type_length) == 0) {
 			tag->type = i;
@@ -115,18 +115,19 @@ static int parse_tag_buffer(git_tag *tag, const char *buffer, const char *buffer
 	}
 
 	if (tag->type == GIT_OBJ_BAD)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Invalid object type");
 
 	if (buffer + 4 >= buffer_end)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Object too short");
 
 	if (memcmp(buffer, "tag ", 4) != 0)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Tag field not found");
+
 	buffer += 4;
 
 	search = memchr(buffer, '\n', buffer_end - buffer);
 	if (search == NULL)
-		return GIT_EOBJCORRUPTED;
+		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tag. Object too short");
 
 	text_len = search - buffer;
 
@@ -218,7 +219,7 @@ static int tag_create(
 	}
 
 	if (!git_odb_exists(repo->db, target))
-		return GIT_ENOTFOUND;
+		return git__throw(GIT_ENOTFOUND, "Failed to create tag. Object to tag doesn't exist");
 
 	/* Try to find out what the type is */
 	if (target_type == GIT_OBJ_ANY) {
diff --git a/src/tree.c b/src/tree.c
index b7daf39..6f9fc86 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -151,15 +151,15 @@ static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buf
 			return GIT_ENOMEM;
 
 		if (git__strtol32((long *)&entry->attr, buffer, &buffer, 8) < GIT_SUCCESS)
-			return GIT_EOBJCORRUPTED;
+			return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Can't parse attributes");
 
 		if (*buffer++ != ' ') {
-			error = GIT_EOBJCORRUPTED;
+			error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Object it corrupted");
 			break;
 		}
 
 		if (memchr(buffer, 0, buffer_end - buffer) == NULL) {
-			error = GIT_EOBJCORRUPTED;
+			error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Object it corrupted");
 			break;
 		}
 
@@ -274,7 +274,7 @@ int git_tree_create_fromindex(git_oid *oid, git_index *index)
 	int error;
 
 	if (index->repository == NULL)
-		return GIT_EBAREINDEX;
+		return git__throw(GIT_EBAREINDEX, "Failed to create tree. The index file is not backed up by an existing repository");
 
 	error = write_index(oid, index, "", 0, 0, git_index_entrycount(index));
 	return (error < GIT_SUCCESS) ? error : GIT_SUCCESS;
@@ -343,7 +343,7 @@ int git_treebuilder_insert(git_tree_entry **entry_out, git_treebuilder *bld, con
 	assert(bld && id && filename);
 
 	if (!valid_attributes(attributes))
-		return GIT_ERROR;
+		return git__throw(GIT_ERROR, "Failed to insert entry. Invalid atrributes");
 
 	if ((pos = git_vector_bsearch2(&bld->entries, entry_search_cmp, filename)) != GIT_ENOTFOUND) {
 		entry = git_vector_get(&bld->entries, pos);
@@ -400,7 +400,7 @@ int git_treebuilder_remove(git_treebuilder *bld, const char *filename)
 	git_tree_entry *remove_ptr = (git_tree_entry *)git_treebuilder_get(bld, filename);
 
 	if (remove_ptr == NULL || remove_ptr->removed)
-		return GIT_ENOTFOUND;
+		return git__throw(GIT_ENOTFOUND, "Failed to remove entry. File isn't in the tree");
 
 	remove_ptr->removed = 1;
 	bld->entry_count--;
@@ -431,7 +431,7 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b
 	}
 
 	if ((error = git_odb_open_wstream(&stream, git_repository_database(repo), size, GIT_OBJ_TREE)) < GIT_SUCCESS)
-		return error;
+		return git__rethrow(error, "Failed to write tree. Can't open write stream");
 
 	for (i = 0; i < bld->entries.length; ++i) {
 		git_tree_entry *entry = bld->entries.contents[i];
diff --git a/src/util.h b/src/util.h
index 3dcdc36..6724e8d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -6,17 +6,41 @@
 #define MSB(x, bits) ((x) & (~0ULL << (bitsizeof(x) - (bits))))
 
 /* 
- * Don't wrap malloc/calloc.
- * Use the default versions in glibc, and make
- * sure that any methods that allocate memory
- * return a GIT_ENOMEM error when allocation
- * fails.
+ * Custom memory allocation wrappers
+ * that set error code and error message
+ * on allocation failure
  */
-#define git__malloc malloc
-#define git__calloc calloc
-#define git__realloc realloc
-#define git__strdup strdup
-#define git__strndup strndup
+GIT_INLINE(void *) git__malloc(size_t len)
+{
+	void *ptr = malloc(len);
+	if (!ptr)
+		git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)len);
+	return ptr;
+}
+
+GIT_INLINE(void *) git__calloc(size_t nelem, size_t elsize)
+{
+	void *ptr = calloc(nelem, elsize);
+	if (!ptr)
+		git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)elsize);
+	return ptr;
+}
+
+GIT_INLINE(char *) git__strdup(const char *str)
+{
+	char *ptr = strdup(str);
+	if (!ptr)
+		git__throw(GIT_ENOMEM, "Out of memory. Failed to duplicate string");
+	return ptr;
+}
+
+GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
+{
+	void *new_ptr = realloc(ptr, size);
+	if (!new_ptr)
+		git__throw(GIT_ENOMEM, "Out of memory. Failed to allocate %d bytes.", (int)size);
+	return new_ptr;
+}
 
 extern int git__fmt(char *, size_t, const char *, ...)
 	GIT_FORMAT_PRINTF(3, 4);
diff --git a/src/vector.c b/src/vector.c
index d0b0c5c..1ddc26e 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -106,7 +106,7 @@ int git_vector_bsearch2(git_vector *v, git_vector_cmp key_lookup, const void *ke
 
 	/* need comparison function to sort the vector */
 	if (v->_cmp == NULL)
-		return GIT_ENOTFOUND;
+		return git__throw(GIT_ENOTFOUND, "Can't sort vector. No comparison function set");
 
 	git_vector_sort(v);
 
@@ -114,7 +114,7 @@ int git_vector_bsearch2(git_vector *v, git_vector_cmp key_lookup, const void *ke
 	if (find != NULL)
 		return (int)(find - v->contents);
 
-	return GIT_ENOTFOUND;
+	return git__throw(GIT_ENOTFOUND, "Can't find element");
 }
 
 int git_vector_search2(git_vector *v, git_vector_cmp key_lookup, const void *key)
@@ -128,7 +128,7 @@ int git_vector_search2(git_vector *v, git_vector_cmp key_lookup, const void *key
 			return i;
 	}
 
-	return GIT_ENOTFOUND;
+	return git__throw(GIT_ENOTFOUND, "Can't find element");
 }
 
 static int strict_comparison(const void *a, const void *b)
@@ -143,9 +143,6 @@ int git_vector_search(git_vector *v, const void *entry)
 
 int git_vector_bsearch(git_vector *v, const void *key)
 {
-	if (v->_cmp == NULL)
-		return GIT_ENOTFOUND;
-
 	return git_vector_bsearch2(v, v->_cmp, key);
 }
 
@@ -156,7 +153,7 @@ int git_vector_remove(git_vector *v, unsigned int idx)
 	assert(v);
 
 	if (idx >= v->length || v->length == 0)
-		return GIT_ENOTFOUND;
+		return git__throw(GIT_ENOTFOUND, "Can't remove element. Index out of bounds");
 
 	for (i = idx; i < v->length - 1; ++i)
 		v->contents[i] = v->contents[i + 1];
diff --git a/src/win32/pthread.c b/src/win32/pthread.c
index f47364a..7e17b6b 100644
--- a/src/win32/pthread.c
+++ b/src/win32/pthread.c
@@ -48,16 +48,15 @@ int pthread_join(pthread_t thread, void **value_ptr)
 int pthread_mutex_init(pthread_mutex_t *GIT_RESTRICT mutex,
                        const pthread_mutexattr_t *GIT_RESTRICT GIT_UNUSED(mutexattr))
 {
-	GIT_UNUSED_ARG(mutexattr);
+    GIT_UNUSED_ARG(mutexattr);
     InitializeCriticalSection(mutex);
     return 0;
 }
 
 int pthread_mutex_destroy(pthread_mutex_t *mutex)
 {
-    int ret;
-    ret = CloseHandle(mutex);
-    return -(!ret);
+    DeleteCriticalSection(mutex);
+    return 0;
 }
 
 int pthread_mutex_lock(pthread_mutex_t *mutex)
diff --git a/tests/t10-refs.c b/tests/t10-refs.c
index db767a1..ee006a8 100644
--- a/tests/t10-refs.c
+++ b/tests/t10-refs.c
@@ -292,7 +292,7 @@ BEGIN_TEST(create2, "create a new OID reference")
 	/* Similar test with a fresh new repository */
 	must_pass(git_repository_open(&repo2, TEMP_REPO_FOLDER));
 
-	must_pass(git_reference_lookup(&looked_up_ref, repo, new_head));
+	must_pass(git_reference_lookup(&looked_up_ref, repo2, new_head));
 	must_be_true(git_oid_cmp(&id, git_reference_oid(looked_up_ref)) == 0);
 
 	close_temp_repo(repo2);