Pisanie pierwszej poprawki do Django

Wprowadzenie

Jesteś zainteresowany odwdzięczeniem się odrobinę społeczności? Może znalazłeś błąd w Django, który chciałbyś, by był rozwiązany, lub jest jakaś mała funkcjonalność, którą chciałbyś, by była dodana.

Pomoc w rozwoju Django jest najlepszym sposobem na rozwiązanie napotkanych przez Ciebie problemów. Na początku może to wydawać się zniechęcające, ale tak naprawdę jest całkiem proste. Przeprowadzimy Cię przez cały proces na przykładzie, abyś mógł się nauczyć tego w praktyce.

Dla kogo jest ten tutorial?

Zobacz także

Jeśli szukasz informacji jak zgłaszać poprawki, obejrzyj dokumentację Submitting patches.

Na potrzeby tego tutorialu oczekujemy posiadanie co najmniej podstawowego rozumienia, jak działa Django. To znaczy, że czytelnik powinien być już obeznany z istniejącymi tutorialami na temat pisania jego pierwszej aplikacji Django. Dodatkowo, powinien dobrze rozumieć samego Pythona. W przypadku jeśli tak nie jest, Dive Into Python jest fantastyczną (i darmową) książką online dla początkujących programistów Pythona.

Ci z was, którzy nie są zaznajomieni z systemami kontroli wersji i Trakiem przekonają się, że w tym poradniku i jego odnośnikach znajdą wystarczająco informacji, aby zacząć pracę. Pomimo tego, prawdopodobnie będziecie potrzebować przeczytać nieco więcej o tych różnych narzędziach, jeśli planujecie regularnie współtworzyć Django.

Celem tego poradnika w głównej mierze jest wytłumaczenie wszystkiego najdokładniej jak to możliwe, aby mógł być on używany przez szerokie grono odbiorców.

Gdzie szukać pomocy:

Jeśli masz problemy z przejściem tego samouczka, prosimy napisz wiadomość do django-developers lub wpadnij na #django-dev na irc.freenode.net, aby czatować z innymi użytkownikami Django, którzy mogą być w stanie udzielić ci pomocy.

Co zawiera ten przewodnik?

Przeprowadzimy cię przez pierwsze tworzenie poprawki do Django. Pod koniec tego tutoriala, powinieneś(nnaś) rozumieć podstawy zarówno narzędzi jak i wykorzystanych procesów. W szczególności poruszymy następujące tematy:

  • Instalacja Gita.
  • Pobieranie kopii wersji rozwojowej Django
  • Uruchamianie zestawu testów Django.
  • Pisanie testu dla twojej poprawki.
  • Pisanie kodu dla twojej poprawki.
  • Testowanie twojej poprawki.
  • Wysyłanie prośby o pull.
  • Gdzie szukać więcej informacji.

Kiedy tutorial jest już za tobą, możesz przejrzeć resztę Django’s documentation on contributing. Zawiera ona wiele dobrych informacji i jest lekturą obowiązkową dla każdego, kto chciałby zostać stałym współtwórcą Django. Jeśli masz pytania, tam prawdopodobnie są odpowiedzi.

Wymagany Python 3!

Bieżąca wersja Django nie wspiera Pythona 2.7. Pobierz Pythona 3 ze strony pobrań Pythona lub za pomocą menadżera pakietów swojego systemu operacyjnego.

Dla użytkowników Windows

Instalując Pythona na Windowsie upewnij się, że zaznaczyłeś opcję „Add python.exe to Path”, aby zawsze był dostępny z linii komend.

Kodeks Postępowania

Jako współtwórca możesz pomóc nam utrzymać społeczność Django otwartą i zintegrowaną. Przeczytaj i postępuj zgodnie z naszym Kodeksem Postępowania.

Instalacja Git’a

Do tego poradnika będziesz potrzebował mieć zainstalowanego Gita, aby pobrać aktualną wersję rozwojową Django i wygenerować pliki poprawek dla zmian, które dokonasz.

Aby sprawdzić, czy posiadasz zainstalowanego Gita, wpisz git w wiersz poleceń. Jeśli otrzymasz informację, że taka komenda nie została znaleziona, będziesz musiał go pobrać i zainstalować. Zobacz stronę pobierania Gita.

Jeśli nie jesteś zaznajomiony z Gitem, możesz zawsze znaleźć więcej informacji na temat komend (kiedy Git jest zainstalowany) wpisując git help w wiersz poleceń.

Uzyskiwanie kopii wersji rozwojowej Django

Pierwszym krokiem do współtworzenia Django jest uzyskanie kopii kodu źródłowego. Najpierw rozwidlij Django na GitHubie. Następnie użyj polecenia cd w linii poleceń, aby przejść do katalogu, gdzie będziesz chciał trzymać swoją lokalną kopię Django.

Pobierz repozytorium kodu źródłowego Django używając poniższego polecenia:

$ git clone https://github.com/YourGitHubName/django.git
...\> git clone https://github.com/YourGitHubName/django.git

Połączenie o niskiej przepustowości?

Możesz dodać argument --depth 1 do git clone, aby ominąć pobieranie całej historii commitów Django, co zmniejsza transfer danych z ~250 MB do ~70 MB.

Kiedy już masz lokalną kopię Django, możesz go zainstalować tak jak zainstalowałbyś dowolny pakiet za pomocą pipa. Najwygodniejszym sposobem, aby to zrobić, jest użycie środowiska wirtualnego, które jest funkcjonalnością wbudowaną w Pythona, która pozwala ci trzymać oddzielny katalog zainstalowanych pakietów dla każdego z twoich projektów, aby nie wchodziły ze sobą w konflikt.

Dobrą praktyką jest przechowywanie wszystkich swoich wirtualnych środowisk w jednym miejscu, na przykład w .virtualenvs/ w Twoim katalogu domowym.

Stwórz nowe środowisko wirtualne uruchamiając:

$ python3 -m venv ~/.virtualenvs/djangodev
...\> py -m venv %HOMEPATH%\.virtualenvs\djangodev

Ścieżką jest miejsce gdzie nowe środowisko zostanie zapisane na Twoim komputerze:

Ostatnim krokiem w procesie konfigurowania twojego środowiska wirtualnego jest jego aktywacja:

$ source ~/.virtualenvs/djangodev/bin/activate

Jeśli komenda source nie jest dostępna, możesz spróbować zamiast niej użyć kropki:

$ . ~/.virtualenvs/djangodev/bin/activate

Dla użytkowników Windows

Aby aktywować swoje środowisko wirtualne w systemie Windows, uruchom:

...\> %HOMEPATH%\.virtualenvs\djangodev\Scripts\activate.bat

Musisz aktywować swoje środowisko wirtualne zawsze, kiedy otwierasz nowe okno terminala. virtualenvwrapper jest przydatnym narzędziem ułatwiającym ten proces.

Nazwa obecnie aktywnego środowiska wirtualnego jest wyświetlana w linii komend, aby pomóc śledzić, którego środowiska używasz. Cokolwiek, co zainstalujesz pipem, gdy ta nazwa się wyświetla, zostanie zainstalowane w tym wirtualnym środowisku, wyizolowane od innych środowisk i pakietów systemowych.

Śmiało, zainstaluj wcześniej sklonowaną kopię Django:

$ pip install -e /path/to/your/local/clone/django/
...\> pip install -e \path\to\your\local\clone\django\

The installed version of Django is now pointing at your local copy by installing in editable mode. You will immediately see any changes you make to it, which is of great help when writing your first patch.

Creating projects with a local copy of Django

It may be helpful to test your local changes with a Django project. First you have to create a new virtual environment, install the previously cloned local copy of Django in editable mode, and create a new Django project outside of your local copy of Django. You will immediately see any changes you make to Django in your new project, which is of great help when writing your first patch.

Uruchomienie zestawu testów Django po raz pierwszy

Dając wkład w kod Django, bardzo ważne jest, aby twoje zmiany nie wprowadzały błędów w innych obszarach Django. Jednym ze sposobów, aby sprawdzić, czy Django nadal działa po twoich zmianach jest uruchomienie zestawu testów Django. Jeśli wszystkie testy nadal przechodzą, wtedy masz podstawy, by sądzić, że twoje zmiany działają i nie popsuły innych części Django. Jeśli nigdy wcześniej nie uruchamiałeś zestawu testów Django, dobrym pomysłem jest uprzednio uruchomienie ich raz po to, abyś zaznajomił się z ich efektem.

Przed uruchomieniem modułu testów zainstaluj jego zależności wchodząc cd do katalogu tests/ Django a następnie uruchamiając:

$ pip install -r requirements/py3.txt
...\> pip install -r requirements\py3.txt

Jeśli napotkasz błąd w trakcie instalacji, może to oznaczać, że w twoim systemie brakuje zależności dla jednego lub więcej pythonowych pakietów. Sprawdź dokumentację pakietów, które zgłaszają błąd lub przeszukaj sieć z komunikatem błędu, który napotkałeś.

Jesteśmy gotowi do uruchomienia zestawu testów. Jeśli używasz GNU/Linuksa, macOS-a lub innego rodzaju Uniksa, uruchom:

$ ./runtests.py
...\> runtests.py 

Teraz usiądź i odpręż się. Cały zestaw testów Django ma ich tysiące a ich wykonywanie może zająć co najmniej kilka minut, w zależności od szybkości twojego komputera.

Kiedy uruchomisz zestaw testów Django, zobaczysz strumień znaków oznaczających status każdego testu po jego zakończeniu. E oznacza, że został zgłoszony błąd podczas testu, F oznacza, że asercje testu nie zostały spełnione. Obie z nich są traktowane jako porażki testów. Jednocześnie x i s oznaczają kolejno spodziewane porażki i ominięte testy. Kropki oznaczają pomyślne przechodzenie testu.

Testy omijane są zazwyczaj z powodu brakujących zewnętrznych bibliotek wymaganych do uruchomienia testu; zobacz Running all the tests, aby obejrzeć listę zależności i upewnij się, że zainstalowałeś te, które są związane ze zmianami, które wprowadzasz (nie będziemy potrzebować żadnej w tym tutorialu). Niektóre testy są właściwe dla wybranego back-endu bazodanowego i zostaną ominięte, jeśli test nie odbywa się z tym back-endem. Aby uruchomić testy z użyciem innego back-endu, sprawdź Using another settings module.

Kiedy testy się skończą, powinieneś zobaczyć komunikat informujący, czy zestaw testów udał się czy odniósł porażkę. Nie zrobiłeś żadnych zmian w kodzie Django, więc cały zestaw testów powinien się udać. Jeśli otrzymujesz porażki lub błędy upewnij się, że poprzednie kroki wykonałeś odpowiednio. Zobacz więcej informacji w Running the unit tests.

Zwróć uwagę, że najnowsza wersja mastera Django może nie zawsze być stabilna. Kiedy dewelopujesz z użyciem mastera, możesz sprawdzić Django’s continous integration builds, aby zweryfikować czy porażki są specyficzne dla twojej maszyny czy są również obecne w oficjalnych buildach Django. Jeśli klikniesz, aby zobaczyć poszczególny build, możesz zobaczyć „Configuration Matrix”, która pokazuje porażki uzyskane w poszczególnych wersjach Pythona i bazodanowego backendu.

Informacja

Na potrzeby tego tutorialu i zgłoszenia, nad którym pracujemy, testowanie z użyciem SQLite wystarczy, chociaż jest możliwe (i czasem niezbędne), aby uruchomić testy używając innej bazy danych.

Praca nad funkcjonalnością

Na potrzeby tego tutoriala będziemy pracowali nad „sztucznym zgłoszeniem” jako studium przypadku. Tutaj są fikcyjne szczegóły:

Zgłoszenie #99999 – Umożliwić tworzenie toastów

Django powinno zawierać funkcję django.shortcuts.make_toast(), która zwraca 'toast'.

Teraz zaimplementujemy tę funkcjonalność i związane z nią testy.

Tworzenie brancha dla swojego patcha

Przed wprowadzeniem jakichkolwiek zmian, stwórz nowy branch dla zgłoszenia:

$ git checkout -b ticket_99999
...\> git checkout -b ticket_99999

Możesz wybrać dowolną nazwę dla brancha, na przykład „ticket_99999”. Wszystkie zmiany zrobione w tym branchu będą specyficzne dla zgłoszenia i nie wpłyną na główną kopię kodu, którą wcześniej sklonowaliśmy.

Pisanie testów do twojego zgłoszenia

W większości przypadków, aby poprawka została wcielona do Django, musi zawierać testy. Dla poprawek błędów znaczy to napisanie testu regresyjnego, aby upewnić się, że bug nie zostanie wprowadzony z powrotem w przyszłości. Test regresyjny powinien zostać napisany w taki sposób, aby nie przechodził jeśli bug nadal istnieje i aby przechodził wtedy, kiedy bug zostanie naprawiony. Dla poprawek zawierających nowe funkcjonalności, musisz załączyć testy, które pozwolą się upewnić, że ta nowa funkcja działa poprawnie. One też powinny nie przechodzić kiedy nie ma nowej funkcji i przechodzić wtedy, kiedy zostanie ona zaimplementowana.

Dobrym sposobem na to jest napisanie twoich testów najpierw, przed jakimikolwiek zmianami w kodzie. Taki styl pracy jest nazywany test-driven development i może być zastosowany zarówno do całych projektów jak i pojedynczych poprawek. Po napisaniu testów możesz je uruchomić, aby upewnić się, że nie przechodzą (bo przecież nie naprawiłeś tego błędu lub nie dodałeś tej funkcjonalności). Jeśli twoje nowe testy przechodzą pomyślnie, musisz poprawić je, aby nie przechodziły. Koniec końców test regresyjny, który przechodzi pomyślnie niezależnie od obecności buga w kodzie, nie pomoże za bardzo w ochronie przed pojawieniem się go w przyszłości.

Pora na nasz praktyczny przykład.

Pisanie testu do zgłoszenia #99999

Aby rozwiązać to zgłoszenie, dodamy funkcję make_toast() do modułu django najwyższego poziomu. Najpierw dodamy test, który próbuje użyć funkcji i sprawdza, że jej wynik wygląda poprawnie.

Przejdź do folderu tests/shortcuts Django i stwórz nowy plik test_make_toast.py. Dodaj następujący kod:

from django.shortcuts import make_toast
from django.test import SimpleTestCase


class MakeToastTests(SimpleTestCase):
    def test_make_toast(self):
        self.assertEqual(make_toast(), 'toast')

Ten test sprawdza, że make_toast() zwraca 'toast'.

Ale to całe testowanie wygląda na dość ciężkie…

Jeśli nie miałeś nigdy wcześniej do czynienia z testami, mogą wyglądać na trochę trudne do pisania na pierwszy rzut oka. Na szczęście testowanie jest bardzo dużym tematem w programowaniu komputerów, więc można znaleźć na jego temat wiele informacji:

  • Dobry artykuł na początek o pisaniu testów do Django można znaleźć w dokumentacji: Writing and running tests.
  • Dive Into Python (darmowa książka online dla początkujących Python-deweloperów) zawiera świetny wstęp do testów jednostkowych.
  • Po ich przeczytaniu, jeśli chcesz zanurzyć zęby w czymś bardziej mięsistym, jest zawsze dokumentacja unittest Pythona.

Uruchomienie twojego nowego testu

Jako że nie wprowadziliśmy jeszcze żadnych zmian do django.shortcuts, nasz test powinien się nie powieźć. Uruchommy wszystkie testy w folderze shortcuts, aby upewnić się, że tak naprawdę się dzieje. cd-uj do katalogu tests/ Django i uruchom:

$ ./runtests.py shortcuts
...\> runtests.py shortcuts

Jeśli testy uruchomiły się poprawnie, powinieneś zobaczyć jedną porażkę odpowiadającą metodzie testowej, którą dodaliśmy, z tym błędem:

ImportError: cannot import name 'make_toast' from 'django.shortcuts'

Jeśli wszystkie testy przeszły, wtedy musisz upewnić się, że dodałeś nowy test pokazany powyżej do odpowiedniego folderu i pliku o odpowiedniej nazwie.

Pisanie kodu do twojego zgłoszenia

Następnie dodamy funkcję make_toast().

Przejdź do folderu django/ i otwórz plik shortcuts.py. Na jego końcu dodaj:

def make_toast():
    return 'toast'

Teraz powinniśmy się upewnić, że test, który napisaliśmy wcześniej, przechodzi, abyśmy zobaczyli, czy kod, który dodaliśmy, działa poprawnie. Znów przejdź do katalogu tests/ Django i uruchom:

$ ./runtests.py shortcuts
...\> runtests.py shortcuts

Wszystko powinno przejść. Jeśli nie przeszło, upewnij się, że poprawnie dodałeś funkcję do odpowiedniego pliku.

Uruchamianie zestawu testów Django drugi raz

Kiedy zweryfikowałeś, że twoje poprawki i testy działają poprawnie, dobrym pomysłem jest uruchomić cały zestaw testów Django, aby zweryfikować tylko, czy twoja zmiana nie wprowadziła żadnych bugów w innych obszarach Django.

Aby uruchomić zestaw testów Django w całości, wejdź cd w katalog tests/ Django i uruchom:

$ ./runtests.py
...\> runtests.py 

Pisanie dokumentacji

To nowa funkcjonalność, więc powinna zostać udokumentowana. Otwórz plik docs/topics/http/shortcuts.txt i dodaj co następuje na końcu tego pliku:

``make_toast()``
================

.. versionadded:: 2.2

Returns ``'toast'``.

Jako że ta nowa funkcjonalność będzie w nadchodzącym wydaniu, dodamy ją również do informacji na temat wydania dla następnej wersji Django. Otwórz informacje o wydaniu dla ostatniej wersji w docs/releases/, która w momencie pisania to 2.2.txt. Dodaj notatkę pod nagłówkiem „Minor Features”:

:mod:`django.shortcuts`
~~~~~~~~~~~~~~~~~~~~~~~

* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.

Po więcej informacji na temat pisania dokumentacji, wliczając wyjaśnienie o co chodzi w cząstce versionadded, odsyłamy do Writing documentation. Ta strona zawiera również wyjaśnienie jak zbudować lokalnie kopię dokumentacji, aby móc obejrzeć HTML, który zostanie później wygenerowany.

Podgląd twoich zmian

Teraz jest czas na przejrzenie wszystkich zmian, które wprowadziliśmy w naszym patchu. Aby zestage’ować wszystkie zmiany gotowe do commita, uruchom:

$ git add --all
...\> git add --all

Następnie wyświetl różnice między twoją bieżącą kopią Djang (z twoimi zmianami) i rewizją, którą pierwotnie zcheck-outowałeś wcześniej w tym tutorialu, używając:

$ git diff --cached
...\> git diff --cached

Użyj klawiszy strzałek, aby przesuwać się do góry i w dół.

diff --git a/django/shortcuts.py b/django/shortcuts.py
index 7ab1df0e9d..8dde9e28d9 100644
--- a/django/shortcuts.py
+++ b/django/shortcuts.py
@@ -156,3 +156,7 @@ def resolve_url(to, *args, **kwargs):

     # Finally, fall back and assume it's a URL
     return to
+
+
+def make_toast():
+    return 'toast'
diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt
index 7d85d30c4a..81518187b3 100644
--- a/docs/releases/2.2.txt
+++ b/docs/releases/2.2.txt
@@ -40,6 +40,11 @@ database constraints. Constraints are added to models using the
 Minor features
 --------------

+:mod:`django.shortcuts`
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.
+
 :mod:`django.contrib.admin`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~

diff --git a/docs/topics/http/shortcuts.txt b/docs/topics/http/shortcuts.txt
index 7b3a3a2c00..711bf6bb6d 100644
--- a/docs/topics/http/shortcuts.txt
+++ b/docs/topics/http/shortcuts.txt
@@ -271,3 +271,12 @@ This example is equivalent to::
         my_objects = list(MyModel.objects.filter(published=True))
         if not my_objects:
             raise Http404("No MyModel matches the given query.")
+
+``make_toast()``
+================
+
+.. function:: make_toast()
+
+.. versionadded:: 2.2
+
+Returns ``'toast'``.
diff --git a/tests/shortcuts/test_make_toast.py b/tests/shortcuts/test_make_toast.py
new file mode 100644
index 0000000000..6f4c627b6e
--- /dev/null
+++ b/tests/shortcuts/test_make_toast.py
@@ -0,0 +1,7 @@
+from django.shortcuts import make_toast
+from django.test import SimpleTestCase
+
+
+class MakeToastTests(SimpleTestCase):
+    def test_make_toast(self):
+        self.assertEqual(make_toast(), 'toast')

Kiedy skończysz oglądać patch, kliknij przycisk q, aby wyjść i wrócić do linii komend. Jeśli treść patcha wyglądała w porządku, czas na scommitowanie zmian.

Commitowanie zmian w patchu

Aby scommitować zmiany:

$ git commit
...\> git commit

Powoduje to otwarcie edytora tekstu do wpisania „commit message”. Zrealizuj zalecenia commit message’y i napisz notatkę w ten sposób:

Fixed #99999 -- Added a shortcut function to make toast.

Pushowanie commita i tworzenie pull requesta

Po skomitowaniu patcha, wyślij go do swojego forka na GitHubie (zamień „ticket_99999” z nazwą swojego brancha, jeśli jest inna):

$ git push origin ticket_99999
...\> git push origin ticket_99999

Możesz stworzyć pull request odwiedzając stronę Django na GitHubie. Zobaczysz swój branch pod „Your recently pushed branches”. Kliknij „Compare & pull request” obok niego.

Prosimy nie rób tego z powodu tego tutoriala, ale na następnej stronie, która prezentuje podgląd zmian, kliknąłbyś „Create pull request”.

Następne kroki

Gratulacje, nauczyłeś się tworzyć pull requesty do Django! Szczegóły bardziej zaawansowanych technik, których możesz potrzebować są w Working with Git and GitHub.

Teraz możesz dobrze wykorzystać te umiejętności pomagając ulepszać bazowy kod Django.

Więcej informacji dla nowych kontrybutorów

Zanim za bardzo wsiąkniesz w pisanie patchy Django, jest trochę więcej informacji o dawaniu wkładu, na które prawdopodobnie powinieneś spojrzeć:

  • Powinieneś się upewnić, że przeczytałeś dokumentację Django na temat tworzenia zgłoszeń i wysyłania patchy. Zawiera ona etykietę Traca, jak przypisywać sobie zgłoszenia, oczekiwany styl kodowania w patchach i wiele innych ważnych szczegółów.
  • Ci, którzy mają styczność pierwszy raz z wnoszeniem wkładu do kodu, powinni przeczytać też dokumentację Django dla nowych kontrybutorów. Zawiera wiele dobrych rad dla tych, którzy są nowi w pomaganiu w Django.
  • Dalej, jeśli wciąż jesteś głodny informacji o współtworzeniu, zawsze możesz przejrzeć resztę dokumentacji Django na temat współtorzenia. Zawiera tonę przydatnych informacji i powinna być twoim pierwszym źródłem, odpowiadającym na każde pytanie, które możesz mieć.

Znajdowanie twojego pierwszego prawdziwego zgłoszenia

Kiedy już przejrzałeś trochę z tych informacji, będziesz gotowy iść i znaleźć zgłoszenie, do którego napiszesz patcha. Zwróć szczególną uwagę na zgłoszenia z kryterium „easy pickings”. Te zgłoszenia często są z natury dużo prostsze i są świetne dla pierwszorazowych kontrybutorów. Gdy już będziesz zaznajomiony z wnoszeniem wkładu w Django, możesz iść dalej i pisać patche do trudniejszych i bardziej skomplikowanych zgłoszeń.

Jeśli po prostu już chcesz zacząć (nikt nie będzie cię winił!), spróbuj rzucić okiem na listę łatwych zgłoszeń, które potrzebują patchy i łatwych zgłoszeń, które mają patche potrzebujące poprawy. Jeśli umiesz pisać testy, możesz też spojrzeć na listę łatwych zgłoszeń, które potrzebują testów. Pamiętaj tylko przestrzegać wskazówek dotyczących przypisywania zgłoszeń, o czym było wspomniane w odnośniku do dokumentacji Django na temat przypisywania zgłoszeń i wgrywaniu patchy.

Co dalej po stworzeniu pull requesta?

Po tym, jak ticket ma patcha, musi zostać przejrzany przez drugą parę oczu. Po wysłaniu pull requesta zaktualizuj metadane ticketu ustawiając na tickecie flagi, które mówią „has patch”, „doesn’t need tests” i tak dalej, aby inni mogli go znaleźć do przejrzenia. Wnoszenie wkładu niekoniecznie zawsze znaczy pisanie patcha od zera. Przeglądanie istniejących patchy jest również bardzo pomocnym wkładem. Zobacz Triaging tickets po szczegóły.

Back to Top